mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-14 10:01:08 +08:00
fix(android): content uri handling improvements (#9936)
This commit is contained in:

committed by
Nathan Walker

parent
464ea18737
commit
99480c06db
@ -1,4 +1,4 @@
|
||||
import { Page, EventData, Application, File } from '@nativescript/core';
|
||||
import { Page, EventData, Application, File, Folder, knownFolders, path, getFileAccess, Utils } from '@nativescript/core';
|
||||
|
||||
let page: Page;
|
||||
|
||||
@ -71,3 +71,108 @@ function doWork(path: string) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
export function pickFiles() {
|
||||
if (!global.isAndroid) {
|
||||
return;
|
||||
}
|
||||
const Intent = android.content.Intent;
|
||||
Application.android.on('activityResult', (args) => {
|
||||
if (args.requestCode === 1000) {
|
||||
const intent: android.content.Intent = args.intent;
|
||||
const clip = intent.getClipData();
|
||||
if (clip) {
|
||||
const count = clip.getItemCount();
|
||||
for (let i = 0; i < count; i++) {
|
||||
const item = clip.getItemAt(i);
|
||||
readFile(item.getUri().toString());
|
||||
}
|
||||
} else {
|
||||
readFile(intent.getData().toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
const picker = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||
picker.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
|
||||
picker.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
picker.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
|
||||
picker.setType('*/*');
|
||||
Application.android.foregroundActivity.startActivityForResult(picker, 1000);
|
||||
}
|
||||
|
||||
export function pickFile() {
|
||||
if (!global.isAndroid) {
|
||||
return;
|
||||
}
|
||||
Application.android.on('activityResult', (args) => {
|
||||
if (args.requestCode === 1000) {
|
||||
const file = args.intent.getData().toString();
|
||||
//const file = File.fromPath(args.intent.getData().toString());
|
||||
//console.log(file);
|
||||
readFile(file);
|
||||
}
|
||||
});
|
||||
const Intent = android.content.Intent;
|
||||
const picker = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||
picker.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
|
||||
picker.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
picker.setType('*/*');
|
||||
Application.android.foregroundActivity.startActivityForResult(picker, 1000);
|
||||
}
|
||||
|
||||
function readFile(selected: string) {
|
||||
let applicationContext = Utils.android.getApplicationContext();
|
||||
const getOrSetHelper: org.nativescript.widgets.FileHelper = org.nativescript.widgets.FileHelper.fromString(applicationContext, selected);
|
||||
|
||||
console.log('==== CONTEXT START =========');
|
||||
console.log('applicationContext', applicationContext);
|
||||
console.log('selected: ', decodeURIComponent(selected));
|
||||
console.log('getOrSetHelper: ', getOrSetHelper);
|
||||
console.log('==== CONTEXT END =========');
|
||||
|
||||
console.log('==== READ START =========');
|
||||
const fileRead = getFileAccess().read(selected);
|
||||
console.log('# read: ', fileRead);
|
||||
|
||||
const readSync = getFileAccess().readSync(selected);
|
||||
console.log('# readSync: ', readSync);
|
||||
|
||||
const readText = getFileAccess().readText(selected);
|
||||
console.log('# readText: ', readText);
|
||||
|
||||
getFileAccess()
|
||||
.readAsync(selected)
|
||||
.then(
|
||||
(readAsyncResolve) => {
|
||||
console.log('# readAsynccResolve: ', readAsyncResolve);
|
||||
},
|
||||
(readAsyncRejected) => {
|
||||
console.log('# readAsyncRejected: ', readAsyncRejected);
|
||||
}
|
||||
);
|
||||
console.log('==== READ END =========');
|
||||
|
||||
saveFile(selected, readSync);
|
||||
}
|
||||
|
||||
function saveFile(selected, readSync) {
|
||||
const folder: Folder = <Folder>knownFolders.documents();
|
||||
|
||||
let newPath: string = path.join(folder.path, getFileNameFromContent(selected));
|
||||
|
||||
File.fromPath(newPath).writeSync(readSync, (error) => {
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
let savedFile = folder.getFile(getFileNameFromContent(selected));
|
||||
|
||||
console.log('==== SAVE START =========');
|
||||
console.log('# saved file: ', savedFile);
|
||||
console.log('# save size: ', savedFile.size);
|
||||
console.log('==== SAVE END =========');
|
||||
}
|
||||
|
||||
function getFileNameFromContent(content: string) {
|
||||
const file = getFileAccess().getFile(content);
|
||||
return decodeURIComponent(file.name).split('/').pop().toLowerCase();
|
||||
}
|
||||
|
@ -2,5 +2,7 @@
|
||||
|
||||
<StackLayout>
|
||||
<Button text="Create Random" tap="createRandom" />
|
||||
<Button text="Pick File" tap="pickFile" />
|
||||
<Button text="Pick Multiple Files" tap="pickFiles" />
|
||||
</StackLayout>
|
||||
</Page>
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nativescript/core",
|
||||
"version": "8.2.5",
|
||||
"version": "8.2.6-alpha.0",
|
||||
"description": "A JavaScript library providing an easy to use api for interacting with iOS and Android platform APIs.",
|
||||
"main": "index",
|
||||
"types": "index.d.ts",
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -34,7 +34,7 @@
|
||||
</data>
|
||||
<key>Info.plist</key>
|
||||
<data>
|
||||
xwF1juLfCl48xVJYOqCb8tG0WhQ=
|
||||
0Rmccf4SQGyUrsxYOyGPzKsCAqU=
|
||||
</data>
|
||||
<key>Modules/module.modulemap</key>
|
||||
<data>
|
||||
|
Binary file not shown.
@ -48,44 +48,35 @@ public class FileHelper {
|
||||
}
|
||||
|
||||
private static boolean isExternalStorageDocument(Uri uri) {
|
||||
return "com.android.externalstorage.documents".equals(uri
|
||||
.getAuthority());
|
||||
return false;
|
||||
// return "com.android.externalstorage.documents".equals(uri
|
||||
// .getAuthority());
|
||||
}
|
||||
|
||||
private static @Nullable
|
||||
Cursor getCursor(Context context, Uri uri) {
|
||||
Cursor cursor = null;
|
||||
String[] projections = {
|
||||
MediaStore.MediaColumns.SIZE,
|
||||
MediaStore.MediaColumns.DISPLAY_NAME,
|
||||
MediaStore.MediaColumns.DATE_MODIFIED
|
||||
};
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
if (DocumentsContract.isDocumentUri(context, uri)) {
|
||||
String docId = DocumentsContract.getDocumentId(uri);
|
||||
String[] split = docId.split(":");
|
||||
String type = split[0];
|
||||
|
||||
Uri contentUri;
|
||||
if ("image".equals(type)) {
|
||||
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
|
||||
} else if ("video".equals(type)) {
|
||||
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
|
||||
} else if ("audio".equals(type)) {
|
||||
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
||||
} else {
|
||||
contentUri = MediaStore.Files.getContentUri("external");
|
||||
if (Build.VERSION.SDK_INT >= 29) {
|
||||
if (!uri.toString().startsWith("content://com.android.providers.downloads.documents")) {
|
||||
cursor = context.getContentResolver().query(
|
||||
MediaStore.getMediaUri(context, uri), projections, null, null, null, null
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String selection = "_id=?";
|
||||
String[] selectionArgs = {split[1]};
|
||||
|
||||
cursor = context.getContentResolver().query(
|
||||
contentUri, null, selection, selectionArgs, null, null
|
||||
);
|
||||
}
|
||||
}
|
||||
if (cursor == null) {
|
||||
cursor = context.getContentResolver().query(uri, null, null, null, null);
|
||||
cursor = context.getContentResolver().query(uri, projections, null, null, null);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
cursor = null;
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
return cursor;
|
||||
@ -120,7 +111,7 @@ public class FileHelper {
|
||||
public static @Nullable
|
||||
FileHelper fromString(Context context, String string) {
|
||||
try {
|
||||
return fromUri(context, Uri.parse(Uri.decode(string)), false);
|
||||
return fromUri(context, Uri.parse(string));
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
@ -158,20 +149,10 @@ public class FileHelper {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static @Nullable
|
||||
FileHelper fromUri(Context context, Uri uri) {
|
||||
return fromUri(context, uri, true);
|
||||
}
|
||||
|
||||
private static @Nullable
|
||||
FileHelper fromUri(Context context, Uri contentUri, boolean parseUri) {
|
||||
Uri uri;
|
||||
|
||||
if (parseUri) {
|
||||
uri = Uri.parse(Uri.decode(contentUri.toString()));
|
||||
} else {
|
||||
uri = contentUri;
|
||||
}
|
||||
FileHelper fromUri(Context context, Uri contentUri) {
|
||||
Uri uri = contentUri;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 19 && isExternalStorageDocument(uri)) {
|
||||
File file = getFile(context, uri);
|
||||
@ -338,10 +319,17 @@ public class FileHelper {
|
||||
|
||||
private byte[] readSyncInternal(Context context) throws Exception {
|
||||
InputStream is = getInputStream(context, uri);
|
||||
byte[] array = new byte[(int) size];
|
||||
is.read(array);
|
||||
|
||||
Async.Http.RequestResult.ByteArrayOutputStream2 ret = new Async.Http.RequestResult.ByteArrayOutputStream2();
|
||||
|
||||
byte[] buff = new byte[4096];
|
||||
int read;
|
||||
while ((read = is.read(buff, 0, buff.length)) != -1) {
|
||||
ret.write(buff, 0, read);
|
||||
}
|
||||
|
||||
is.close();
|
||||
return array;
|
||||
return ret.buf();
|
||||
}
|
||||
|
||||
public @Nullable
|
||||
@ -517,40 +505,28 @@ public class FileHelper {
|
||||
return file.delete();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (DocumentsContract.isDocumentUri(context, uri)) {
|
||||
if (Build.VERSION.SDK_INT >= 29) {
|
||||
if (!uri.toString().startsWith("content://com.android.providers.downloads.documents")) {
|
||||
return context.getContentResolver().delete(
|
||||
MediaStore.getMediaUri(context, uri), null, null
|
||||
) > 0;
|
||||
}
|
||||
|
||||
if (DocumentsContract.isDocumentUri(context, uri)) {
|
||||
String docId = DocumentsContract.getDocumentId(uri);
|
||||
String[] split = docId.split(":");
|
||||
String type = split[0];
|
||||
|
||||
Uri contentUri;
|
||||
if ("image".equals(type)) {
|
||||
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
|
||||
} else if ("video".equals(type)) {
|
||||
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
|
||||
} else if ("audio".equals(type)) {
|
||||
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
||||
} else {
|
||||
contentUri = MediaStore.Files.getContentUri("external");
|
||||
} else {
|
||||
return DocumentsContract.deleteDocument(context.getContentResolver(), uri);
|
||||
}
|
||||
}
|
||||
|
||||
String selection = "_id=?";
|
||||
String[] selectionArgs = {split[1]};
|
||||
|
||||
return context.getContentResolver().delete(
|
||||
contentUri, selection, selectionArgs
|
||||
) > 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return context.getContentResolver().delete(uri, null, null) > 0;
|
||||
} catch (SecurityException e) {
|
||||
} catch (SecurityException | FileNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void renameInternal(Context context, String newName) throws Exception {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(MediaStore.MediaColumns.DISPLAY_NAME, newName);
|
||||
@ -566,29 +542,18 @@ public class FileHelper {
|
||||
}
|
||||
|
||||
if (DocumentsContract.isDocumentUri(context, uri)) {
|
||||
String docId = DocumentsContract.getDocumentId(uri);
|
||||
String[] split = docId.split(":");
|
||||
String type = split[0];
|
||||
|
||||
Uri contentUri;
|
||||
if ("image".equals(type)) {
|
||||
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
|
||||
} else if ("video".equals(type)) {
|
||||
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
|
||||
} else if ("audio".equals(type)) {
|
||||
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
||||
} else {
|
||||
contentUri = MediaStore.Files.getContentUri("external");
|
||||
if (Build.VERSION.SDK_INT >= 29) {
|
||||
if (!uri.toString().startsWith("content://com.android.providers.downloads.documents")) {
|
||||
context.getContentResolver().update(
|
||||
uri, values, null, null
|
||||
);
|
||||
return;
|
||||
}
|
||||
DocumentsContract.renameDocument(context.getContentResolver(), uri, newName);
|
||||
} else if (Build.VERSION.SDK_INT >= 21) {
|
||||
DocumentsContract.renameDocument(context.getContentResolver(), uri, newName);
|
||||
return;
|
||||
}
|
||||
|
||||
String selection = "_id=?";
|
||||
String[] selectionArgs = {split[1]};
|
||||
|
||||
context.getContentResolver().update(
|
||||
contentUri, values, selection, selectionArgs
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user