Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(android) workaround to app crashes after copying an image and paste it on app restart #447

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion super_clipboard/example/android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
buildscript {
ext.kotlin_version = '1.6.10'
ext.kotlin_version = '1.7.10'
repositories {
google()
mavenCentral()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);
Expand Down Expand Up @@ -88,16 +91,30 @@ String[] getFormats(ClipData.Item item, Context context) {
if (item.getText() != null) {
res.add(typeTextPlain);
}

ContentResolver contentResolver = 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 " + 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 " + contentResolver.getType(item.getUri()) + " due to IO error: " + e);
return res.toArray(new String[0]);
}
String[] types = contentResolver.getStreamTypes(item.getUri(), "*/*");
if (types != null) {
for (String type : types) {
if (!res.contains(type)) {
res.add(type);
}
}
} else {
String type = context.getContentResolver().getType(item.getUri());
String type = contentResolver.getType(item.getUri());
if (type != null) {
res.add(type);
} else {
Expand All @@ -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.
* <p>
* 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);
}
Expand Down
Loading