Merge branch 'fix_uri_mess' into 'master'

Fix crashes due to ClassCastException

See merge request pixeldroid/PixelDroid!579
This commit is contained in:
Matthieu 2024-02-25 11:03:55 +00:00
commit 37b83f5ae2
7 changed files with 63 additions and 36 deletions

View File

@ -30,8 +30,8 @@ android {
} }
defaultConfig { defaultConfig {
minSdkVersion 23 minSdkVersion 23
versionCode 30
targetSdkVersion 34 targetSdkVersion 34
versionCode 31
versionName "1.0.beta" + versionCode versionName "1.0.beta" + versionCode
//TODO add resConfigs("en", "fr", "ja",...) ? //TODO add resConfigs("en", "fr", "ja",...) ?

View File

@ -1,5 +1,9 @@
package org.pixeldroid.app.postCreation package org.pixeldroid.app.postCreation
import android.content.ClipData
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.NavHostFragment
@ -15,6 +19,31 @@ class PostCreationActivity : BaseActivity() {
internal const val POST_REDRAFT = "post_redraft" internal const val POST_REDRAFT = "post_redraft"
internal const val POST_NSFW = "post_nsfw" internal const val POST_NSFW = "post_nsfw"
internal const val TEMP_FILES = "temp_files" internal const val TEMP_FILES = "temp_files"
fun intentForUris(context: Context, uris: List<Uri>) =
Intent(Intent.ACTION_SEND_MULTIPLE).apply {
// Pass downloaded images to new post creation activity
putParcelableArrayListExtra(
Intent.EXTRA_STREAM, ArrayList(uris)
)
uris.forEach {
// Why are we using ClipData in addition to parcelableArrayListExtra here?
// Because the FLAG_GRANT_READ_URI_PERMISSION needs to be applied to the URIs, and
// for some reason it doesn't get applied to all of them when not using ClipData
if (clipData == null) {
clipData = ClipData("", emptyArray(), ClipData.Item(it))
} else {
clipData!!.addItem(ClipData.Item(it))
}
}
setClass(context, PostCreationActivity::class.java)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
}
} }
private lateinit var binding: ActivityPostCreationBinding private lateinit var binding: ActivityPostCreationBinding
@ -32,4 +61,5 @@ class PostCreationActivity : BaseActivity() {
} }
override fun onSupportNavigateUp() = navController.navigateUp() || super.onSupportNavigateUp() override fun onSupportNavigateUp() = navController.navigateUp() || super.onSupportNavigateUp()
} }

View File

@ -1,6 +1,6 @@
package org.pixeldroid.app.postCreation package org.pixeldroid.app.postCreation
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Parcelable import android.os.Parcelable
@ -33,10 +33,10 @@ import kotlinx.parcelize.Parcelize
import okhttp3.MultipartBody import okhttp3.MultipartBody
import org.pixeldroid.app.MainActivity import org.pixeldroid.app.MainActivity
import org.pixeldroid.app.R import org.pixeldroid.app.R
import org.pixeldroid.app.postCreation.camera.CameraFragment import org.pixeldroid.app.postCreation.camera.CameraFragment
import org.pixeldroid.app.utils.api.objects.Attachment import org.pixeldroid.app.utils.api.objects.Attachment
import org.pixeldroid.app.utils.db.AppDatabase import org.pixeldroid.app.utils.db.AppDatabase
import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
import org.pixeldroid.app.utils.di.PixelfedAPIHolder import org.pixeldroid.app.utils.di.PixelfedAPIHolder
import org.pixeldroid.app.utils.fileExtension import org.pixeldroid.app.utils.fileExtension
import org.pixeldroid.app.utils.getMimeType import org.pixeldroid.app.utils.getMimeType
@ -101,15 +101,31 @@ data class PhotoData(
class PostCreationViewModel @Inject constructor( class PostCreationViewModel @Inject constructor(
private val state: SavedStateHandle, private val state: SavedStateHandle,
@ApplicationContext private val applicationContext: Context, @ApplicationContext private val applicationContext: Context,
db: AppDatabase db: AppDatabase,
): ViewModel() { ): ViewModel() {
private var storyPhotoDataBackup: MutableList<PhotoData>? = null private var storyPhotoDataBackup: MutableList<PhotoData>? = null
private val photoData: MutableLiveData<MutableList<PhotoData>> by lazy { private val photoData: MutableLiveData<MutableList<PhotoData>> by lazy {
//FIXME We should be able to access the Intent action somehow, to determine if there are
// 1 or multiple Uris instead of relying on the ClassCastException
// This should not work like this (reading its source code, get() function should return null
// if it's the wrong type but instead throws ClassCastException).
// Lucky for us that it does though: we first try to get a single Uri (which we could be
// getting from a share of a single picture to the app), when the cast to Uri fails
// we try to get a list of Uris instead (casting ourselves from Parcelable as suggested
// in get() documentation)
val uris = try {
val singleUri: Uri? = state[Intent.EXTRA_STREAM]
listOfNotNull(singleUri)
} catch (e: ClassCastException) {
state.get<ArrayList<Parcelable>>(Intent.EXTRA_STREAM)?.map { it as Uri }
}
MutableLiveData<MutableList<PhotoData>>( MutableLiveData<MutableList<PhotoData>>(
addPossibleImages( addPossibleImages(
state.get<ArrayList<Uri>>(Intent.EXTRA_STREAM), uris,
state.get<ArrayList<String>>(PostCreationActivity.PICTURE_DESCRIPTIONS), state.get<ArrayList<String>>(PostCreationActivity.PICTURE_DESCRIPTIONS),
mutableListOf() previousList = mutableListOf()
) )
) )
} }
@ -160,7 +176,7 @@ class PostCreationViewModel @Inject constructor(
* as are legal (if any) and a dialog will be shown to the user alerting them of this fact. * as are legal (if any) and a dialog will be shown to the user alerting them of this fact.
*/ */
fun addPossibleImages( fun addPossibleImages(
uris: ArrayList<Uri>?, uris: List<Uri>?,
descriptions: List<String>?, descriptions: List<String>?,
previousList: MutableList<PhotoData>? = photoData.value, previousList: MutableList<PhotoData>? = photoData.value,
): MutableList<PhotoData> { ): MutableList<PhotoData> {

View File

@ -32,7 +32,7 @@ class CameraActivity : BaseActivity() {
// If this CameraActivity wasn't started from the shortcut, // If this CameraActivity wasn't started from the shortcut,
// tell the fragment it's in an activity (so that it sends back the result instead of // tell the fragment it's in an activity (so that it sends back the result instead of
// starting a new post creation process) // starting a new post creation process)
if (intent.action != "android.intent.action.VIEW") { if (intent.action != Intent.ACTION_VIEW) {
val arguments = Bundle() val arguments = Bundle()
arguments.putBoolean(CAMERA_ACTIVITY, true) arguments.putBoolean(CAMERA_ACTIVITY, true)
arguments.putBoolean(CAMERA_ACTIVITY_STORY, story) arguments.putBoolean(CAMERA_ACTIVITY_STORY, story)
@ -47,7 +47,7 @@ class CameraActivity : BaseActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
// If this CameraActivity wasn't started from the shortcut, behave as usual // If this CameraActivity wasn't started from the shortcut, behave as usual
if (intent.action != "android.intent.action.VIEW") return super.onOptionsItemSelected(item) if (intent.action != Intent.ACTION_VIEW) return super.onOptionsItemSelected(item)
// Else, start a new MainActivity when "going back" on this activity // Else, start a new MainActivity when "going back" on this activity
when (item.itemId) { when (item.itemId) {

View File

@ -2,7 +2,6 @@ package org.pixeldroid.app.postCreation.camera
import android.Manifest import android.Manifest
import android.app.Activity import android.app.Activity
import android.content.ClipData
import android.content.ContentUris import android.content.ContentUris
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
@ -38,7 +37,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.pixeldroid.app.databinding.FragmentCameraBinding import org.pixeldroid.app.databinding.FragmentCameraBinding
import org.pixeldroid.app.postCreation.PostCreationActivity import org.pixeldroid.app.postCreation.PostCreationActivity
import org.pixeldroid.app.posts.fromHtml
import org.pixeldroid.app.utils.BaseFragment import org.pixeldroid.app.utils.BaseFragment
import java.io.File import java.io.File
import java.util.concurrent.ExecutorService import java.util.concurrent.ExecutorService
@ -450,16 +448,7 @@ class CameraFragment : BaseFragment() {
private fun startAlbumCreation(uris: ArrayList<String>) { private fun startAlbumCreation(uris: ArrayList<String>) {
val intent = Intent(Intent.ACTION_SEND_MULTIPLE).apply { val intent = PostCreationActivity.intentForUris(requireContext(), uris.map { it.toUri() })
// Pass downloaded images to new post creation activity
putParcelableArrayListExtra(
Intent.EXTRA_STREAM, ArrayList(uris.map { it.toUri() })
)
setClass(requireContext(), PostCreationActivity::class.java)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
}
if(inActivity && !addToStory){ if(inActivity && !addToStory){
requireActivity().setResult(Activity.RESULT_OK, intent) requireActivity().setResult(Activity.RESULT_OK, intent)

View File

@ -536,18 +536,7 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
).show() ).show()
// Create new post creation activity // Create new post creation activity
val intent = PostCreationActivity.intentForUris(context, imageUris).apply {
//TODO use this instead of clipdata (everywhere)
val intent = Intent(Intent.ACTION_SEND_MULTIPLE).apply {
// Pass downloaded images to new post creation activity
putParcelableArrayListExtra(
Intent.EXTRA_STREAM, ArrayList(imageUris)
)
setClass(context, PostCreationActivity::class.java)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
putExtra( putExtra(
PostCreationActivity.PICTURE_DESCRIPTIONS, PostCreationActivity.PICTURE_DESCRIPTIONS,
ArrayList(imageDescriptions) ArrayList(imageDescriptions)

View File

@ -0,0 +1,3 @@
* Fix crash when sharing an image from gallery etc to the app
* Fix permission issue causing images to throw a permission denied error