From 4b41c0070e197022ebe13b9ab27a15b0e825c672 Mon Sep 17 00:00:00 2001 From: knyipab <46513942+knyipab@users.noreply.github.com> Date: Sun, 13 Mar 2022 19:26:54 +0800 Subject: [PATCH 1/2] more features for StorageGetAPI: print URI, async, folder, persistable, multiple, mimetype, etc. --- app/src/main/AndroidManifest.xml | 2 +- .../java/com/termux/api/StorageGetAPI.java | 167 +++++++++++++++--- 2 files changed, 141 insertions(+), 28 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cea78e993..1322d2d04 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -80,7 +80,7 @@ android:exported="false"/> { - final String fileExtra = intent.getStringExtra("file"); - if (fileExtra == null || !new File(fileExtra).getParentFile().canWrite()) { - out.println("ERROR: Not a writable folder: " + fileExtra); - return; - } - + try { Intent intent1 = new Intent(context, StorageActivity.class); - intent1.putExtra(FILE_EXTRA, fileExtra); + intent1.putExtra(INTENT_EXTRA, intent); intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent1); - }); + } catch (Exception e) { + if (intent.getBooleanExtra("json", true)) { + ResultReturner.returnData(apiReceiver, intent, new ResultReturner.ResultJsonWriter() { + @Override + public void writeJson(JsonWriter out) throws Exception { + out.beginObject(); + out.name("error").value(ERROR_INITIATE_INTENT); + out.name("uri").beginArray(); + out.endArray(); + out.endObject(); + } + }); + } + return; + } + if (!intent.getBooleanExtra("async", false)) { + ResultReturner.returnData(apiReceiver, intent, out -> { }); + } } public static class StorageActivity extends Activity { private String outputFile; + private Intent mIntent; + private boolean async; + private boolean folder; + private boolean persist; + private boolean multiple; + private boolean json; + private String mimeType; + private Uri[] data; + private int error; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Intent intent = this.getIntent(); + mIntent = intent.getParcelableExtra(INTENT_EXTRA); + outputFile = mIntent.getStringExtra("file"); + mimeType = mIntent.getStringExtra("type"); + async = mIntent.getBooleanExtra("async", false); + folder = mIntent.getBooleanExtra("folder", false); + persist = mIntent.getBooleanExtra("persist", false); + multiple = mIntent.getBooleanExtra("multiple", false); + json = mIntent.getBooleanExtra("json", true); + data = null; + error = 0; + } @Override public void onResume() { super.onResume(); - outputFile = getIntent().getStringExtra(FILE_EXTRA); - - // ACTION_OPEN_DOCUMENT is the intent to choose a file via the system's file browser. - Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); - - // Filter to only show results that can be "opened", such as a - // file (as opposed to a list of contacts or timezones) - intent.addCategory(Intent.CATEGORY_OPENABLE); + try { + // ACTION_OPEN_DOCUMENT is the intent to choose a file via the system's file browser. + Intent intent = new Intent(folder ? Intent.ACTION_OPEN_DOCUMENT_TREE : Intent.ACTION_OPEN_DOCUMENT); - intent.setType("*/*"); + if (multiple && !folder) { + intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); + } - startActivityForResult(intent, 42); + // Filter to only show results that can be "opened", such as a + // file (as opposed to a list of contacts or timezones) + if (!folder) { + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType("*/*"); + if (mimeType != null) { + intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeType.split(",")); + } + } + int flags = folder ? Intent.FLAG_GRANT_PREFIX_URI_PERMISSION : 0; + if (persist) { + flags |= Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION; + } + intent.setFlags(flags); + + startActivityForResult(intent, 42); + } catch (Exception e) { + if (json) { + ResultReturner.returnData(this, mIntent, new ResultReturner.ResultJsonWriter() { + @Override + public void writeJson(JsonWriter out) throws Exception { + out.beginObject(); + out.name("error").value(ERROR_INITIATE_INTENT); + out.name("uri").beginArray(); + out.endArray(); + out.endObject(); + } + }); + } + } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent resultData) { + InputStream in = null; + OutputStream out = null; super.onActivityResult(requestCode, resultCode, resultData); if (resultCode == RESULT_OK) { - Uri data = resultData.getData(); try { - try (InputStream in = getContentResolver().openInputStream(data)) { - try (OutputStream out = new FileOutputStream(outputFile)) { + if(resultData.getClipData() != null) { // checking multiple selection or not + data = new Uri[resultData.getClipData().getItemCount()]; + for(int i = 0; i < resultData.getClipData().getItemCount(); i++) { + data[i] = resultData.getClipData().getItemAt(i).getUri(); + } + } else { + data = new Uri[1]; + data[0] = resultData.getData(); + } + if (!folder && outputFile != null) { + for (int i = 0; i < data.length; i++) { + in = getContentResolver().openInputStream(data[i]); + out = new FileOutputStream(multiple ? String.format(outputFile, i) : outputFile); byte[] buffer = new byte[8192]; while (true) { int read = in.read(buffer); @@ -71,15 +151,48 @@ protected void onActivityResult(int requestCode, int resultCode, Intent resultDa out.write(buffer, 0, read); } } + in.close(); + out.close(); } } - } catch (IOException e) { - TermuxApiLogger.error("Error copying " + data + " to " + outputFile); + + } catch (Exception e) { + TermuxApiLogger.error("Error copying file(s). "); + error = ERROR_COPY_FILE; + } finally { + try { if (in != null) { in.close(); } } catch (Exception e) { } + try { if (out != null) { out.close(); } } catch (Exception e) { } } } - finish(); + if (async) { + if (json) { + ResultReturner.returnData(this, mIntent, new ResultReturner.ResultJsonWriter() { + @Override + public void writeJson(JsonWriter out) throws Exception { + out.beginObject(); + out.name("error").value(error); + out.name("uri").beginArray(); + if (data != null) { + for (int i = 0; i < data.length; i++) { + out.value(data[i].toString()); + } + } + out.endArray(); + out.endObject(); + } + }); + } else { + ResultReturner.returnData(this, mIntent, output -> { + if (data != null) { + for (int i = 0; i < data.length; i++) { + output.println(data[i].toString()); + } + } + }); + } + } + finishAndRemoveTask(); } - } } From bae72acdee297e692c5ca29a91c2f7b6a3dae82e Mon Sep 17 00:00:00 2001 From: knyipab <46513942+knyipab@users.noreply.github.com> Date: Sun, 13 Mar 2022 22:11:39 +0800 Subject: [PATCH 2/2] fix wording --- app/src/main/java/com/termux/api/StorageGetAPI.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/termux/api/StorageGetAPI.java b/app/src/main/java/com/termux/api/StorageGetAPI.java index 539ae7ea9..4a171d3df 100644 --- a/app/src/main/java/com/termux/api/StorageGetAPI.java +++ b/app/src/main/java/com/termux/api/StorageGetAPI.java @@ -45,7 +45,7 @@ public void writeJson(JsonWriter out) throws Exception { } return; } - if (!intent.getBooleanExtra("async", false)) { + if (!intent.getBooleanExtra("wait", false)) { ResultReturner.returnData(apiReceiver, intent, out -> { }); } } @@ -54,7 +54,7 @@ public static class StorageActivity extends Activity { private String outputFile; private Intent mIntent; - private boolean async; + private boolean wait; private boolean folder; private boolean persist; private boolean multiple; @@ -70,7 +70,7 @@ public void onCreate(@Nullable Bundle savedInstanceState) { mIntent = intent.getParcelableExtra(INTENT_EXTRA); outputFile = mIntent.getStringExtra("file"); mimeType = mIntent.getStringExtra("type"); - async = mIntent.getBooleanExtra("async", false); + wait = mIntent.getBooleanExtra("wait", false); folder = mIntent.getBooleanExtra("folder", false); persist = mIntent.getBooleanExtra("persist", false); multiple = mIntent.getBooleanExtra("multiple", false); @@ -164,7 +164,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent resultDa try { if (out != null) { out.close(); } } catch (Exception e) { } } } - if (async) { + if (wait) { if (json) { ResultReturner.returnData(this, mIntent, new ResultReturner.ResultJsonWriter() { @Override