-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
194 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# cordova-plugin-save-dialog | ||
|
||
This Cordova plugin for Android displays the native Save dialog which allows users to store a file in the selected location. The plugin utilizes the Storage Access Framework to save a file in a user-selected location as described in the [Android developer guide](https://developer.android.com/training/data-storage/shared/documents-files#create-file). Platforms other than Android are not supported currently. | ||
|
||
## Installation | ||
|
||
``` | ||
cordova plugin add cordova-plugin-save-dialog --save | ||
``` | ||
|
||
## API | ||
|
||
The plugin’s functionality is accessible through the object `cordova.plugins.saveDialog`. | ||
|
||
### saveFile | ||
|
||
Call this method to open the Save dialog and store raw contents in a file. The method accepts two arguments: | ||
|
||
* file contents as a Blob instance, | ||
* optional file name to display on default (the user may change it manually though). | ||
|
||
To construct a Blob representation for a file contents, either use the [Blob constructor](https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob) directly: | ||
|
||
```javascript | ||
let blob = new Blob(["file contents"], {type: "text/plain"}); | ||
let fileName = "my-file.txt"; | ||
cordova.plugins.saveDialog.saveFile(blob, fileName).then(() => { | ||
console.info("The file has been successfully saved"); | ||
}).catch(reason => { | ||
console.warn(reason); | ||
}); | ||
``` | ||
|
||
or apply other methods of blob generation (such as [Response.blob()](https://developer.mozilla.org/en-US/docs/Web/API/Response/blob) for a network-fetched content): | ||
|
||
```javascript | ||
try { | ||
let response = await fetch(`https://avatars.dicebear.com/api/avataaars/${Math.random()}.svg`); | ||
let blob = await response.blob(); | ||
await cordova.plugins.saveDialog.saveFile(blob, "random-avatar.svg"); | ||
} catch (e) { | ||
console.error(e); | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"name": "cordova-plugin-save-dialog", | ||
"version": "0.1.0", | ||
"description": "Cordova plugin for Android to display the native Save dialog and store a file in the selected location", | ||
"main": "index.js", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/Amphiluke/cordova-plugin-save-dialog.git" | ||
}, | ||
"keywords": [ | ||
"ecosystem:cordova", | ||
"cordova-android", | ||
"save", | ||
"dialog" | ||
], | ||
"author": "Amphiluke", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/Amphiluke/cordova-plugin-save-dialog/issues" | ||
}, | ||
"homepage": "https://github.com/Amphiluke/cordova-plugin-save-dialog#readme" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" id="cordova-plugin-save-dialog" version="0.1.0"> | ||
<name>Save Dialog</name> | ||
<description>Cordova plugin for Android to display the native Save dialog and store a file in the selected location</description> | ||
<license>MIT</license> | ||
<keywords>cordova,save,dialog</keywords> | ||
<js-module src="www/save-dialog.js" name="SaveDialog"> | ||
<clobbers target="cordova.plugins.saveDialog" /> | ||
</js-module> | ||
|
||
<platform name="android"> | ||
<config-file target="res/xml/config.xml" parent="/*"> | ||
<feature name="SaveDialog" > | ||
<param name="android-package" value="io.github.amphiluke.SaveDialog"/> | ||
</feature> | ||
</config-file> | ||
<source-file src="src/android/SaveDialog.java" target-dir="src/io/github/amphiluke" /> | ||
</platform> | ||
</plugin> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package io.github.amphiluke; | ||
|
||
import android.app.Activity; | ||
import android.content.Intent; | ||
import android.net.Uri; | ||
import android.os.Bundle; | ||
import android.os.ParcelFileDescriptor; | ||
// import android.provider.DocumentsContract; | ||
import android.util.Base64; | ||
|
||
import org.apache.cordova.CallbackContext; | ||
import org.apache.cordova.CordovaPlugin; | ||
|
||
import org.json.JSONArray; | ||
import org.json.JSONException; | ||
|
||
import java.io.FileOutputStream; | ||
|
||
public class SaveDialog extends CordovaPlugin { | ||
private static final int LOCATE_FILE = 1; | ||
|
||
private CallbackContext callbackContext; | ||
|
||
@Override | ||
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { | ||
this.callbackContext = callbackContext; | ||
if (action.equals("locateFile")) { | ||
this.locateFile(args.getString(0), args.getString(1)); | ||
} else if (action.equals("saveFile")) { | ||
this.saveFile(Uri.parse(args.getString(0)), args.getString(1)); | ||
} else { | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
private void locateFile(String type, String name) { | ||
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); | ||
intent.addCategory(Intent.CATEGORY_OPENABLE); | ||
intent.setType(type); | ||
intent.putExtra(Intent.EXTRA_TITLE, name); | ||
// TODO Optionally, specify a URI for the directory that should be opened in | ||
// the system file picker when your app creates the document. | ||
// intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri); | ||
cordova.startActivityForResult(this, intent, SaveDialog.LOCATE_FILE); | ||
} | ||
|
||
@Override | ||
public void onActivityResult(int requestCode, int resultCode, Intent resultData) { | ||
if (requestCode == SaveDialog.LOCATE_FILE && this.callbackContext != null) { | ||
if (resultCode == Activity.RESULT_CANCELED) { | ||
this.callbackContext.error("The dialog has been cancelled"); | ||
} else if (resultCode == Activity.RESULT_OK && resultData != null) { | ||
Uri uri = resultData.getData(); | ||
this.callbackContext.success(uri.toString()); | ||
} else { | ||
this.callbackContext.error("Unknown error"); | ||
} | ||
} | ||
} | ||
|
||
public void onRestoreStateForActivityResult(Bundle state, CallbackContext callbackContext) { | ||
this.callbackContext = callbackContext; | ||
} | ||
|
||
private void saveFile(Uri uri, String data) { | ||
try { | ||
byte[] rawData = Base64.decode(data, Base64.DEFAULT); | ||
ParcelFileDescriptor pfd = cordova.getActivity().getContentResolver().openFileDescriptor(uri, "w"); | ||
FileOutputStream fileOutputStream = new FileOutputStream(pfd.getFileDescriptor()); | ||
try { | ||
fileOutputStream.write(rawData); | ||
this.callbackContext.success(); | ||
} catch (Exception e) { | ||
this.callbackContext.error(e.getMessage()); | ||
e.printStackTrace(); | ||
} finally { | ||
fileOutputStream.close(); | ||
pfd.close(); | ||
} | ||
} catch (Exception e) { | ||
this.callbackContext.error(e.getMessage()); | ||
e.printStackTrace(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
let exec = require("cordova/exec"); | ||
let moduleMapper = require("cordova/modulemapper"); | ||
let FileReader = moduleMapper.getOriginalSymbol(window, "FileReader") || window.FileReader; | ||
|
||
module.exports = { | ||
saveFile(blob, name = "") { | ||
return new Promise((resolve, reject) => { | ||
exec(resolve, reject, "SaveDialog", "locateFile", [blob.type || "application/octet-stream", name]); | ||
}).then(uri => { | ||
let reader = new FileReader(); | ||
reader.onload = () => { | ||
exec(resolve, reject, "SaveDialog", "saveFile", [uri, reader.result]); | ||
}; | ||
reader.onerror = () => { | ||
reject(reader.error); | ||
}; | ||
reader.onabort = () => { | ||
reject("Blob reading has been aborted"); | ||
}; | ||
reader.readAsArrayBuffer(blob); | ||
}); | ||
} | ||
}; |