Small cleanups on imagePicker code
parent
1ef4fcbb10
commit
162682ef8b
|
|
@ -14,6 +14,7 @@ import io.flutter.embedding.engine.FlutterEngine
|
|||
import io.flutter.embedding.engine.FlutterEngineCache
|
||||
import java.io.File
|
||||
|
||||
|
||||
/**
|
||||
* Activity that handles ACTION_GET_CONTENT and ACTION_PICK intents
|
||||
* Communicates with Flutter to get the selected image URI
|
||||
|
|
@ -25,7 +26,7 @@ class ImagePickerActivity : FlutterActivity() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
Log.d(TAG, "onCreate() called")
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
|
||||
val action = intent.action
|
||||
val type = intent.type
|
||||
|
||||
|
|
@ -36,7 +37,7 @@ class ImagePickerActivity : FlutterActivity() {
|
|||
} else {
|
||||
// Invalid intent, finish immediately
|
||||
Log.w(TAG, "Invalid intent action or type, finishing activity")
|
||||
setResult(Activity.RESULT_CANCELED)
|
||||
setResult(RESULT_CANCELED)
|
||||
finish()
|
||||
}
|
||||
Log.d(TAG, "onCreate() finished")
|
||||
|
|
@ -45,17 +46,17 @@ class ImagePickerActivity : FlutterActivity() {
|
|||
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
||||
Log.d(TAG, "configureFlutterEngine() called, hasRequestedImage = $hasRequestedImage")
|
||||
super.configureFlutterEngine(flutterEngine)
|
||||
|
||||
|
||||
// Register all plugins
|
||||
Log.d(TAG, "Registering plugins...")
|
||||
MainActivity.registerPlugins(this, flutterEngine)
|
||||
Log.d(TAG, "Plugins registered")
|
||||
|
||||
|
||||
// Set up the image picker API
|
||||
Log.d(TAG, "Setting up ImagePickerProviderApi...")
|
||||
imagePickerApi = ImagePickerProviderApi(flutterEngine.dartExecutor.binaryMessenger)
|
||||
Log.d(TAG, "ImagePickerProviderApi set up: ${imagePickerApi != null}")
|
||||
|
||||
Log.d(TAG, "ImagePickerProviderApi set up: ${true}")
|
||||
|
||||
// Check if this is a valid image picker intent and we haven't requested yet
|
||||
val action = intent.action
|
||||
if (!hasRequestedImage && (action == Intent.ACTION_GET_CONTENT || action == Intent.ACTION_PICK)) {
|
||||
|
|
@ -63,7 +64,10 @@ class ImagePickerActivity : FlutterActivity() {
|
|||
hasRequestedImage = true
|
||||
requestImageFromFlutter()
|
||||
} else {
|
||||
Log.w(TAG, "NOT calling requestImageFromFlutter() - hasRequestedImage: $hasRequestedImage, action: $action")
|
||||
Log.w(
|
||||
TAG,
|
||||
"NOT calling requestImageFromFlutter() - hasRequestedImage: $hasRequestedImage, action: $action"
|
||||
)
|
||||
}
|
||||
Log.d(TAG, "configureFlutterEngine() finished")
|
||||
}
|
||||
|
|
@ -71,82 +75,77 @@ class ImagePickerActivity : FlutterActivity() {
|
|||
private fun requestImageFromFlutter() {
|
||||
Log.d(TAG, "=== requestImageFromFlutter() CALLED ===")
|
||||
Log.d(TAG, "imagePickerApi is null: ${imagePickerApi == null}")
|
||||
|
||||
|
||||
// Check if the calling app allows multiple selection
|
||||
val allowMultiple = intent.getBooleanExtra(Intent.EXTRA_ALLOW_MULTIPLE, false)
|
||||
Log.d(TAG, "Intent allows multiple selection: $allowMultiple")
|
||||
|
||||
|
||||
imagePickerApi?.pickImagesForIntent { result ->
|
||||
Log.d(TAG, "pickImagesForIntent callback received")
|
||||
result.fold(
|
||||
onSuccess = { imageUriList ->
|
||||
Log.d(TAG, "SUCCESS: Received ${imageUriList?.size ?: 0} image URI(s) from Flutter")
|
||||
|
||||
if (imageUriList.isNullOrEmpty()) {
|
||||
// User cancelled or no images selected
|
||||
Log.d(TAG, "No images selected, returning RESULT_CANCELED")
|
||||
setResult(Activity.RESULT_CANCELED)
|
||||
result.fold(onSuccess = { imageUriList ->
|
||||
Log.d(TAG, "SUCCESS: Received ${imageUriList?.size ?: 0} image URI(s) from Flutter")
|
||||
|
||||
if (imageUriList.isNullOrEmpty()) {
|
||||
// User cancelled or no images selected
|
||||
Log.d(TAG, "No images selected, returning RESULT_CANCELED")
|
||||
setResult(RESULT_CANCELED)
|
||||
finish()
|
||||
return@fold
|
||||
}
|
||||
|
||||
try {
|
||||
// Convert all URIs to content URIs
|
||||
val contentUris = imageUriList.filterNotNull().map { uriString ->
|
||||
try {
|
||||
convertToContentUri(uriString)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error converting URI: $uriString", e)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
if (contentUris.isEmpty()) {
|
||||
Log.e(TAG, "No valid content URIs after conversion")
|
||||
setResult(RESULT_CANCELED)
|
||||
finish()
|
||||
return@fold
|
||||
}
|
||||
|
||||
try {
|
||||
// Convert all URIs to content URIs
|
||||
val contentUris = imageUriList.mapNotNull { uriString ->
|
||||
uriString?.let {
|
||||
try {
|
||||
convertToContentUri(it)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error converting URI: $it", e)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
val resultIntent = Intent()
|
||||
|
||||
if (contentUris.size == 1 || !allowMultiple) {
|
||||
// Single image or app doesn't support multiple
|
||||
Log.d(TAG, "Returning single image URI: ${contentUris.first()}")
|
||||
resultIntent.data = contentUris.first()
|
||||
} else {
|
||||
// Multiple images - use ClipData
|
||||
Log.d(TAG, "Returning ${contentUris.size} images using ClipData")
|
||||
val clipData = ClipData.newUri(contentResolver, "Images", contentUris.first())
|
||||
|
||||
// Add the rest of the URIs to ClipData
|
||||
for (i in 1 until contentUris.size) {
|
||||
clipData.addItem(ClipData.Item(contentUris[i]))
|
||||
}
|
||||
|
||||
if (contentUris.isEmpty()) {
|
||||
Log.e(TAG, "No valid content URIs after conversion")
|
||||
setResult(Activity.RESULT_CANCELED)
|
||||
finish()
|
||||
return@fold
|
||||
}
|
||||
|
||||
val resultIntent = Intent()
|
||||
|
||||
if (contentUris.size == 1 || !allowMultiple) {
|
||||
// Single image or app doesn't support multiple
|
||||
Log.d(TAG, "Returning single image URI: ${contentUris.first()}")
|
||||
resultIntent.data = contentUris.first()
|
||||
} else {
|
||||
// Multiple images - use ClipData
|
||||
Log.d(TAG, "Returning ${contentUris.size} images using ClipData")
|
||||
val clipData = ClipData.newUri(contentResolver, "Images", contentUris.first())
|
||||
|
||||
// Add the rest of the URIs to ClipData
|
||||
for (i in 1 until contentUris.size) {
|
||||
clipData.addItem(ClipData.Item(contentUris[i]))
|
||||
}
|
||||
|
||||
resultIntent.clipData = clipData
|
||||
resultIntent.data = contentUris.first() // Also set primary URI for compatibility
|
||||
}
|
||||
|
||||
// Grant temporary read permission to all URIs
|
||||
resultIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
|
||||
setResult(Activity.RESULT_OK, resultIntent)
|
||||
finish()
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error processing URIs", e)
|
||||
setResult(Activity.RESULT_CANCELED)
|
||||
finish()
|
||||
resultIntent.clipData = clipData
|
||||
resultIntent.data = contentUris.first() // Also set primary URI for compatibility
|
||||
}
|
||||
},
|
||||
onFailure = { error ->
|
||||
Log.e(TAG, "Error getting images from Flutter", error)
|
||||
setResult(Activity.RESULT_CANCELED)
|
||||
|
||||
// Grant temporary read permission to all URIs
|
||||
resultIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
|
||||
setResult(RESULT_OK, resultIntent)
|
||||
finish()
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error processing URIs", e)
|
||||
setResult(RESULT_CANCELED)
|
||||
finish()
|
||||
}
|
||||
)
|
||||
}, onFailure = { error ->
|
||||
Log.e(TAG, "Error getting images from Flutter", error)
|
||||
setResult(RESULT_CANCELED)
|
||||
finish()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -156,13 +155,11 @@ class ImagePickerActivity : FlutterActivity() {
|
|||
*/
|
||||
private fun convertToContentUri(uriString: String): Uri {
|
||||
val uri = uriString.toUri()
|
||||
|
||||
|
||||
return if (uri.scheme == "file") {
|
||||
val file = File(uri.path!!)
|
||||
FileProvider.getUriForFile(
|
||||
this,
|
||||
"${applicationContext.packageName}.fileprovider",
|
||||
file
|
||||
this, "${applicationContext.packageName}.fileprovider", file
|
||||
)
|
||||
} else {
|
||||
// Already a content URI or other type
|
||||
|
|
@ -172,7 +169,7 @@ class ImagePickerActivity : FlutterActivity() {
|
|||
|
||||
override fun getCachedEngineId(): String? {
|
||||
// Try to use the cached engine if available
|
||||
val hasCachedEngine = FlutterEngineCache.getInstance().contains("immich_engine")
|
||||
val hasCachedEngine = FlutterEngineCache.getInstance().contains(ENGINE_CACHE_KEY)
|
||||
Log.d(TAG, "getCachedEngineId() called, has cached engine: $hasCachedEngine")
|
||||
return if (hasCachedEngine) {
|
||||
Log.d(TAG, "Using cached engine 'immich_engine'")
|
||||
|
|
@ -182,22 +179,22 @@ class ImagePickerActivity : FlutterActivity() {
|
|||
null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
Log.d(TAG, "onStart() called")
|
||||
}
|
||||
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
Log.d(TAG, "onResume() called")
|
||||
}
|
||||
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
Log.d(TAG, "onPause() called")
|
||||
}
|
||||
|
||||
|
||||
override fun onDestroy() {
|
||||
Log.d(TAG, "onDestroy() called")
|
||||
super.onDestroy()
|
||||
|
|
@ -205,5 +202,7 @@ class ImagePickerActivity : FlutterActivity() {
|
|||
|
||||
companion object {
|
||||
private const val TAG = "ImagePickerActivity"
|
||||
const val ENGINE_CACHE_KEY = "immich::image_picker::engine"
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ class ImagePickerProviderService implements ImagePickerProviderApi {
|
|||
dPrint(() => "User selected ${selectedAssets.length} asset(s)");
|
||||
|
||||
// Process all selected assets
|
||||
final List<String?> imageUris = [];
|
||||
final List<String> imageUris = [];
|
||||
|
||||
for (final asset in selectedAssets) {
|
||||
dPrint(() => "Processing asset: ${asset.runtimeType}");
|
||||
|
|
|
|||
Loading…
Reference in New Issue