Yes
Currently under iOS we can easily open a file by using utils.ios.openFile()
method. Under android there is no similar method. There should be a similar method for android enabling the user to open local files. Code similar to this can be used in order to achieve it:
https://github.com/PeterStaev/nativescript-telerik-reporting/blob/b57db9e79f4c4c7ef71fdb070cebd3063e106995/demo/app/main-page.ts#L85-L91
The only catch is that the file must be present on the external storage in order other apps to have access to it.
Android
@PeterStaev perhaps we can create an explicit check if there is an external storage access and implement the method with this as requrment (to be used only for files from external strorage).
For example somthing like:
// tns-core-modules/utils/utils.android.ts
export function openFile(filePath: string): boolean {
const context = ad.getApplicationContext();
try {
if (isExternalStorageAvailable() && !isExternalStorageReadOnly()) {
const fsa = new FileSystemAccess();
const mimeTypeMap = android.webkit.MimeTypeMap.getSingleton();
const mimeType = mimeTypeMap.getMimeTypeFromExtension(fsa.getFileExtension(filePath).replace(".", "").toLowerCase());
const intent = new android.content.Intent(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(android.net.Uri.fromFile(new java.io.File(filePath)), mimeType);
context.startActivity(android.content.Intent.createChooser(intent, "Open File..."));
return true;
} else {
// TODO: no external storage access logic
}
} catch(e) {
traceWrite("Error in openFile", traceCategories.Error, traceMessageType.error);
}
return false;
}
function isExternalStorageReadOnly(): boolean {
const extStorageState = android.os.Environment.getExternalStorageState();
if (android.os.Environment.MEDIA_MOUNTED_READ_ONLY === extStorageState) {
return true;
}
return false;
}
function isExternalStorageAvailable(): boolean {
const extStorageState = android.os.Environment.getExternalStorageState();
if (android.os.Environment.MEDIA_MOUNTED === extStorageState) {
return true;
}
return false;
}
Sounds good 馃憤 I guess in the else
we can traceWrite
something so it is clear to the user that they need to ensure the app has the appropriate permissions.
any update here?
This sounds like a good candidate for a PR extending the utils.android.ts module.
This issue is a good candidate for external contribution. Anyone interested can check out the contributing guide for more info on how to do that.
@NickIliev Your code works like a charm. However just faced some issues on Version 28 and above. Had to make a minor fix so just sharing the same with all.
if (isAndroid) {
const context = utils.ad.getApplicationContext();
try {
if (this.isExternalStorageAvailable() && !this.isExternalStorageReadOnly()) {
const fsa = new FileSystemAccess();
const mimeTypeMap = android.webkit.MimeTypeMap.getSingleton();
const mimeType =
mimeTypeMap.getMimeTypeFromExtension(fsa.getFileExtension(filePath).replace(".",
"").toLowerCase());
const intent = new android.content.Intent(android.content.Intent.ACTION_VIEW);
intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION);
const apkURI = android.support.v4.content.FileProvider.getUriForFile(context,
application.android.context.getApplicationContext().getPackageName() + ".provider" ,
new java.io.File(filePath))
//intent.setDataAndType(android.net.Uri.fromFile(new java.io.File(filePath)), mimeType);
intent.setDataAndType(apkURI, mimeType);
const chooserIntent = android.content.Intent.createChooser(intent, "Open File...");
chooserIntent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
chooserIntent.addFlags(android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(chooserIntent);
return true;
} else {
// TODO: no external storage access logic
}
} catch (e) {
console.log(e);
//traceWrite("Error in openFile", traceCategories.Error, traceMessageType.error);
}
return false;
}
Thanks to @NickIliev and @phatakrajan -- @ADjenkov just merged in the change that should make this a reality :)
And of course @PeterStaev for making the issue in the first place
Hi, is this available now?
Hi, checking tns-core-modules 5.4.0, this is still not available
Hey there: The method is here: https://github.com/NativeScript/NativeScript/blob/master/tns-core-modules/utils/utils.d.ts#L312
Thx for the new feature.
Problem: If I open a pdf file from downloads a list of all apps which can open a pdf file is opened.
If i select google pdf viewer, the file opens correctly. If I close and reopen, again I first have to select the google pdf viewer before the file opens. That is, it doesn't remember my choice. It misses an option to select that I want to use the selected app always, as I can when using e.g. the downloads app. Setting google pdf viewer in android settings to default is not an option, as it is disabled (grey). The same is true for the other pdf viewers I have installed.
P.S. The openFile feature is available with:
import {openFile} from "tns-core-modules/utils/utils"
@jokro thanks for finding that UX bug -- would you mind making a new ticket for it?
Most helpful comment
Thanks to @NickIliev and @phatakrajan -- @ADjenkov just merged in the change that should make this a reality :)
And of course @PeterStaev for making the issue in the first place