From 62aa7569b5ff16272c5c5724a25cc8aff8ce6a69 Mon Sep 17 00:00:00 2001 From: Ellet Date: Wed, 2 Oct 2024 02:11:23 +0300 Subject: [PATCH 1/3] chore(example): update kotlin version in example of super_clipboard for Android to allow running with newer version of Flutter --- super_clipboard/example/android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/super_clipboard/example/android/build.gradle b/super_clipboard/example/android/build.gradle index 9d273445..586557f0 100644 --- a/super_clipboard/example/android/build.gradle +++ b/super_clipboard/example/android/build.gradle @@ -1,5 +1,5 @@ buildscript { - ext.kotlin_version = '1.6.10' + ext.kotlin_version = '1.7.10' repositories { google() mavenCentral() From d91f34fdd03d607ead74756979d074192def9aa3 Mon Sep 17 00:00:00 2001 From: Ellet Date: Wed, 2 Oct 2024 02:32:51 +0300 Subject: [PATCH 2/3] fix(android): workaround to app crashes on Android after copying an image and restart the app and then paste it --- .../ClipDataHelper.java | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/super_native_extensions/android/src/main/java/com/superlist/super_native_extensions/ClipDataHelper.java b/super_native_extensions/android/src/main/java/com/superlist/super_native_extensions/ClipDataHelper.java index 88e9cdec..00ad8a9d 100644 --- a/super_native_extensions/android/src/main/java/com/superlist/super_native_extensions/ClipDataHelper.java +++ b/super_native_extensions/android/src/main/java/com/superlist/super_native_extensions/ClipDataHelper.java @@ -24,6 +24,7 @@ import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -36,6 +37,8 @@ public final class ClipDataHelper { static final String typeTextHtml = "text/html"; static final String typeUriList = "text/uri-list"; + private static final String TAG = "SuperClipboard" + ClipDataHelper.class.getSimpleName(); + public String[] getFormats(ClipData data, int index, Context context) { if (index < data.getItemCount()) { return getFormats(data.getItemAt(index), context); @@ -88,8 +91,22 @@ String[] getFormats(ClipData.Item item, Context context) { if (item.getText() != null) { res.add(typeTextPlain); } + + ContentResolver contentProvider = context.getContentResolver(); if (item.getUri() != null) { - String[] types = context.getContentResolver().getStreamTypes(item.getUri(), "*/*"); + try { + readUriOrThrow( + context, + item.getUri() + ); + } catch (SecurityException e) { + Log.e(TAG, "Could not read the URI " + contentProvider.getType(item.getUri()) + " due to app lifecycle changes: " + e); + return res.toArray(new String[0]); + } catch (IOException e) { + Log.e(TAG, "Could not read the URI " + contentProvider.getType(item.getUri()) + " due to IO error: " + e); + return res.toArray(new String[0]); + } + String[] types = contentProvider.getStreamTypes(item.getUri(), "*/*"); if (types != null) { for (String type : types) { if (!res.contains(type)) { @@ -97,7 +114,7 @@ String[] getFormats(ClipData.Item item, Context context) { } } } else { - String type = context.getContentResolver().getType(item.getUri()); + String type = contentProvider.getType(item.getUri()); if (type != null) { res.add(type); } else { @@ -108,6 +125,20 @@ String[] getFormats(ClipData.Item item, Context context) { return res.toArray(new String[0]); } + /** + * A method to see if any exceptions can occur + * before start using the Uri. + *

+ * The app can lose access to the [Uri] due to lifecycle changes. + * + * @throws SecurityException When the app loses access to the [Uri] due to app lifecycle changes + * or app restart. + * @throws FileNotFoundException Could be thrown when the [Uri] is no longer on the clipboard. + * */ + private void readUriOrThrow(Context context, Uri uri) throws SecurityException, IOException { + Objects.requireNonNull(context.getContentResolver().openInputStream(uri)).close();; + } + CharSequence getText(ClipData.Item item, Context context) { return coerceToPlainText(item, context); } From bfde03065fcc0894e7244deb5364dcdac313ac0f Mon Sep 17 00:00:00 2001 From: Ellet Date: Wed, 2 Oct 2024 12:33:22 +0300 Subject: [PATCH 3/3] chore: rename contentProvider to contentResolver --- .../super_native_extensions/ClipDataHelper.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/super_native_extensions/android/src/main/java/com/superlist/super_native_extensions/ClipDataHelper.java b/super_native_extensions/android/src/main/java/com/superlist/super_native_extensions/ClipDataHelper.java index 00ad8a9d..9866f7c0 100644 --- a/super_native_extensions/android/src/main/java/com/superlist/super_native_extensions/ClipDataHelper.java +++ b/super_native_extensions/android/src/main/java/com/superlist/super_native_extensions/ClipDataHelper.java @@ -92,7 +92,7 @@ String[] getFormats(ClipData.Item item, Context context) { res.add(typeTextPlain); } - ContentResolver contentProvider = context.getContentResolver(); + ContentResolver contentResolver = context.getContentResolver(); if (item.getUri() != null) { try { readUriOrThrow( @@ -100,13 +100,13 @@ String[] getFormats(ClipData.Item item, Context context) { item.getUri() ); } catch (SecurityException e) { - Log.e(TAG, "Could not read the URI " + contentProvider.getType(item.getUri()) + " due to app lifecycle changes: " + e); + Log.e(TAG, "Could not read the URI " + contentResolver.getType(item.getUri()) + " due to app lifecycle changes: " + e); return res.toArray(new String[0]); } catch (IOException e) { - Log.e(TAG, "Could not read the URI " + contentProvider.getType(item.getUri()) + " due to IO error: " + e); + Log.e(TAG, "Could not read the URI " + contentResolver.getType(item.getUri()) + " due to IO error: " + e); return res.toArray(new String[0]); } - String[] types = contentProvider.getStreamTypes(item.getUri(), "*/*"); + String[] types = contentResolver.getStreamTypes(item.getUri(), "*/*"); if (types != null) { for (String type : types) { if (!res.contains(type)) { @@ -114,7 +114,7 @@ String[] getFormats(ClipData.Item item, Context context) { } } } else { - String type = contentProvider.getType(item.getUri()); + String type = contentResolver.getType(item.getUri()); if (type != null) { res.add(type); } else {