fix(android): improve content uri handling (#10316)

This commit is contained in:
Osei Fortune
2023-06-17 13:14:28 -04:00
committed by GitHub
parent 0401b09a43
commit 77f252e551
3 changed files with 767 additions and 741 deletions

View File

@ -649,23 +649,22 @@ declare module org {
export module widgets { export module widgets {
export class FileHelper { export class FileHelper {
public static class: java.lang.Class<org.nativescript.widgets.FileHelper>; public static class: java.lang.Class<org.nativescript.widgets.FileHelper>;
public appendTextSync(param0: globalAndroid.content.Context, param1: string, param2: string, param3: org.nativescript.widgets.FileHelper.Callback): void;
public appendText(param0: globalAndroid.content.Context, param1: string, param2: string, param3: org.nativescript.widgets.FileHelper.Callback): void;
public readText(param0: globalAndroid.content.Context, param1: string, param2: org.nativescript.widgets.FileHelper.Callback): void;
public appendSync(param0: globalAndroid.content.Context, param1: androidNative.Array<number>, param2: org.nativescript.widgets.FileHelper.Callback): void; public appendSync(param0: globalAndroid.content.Context, param1: androidNative.Array<number>, param2: org.nativescript.widgets.FileHelper.Callback): void;
public append(param0: globalAndroid.content.Context, param1: androidNative.Array<number>, param2: org.nativescript.widgets.FileHelper.Callback): void; public readText(param0: globalAndroid.content.Context, param1: string, param2: org.nativescript.widgets.FileHelper.Callback): void;
public appendBufferSync(param0: globalAndroid.content.Context, param1: java.nio.ByteBuffer, param2: org.nativescript.widgets.FileHelper.Callback): void;
public appendBuffer(param0: globalAndroid.content.Context, param1: java.nio.ByteBuffer, param2: org.nativescript.widgets.FileHelper.Callback): void;
public writeBufferSync(param0: globalAndroid.content.Context, param1: java.nio.ByteBuffer, param2: org.nativescript.widgets.FileHelper.Callback): void; public writeBufferSync(param0: globalAndroid.content.Context, param1: java.nio.ByteBuffer, param2: org.nativescript.widgets.FileHelper.Callback): void;
public writeTextSync(param0: globalAndroid.content.Context, param1: string, param2: string, param3: org.nativescript.widgets.FileHelper.Callback): void; public writeTextSync(param0: globalAndroid.content.Context, param1: string, param2: string, param3: org.nativescript.widgets.FileHelper.Callback): void;
public copyToFileSync(param0: globalAndroid.content.Context, param1: java.io.File, param2: org.nativescript.widgets.FileHelper.Callback): boolean; public copyToFileSync(param0: globalAndroid.content.Context, param1: java.io.File, param2: org.nativescript.widgets.FileHelper.Callback): boolean;
public appendTextSync(param0: globalAndroid.content.Context, param1: string, param2: string, param3: org.nativescript.widgets.FileHelper.Callback): void;
public read(param0: globalAndroid.content.Context, param1: org.nativescript.widgets.FileHelper.Callback): void; public read(param0: globalAndroid.content.Context, param1: org.nativescript.widgets.FileHelper.Callback): void;
public renameSync(param0: globalAndroid.content.Context, param1: string, param2: org.nativescript.widgets.FileHelper.Callback): void; public renameSync(param0: globalAndroid.content.Context, param1: string, param2: org.nativescript.widgets.FileHelper.Callback): void;
public appendBufferSync(param0: globalAndroid.content.Context, param1: java.nio.ByteBuffer, param2: org.nativescript.widgets.FileHelper.Callback): void;
public readSync(param0: globalAndroid.content.Context, param1: org.nativescript.widgets.FileHelper.Callback): androidNative.Array<number>; public readSync(param0: globalAndroid.content.Context, param1: org.nativescript.widgets.FileHelper.Callback): androidNative.Array<number>;
public static fromString(param0: globalAndroid.content.Context, param1: string): org.nativescript.widgets.FileHelper; public static fromString(param0: globalAndroid.content.Context, param1: string): org.nativescript.widgets.FileHelper;
public getSize(): number; public getSize(): number;
public getMime(): string; public getMime(): string;
public static exists(param0: globalAndroid.content.Context, param1: globalAndroid.net.Uri): boolean; public static exists(param0: globalAndroid.content.Context, param1: globalAndroid.net.Uri): boolean;
public append(param0: globalAndroid.content.Context, param1: androidNative.Array<number>, param2: org.nativescript.widgets.FileHelper.Callback): void;
public appendBuffer(param0: globalAndroid.content.Context, param1: java.nio.ByteBuffer, param2: org.nativescript.widgets.FileHelper.Callback): void;
public delete(param0: globalAndroid.content.Context): boolean; public delete(param0: globalAndroid.content.Context): boolean;
public writeSync(param0: globalAndroid.content.Context, param1: androidNative.Array<number>, param2: org.nativescript.widgets.FileHelper.Callback): void; public writeSync(param0: globalAndroid.content.Context, param1: androidNative.Array<number>, param2: org.nativescript.widgets.FileHelper.Callback): void;
public writeText(param0: globalAndroid.content.Context, param1: string, param2: string, param3: org.nativescript.widgets.FileHelper.Callback): void; public writeText(param0: globalAndroid.content.Context, param1: string, param2: string, param3: org.nativescript.widgets.FileHelper.Callback): void;
@ -680,6 +679,7 @@ declare module org {
public readTextSync(param0: globalAndroid.content.Context, param1: string, param2: org.nativescript.widgets.FileHelper.Callback): string; public readTextSync(param0: globalAndroid.content.Context, param1: string, param2: org.nativescript.widgets.FileHelper.Callback): string;
public static fromUri(param0: globalAndroid.content.Context, param1: globalAndroid.net.Uri): org.nativescript.widgets.FileHelper; public static fromUri(param0: globalAndroid.content.Context, param1: globalAndroid.net.Uri): org.nativescript.widgets.FileHelper;
public static exists(param0: globalAndroid.content.Context, param1: string): boolean; public static exists(param0: globalAndroid.content.Context, param1: string): boolean;
public appendText(param0: globalAndroid.content.Context, param1: string, param2: string, param3: org.nativescript.widgets.FileHelper.Callback): void;
public getLastModified(): number; public getLastModified(): number;
} }
export module FileHelper { export module FileHelper {

View File

@ -35,12 +35,12 @@ import java.util.concurrent.Executors;
public class FileHelper { public class FileHelper {
private Uri uri; private Uri uri;
private String name;
private String mime;
private long lastModified;
private final ExecutorService executor = Executors.newSingleThreadExecutor(); private final ExecutorService executor = Executors.newSingleThreadExecutor();
private final Handler handler; private final Handler handler;
private DocumentFile documentFile;
private WeakReference<Context> context; private WeakReference<Context> context;
public interface Callback { public interface Callback {
@ -49,9 +49,13 @@ public class FileHelper {
void onSuccess(@Nullable Object result); void onSuccess(@Nullable Object result);
} }
FileHelper(Uri uri) { FileHelper(Context context, Uri uri) {
handler = new Handler(Looper.myLooper()); handler = new Handler(Looper.myLooper());
this.context = new WeakReference<>(context);
this.uri = uri; this.uri = uri;
if (DocumentFile.isDocumentUri(context, uri)) {
documentFile = DocumentFile.fromSingleUri(context, uri);
}
} }
private static boolean isExternalStorageDocument(Uri uri) { private static boolean isExternalStorageDocument(Uri uri) {
@ -63,7 +67,8 @@ public class FileHelper {
Cursor getCursor(Context context, Uri uri) { Cursor getCursor(Context context, Uri uri) {
return getCursor(context, uri, new String[]{ return getCursor(context, uri, new String[]{
MediaStore.MediaColumns.DISPLAY_NAME, MediaStore.MediaColumns.DISPLAY_NAME,
MediaStore.MediaColumns.DATE_MODIFIED MediaStore.MediaColumns.DATE_MODIFIED,
MediaStore.MediaColumns.SIZE
}); });
} }
@ -100,9 +105,22 @@ public class FileHelper {
} }
} }
static File getDocumentFile(Context context, Uri uri) {
if (Build.VERSION.SDK_INT >= 19 && DocumentsContract.isDocumentUri(context, uri)) {
return getFile(context, uri);
}
return null;
}
public static boolean exists(Context context, Uri uri) { public static boolean exists(Context context, Uri uri) {
if (Build.VERSION.SDK_INT >= 19 && isExternalStorageDocument(uri)) { if (Build.VERSION.SDK_INT >= 19) {
File file = getFile(context, uri); if (DocumentsContract.isDocumentUri(context, uri)) {
DocumentFile file = DocumentFile.fromSingleUri(context, uri);
if (file != null) {
return file.exists();
}
}
File file = getDocumentFile(context, uri);
if (file != null) { if (file != null) {
return file.exists(); return file.exists();
} }
@ -119,21 +137,14 @@ public class FileHelper {
public static @Nullable public static @Nullable
FileHelper fromString(Context context, String string) { FileHelper fromString(Context context, String string) {
try { return fromUri(context, Uri.parse(string));
FileHelper ret = fromUri(context, Uri.parse(string));
if (ret != null) {
ret.context = new WeakReference<>(context);
}
return ret;
} catch (Exception e) {
return null;
}
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private static @Nullable private static @Nullable
File getFile(Context context, Uri uri) { File getFile(Context context, Uri uri) {
if (Build.VERSION.SDK_INT >= 19) { if (Build.VERSION.SDK_INT >= 19) {
if (isExternalStorageDocument(uri)) {
String docId = DocumentsContract.getDocumentId(uri); String docId = DocumentsContract.getDocumentId(uri);
String[] split = docId.split(":"); String[] split = docId.split(":");
String type = split[0]; String type = split[0];
@ -161,62 +172,25 @@ public class FileHelper {
} }
} }
} }
}
return null; return null;
} }
public static @Nullable public static @Nullable
FileHelper fromUri(Context context, Uri contentUri) { FileHelper fromUri(Context context, Uri contentUri) {
Uri uri = contentUri; return new FileHelper(context, contentUri);
if (Build.VERSION.SDK_INT >= 19 && isExternalStorageDocument(uri)) {
File file = getFile(context, uri);
if (file == null) {
return null;
}
FileHelper helper = new FileHelper(uri);
helper.name = file.getName();
helper.mime = context.getContentResolver().getType(uri);
helper.lastModified = file.lastModified() / 1000;
helper.context = new WeakReference<>(context);
return helper;
}
Cursor cursor = getCursor(context, uri);
if (cursor == null) {
return null;
}
boolean moved = cursor.moveToFirst();
FileHelper helper = null;
if (moved) {
int nameIndex = cursor.getColumnIndex(
MediaStore.MediaColumns.DISPLAY_NAME
);
int lastModifiedIndex = cursor.getColumnIndex(
MediaStore.MediaColumns.DATE_MODIFIED
);
helper = new FileHelper(uri);
helper.name = cursor.getString(nameIndex);
helper.mime = context.getContentResolver().getType(uri);
helper.lastModified = cursor.getLong(lastModifiedIndex);
helper.context = new WeakReference<>(context);
}
cursor.close();
return helper;
} }
private long getFileSize() { private long getFileSize() {
if (documentFile != null) {
return documentFile.length();
}
Context context = this.context.get(); Context context = this.context.get();
if (context == null) { if (context == null) {
return 0; return 0;
} }
if (Build.VERSION.SDK_INT >= 19 && isExternalStorageDocument(uri)) { if (Build.VERSION.SDK_INT >= 19 && DocumentsContract.isDocumentUri(context, uri)) {
File file = getFile(context, uri); File file = getDocumentFile(context, uri);
if (file == null) { if (file == null) {
return 0; return 0;
} }
@ -279,29 +253,6 @@ public class FileHelper {
updateValue(context, uri, values); updateValue(context, uri, values);
} }
} }
Cursor cursor = getCursor(context, uri);
if (cursor == null) {
return;
}
boolean moved = cursor.moveToFirst();
if (moved) {
int nameIndex = cursor.getColumnIndex(
MediaStore.MediaColumns.DISPLAY_NAME
);
int lastModifiedIndex = cursor.getColumnIndex(
MediaStore.MediaColumns.DATE_MODIFIED
);
name = cursor.getString(nameIndex);
mime = context.getContentResolver().getType(uri);
lastModified = cursor.getLong(lastModifiedIndex);
}
cursor.close();
} }
public long getSize() { public long getSize() {
@ -309,10 +260,53 @@ public class FileHelper {
} }
public String getName() { public String getName() {
if (documentFile != null) {
return documentFile.getName();
}
String name = null;
Context context = this.context.get();
if (context != null) {
if (DocumentFile.isDocumentUri(context, uri)) {
File file = getDocumentFile(context, uri);
if (file != null) {
name = file.getName();
}
} else {
Cursor cursor = getCursor(context, uri, null);
if (cursor == null) {
return null;
}
boolean moved = cursor.moveToFirst();
if (moved) {
int nameIndex = cursor.getColumnIndex(
MediaStore.MediaColumns.DISPLAY_NAME
);
name = cursor.getString(nameIndex);
}
cursor.close();
return name;
}
}
return name; return name;
} }
public String getMime() { public String getMime() {
String mime = null;
Context context = this.context.get();
if (context != null) {
mime = context.getContentResolver().getType(uri);
}
if (mime == null) { if (mime == null) {
return "application/octet-stream"; return "application/octet-stream";
} }
@ -320,6 +314,7 @@ public class FileHelper {
} }
public String getExtension() { public String getExtension() {
String mime = getMime();
if (mime == null) { if (mime == null) {
return ""; return "";
} }
@ -327,6 +322,37 @@ public class FileHelper {
} }
public long getLastModified() { public long getLastModified() {
long lastModified = 0;
if (documentFile != null) {
return documentFile.lastModified();
}
Context context = this.context.get();
if (context != null) {
if (DocumentFile.isDocumentUri(context, uri)) {
File file = getDocumentFile(context, uri);
if (file != null) {
lastModified = file.lastModified() / 1000;
}
} else {
Cursor cursor = getCursor(context, uri, null);
if (cursor == null) {
return 0;
}
boolean moved = cursor.moveToFirst();
if (moved) {
int sizeIndex = cursor.getColumnIndex(
MediaStore.MediaColumns.DATE_MODIFIED
);
lastModified = cursor.getLong(sizeIndex);
}
cursor.close();
}
}
return lastModified; return lastModified;
} }