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 {
minSdkVersion 23
versionCode 30
targetSdkVersion 34
versionCode 31
versionName "1.0.beta" + versionCode
//TODO add resConfigs("en", "fr", "ja",...) ?

View File

@ -1,5 +1,9 @@
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 androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
@ -15,6 +19,31 @@ class PostCreationActivity : BaseActivity() {
internal const val POST_REDRAFT = "post_redraft"
internal const val POST_NSFW = "post_nsfw"
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
@ -32,4 +61,5 @@ class PostCreationActivity : BaseActivity() {
}
override fun onSupportNavigateUp() = navController.navigateUp() || super.onSupportNavigateUp()
}

View File

@ -1,6 +1,6 @@
package org.pixeldroid.app.postCreation
import android.content.Context
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Parcelable
@ -33,10 +33,10 @@ import kotlinx.parcelize.Parcelize
import okhttp3.MultipartBody
import org.pixeldroid.app.MainActivity
import org.pixeldroid.app.R
import org.pixeldroid.app.postCreation.camera.CameraFragment
import org.pixeldroid.app.utils.api.objects.Attachment
import org.pixeldroid.app.utils.db.AppDatabase
import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
import org.pixeldroid.app.postCreation.camera.CameraFragment
import org.pixeldroid.app.utils.api.objects.Attachment
import org.pixeldroid.app.utils.db.AppDatabase
import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
import org.pixeldroid.app.utils.di.PixelfedAPIHolder
import org.pixeldroid.app.utils.fileExtension
import org.pixeldroid.app.utils.getMimeType
@ -101,15 +101,31 @@ data class PhotoData(
class PostCreationViewModel @Inject constructor(
private val state: SavedStateHandle,
@ApplicationContext private val applicationContext: Context,
db: AppDatabase
db: AppDatabase,
): ViewModel() {
private var storyPhotoDataBackup: MutableList<PhotoData>? = null
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>>(
addPossibleImages(
state.get<ArrayList<Uri>>(Intent.EXTRA_STREAM),
uris,
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.
*/
fun addPossibleImages(
uris: ArrayList<Uri>?,
uris: List<Uri>?,
descriptions: List<String>?,
previousList: MutableList<PhotoData>? = photoData.value,
): MutableList<PhotoData> {

View File

@ -32,7 +32,7 @@ class CameraActivity : BaseActivity() {
// 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
// starting a new post creation process)
if (intent.action != "android.intent.action.VIEW") {
if (intent.action != Intent.ACTION_VIEW) {
val arguments = Bundle()
arguments.putBoolean(CAMERA_ACTIVITY, true)
arguments.putBoolean(CAMERA_ACTIVITY_STORY, story)
@ -47,7 +47,7 @@ class CameraActivity : BaseActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
// 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
when (item.itemId) {

View File

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

View File

@ -536,18 +536,7 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
).show()
// Create new post creation activity
//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)
val intent = PostCreationActivity.intentForUris(context, imageUris).apply {
putExtra(
PostCreationActivity.PICTURE_DESCRIPTIONS,
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