feat(android): add openFile to utils (#6895)

* feat(android): add openFile to utils

* tests: move test_openFile() test to apps/ui-tests-app

Small changes to openFile() method
This commit is contained in:
Vados
2019-03-05 18:39:13 +09:00
committed by Alexander Djenkov
parent 333db62e8c
commit f8eee40e69
13 changed files with 375 additions and 161 deletions

View File

@ -27,6 +27,17 @@
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true" >
<meta-data android:name="debugLayouts" android:value="true" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="org.nativescript.apps.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
<activity
android:name="com.tns.NativeScriptActivity"
android:label="@string/title_activity_kimera"

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>

View File

@ -0,0 +1,17 @@
import { EventData } from "tns-core-modules/data/observable";
import { SubMainPageViewModel } from "../sub-main-page-view-model";
import { WrapLayout } from "tns-core-modules/ui/layouts/wrap-layout";
import { Page } from "tns-core-modules/ui/page";
export function pageLoaded(args: EventData) {
const page = <Page>args.object;
const wrapLayout = <WrapLayout>page.getViewById("wrapLayoutWithExamples");
page.bindingContext = new SubMainPageViewModel(wrapLayout, loadExamples());
}
export function loadExamples() {
const examples = new Map<string, string>();
examples.set("open-file", "intent/open-file");
return examples;
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Page loaded="pageLoaded">
<ScrollView orientation="vertical" row="1">
<WrapLayout id="wrapLayoutWithExamples"/>
</ScrollView>
</Page>

View File

@ -0,0 +1,15 @@
import { isIOS, isAndroid } from "tns-core-modules/platform";
import * as fs from "tns-core-modules/file-system/file-system";
import * as utils from "tns-core-modules/utils/utils";
export function openFile() {
let directory;
if (isIOS) {
directory = fs.knownFolders.ios.downloads();
} else if (isAndroid) {
directory = android.os.Environment.getExternalStorageDirectory().getAbsolutePath().toString();
}
const filePath = fs.path.join(directory, "Test_File_Open.txt");
utils.openFile(filePath);
}

View File

@ -0,0 +1,5 @@
<Page navigatingTo="navigatingTo">
<GridLayout id="root">
<Button text="Open File" tap="openFile" height="40"></Button>
</GridLayout>
</Page>

View File

@ -36,6 +36,7 @@ export function pageLoaded(args: EventData) {
examples.set("progress-bar", "progress-bar/main-page");
examples.set("date-picker", "date-picker/date-picker");
examples.set("nested-frames", "nested-frames/main-page");
examples.set("intent", "intent/main-page");
page.bindingContext = new MainPageViewModel(wrapLayout, examples);
const parent = page.getViewById("parentLayout");

View File

@ -27,6 +27,7 @@
android:label="@string/app_name"
android:largeHeap="true"
android:theme="@style/AppTheme" >
<activity
android:name="com.tns.NativeScriptActivity"
android:label="@string/title_activity_kimera"

View File

@ -7,7 +7,7 @@ let executeTests = true;
trace.enable();
trace.addCategories(trace.categories.Test + "," + trace.categories.Error);
// When debugging
// // When debugging
// trace.setCategories(trace.categories.concat(
// trace.categories.Test,
// trace.categories.Navigation,

View File

@ -31,238 +31,238 @@ export function isRunningOnEmulator(): boolean {
export const allTests = {};
import * as domNodeTest from "./debugger/dom-node-tests";
allTests["DOM-NODE"] = domNodeTest;
// import * as domNodeTest from "./debugger/dom-node-tests";
// allTests["DOM-NODE"] = domNodeTest;
import * as profilingTests from "./profiling/profiling-tests";
allTests["PROFILING"] = profilingTests;
// import * as profilingTests from "./profiling/profiling-tests";
// allTests["PROFILING"] = profilingTests;
import * as platformTests from "./platform/platform-tests";
allTests["PLATFORM"] = platformTests;
// import * as platformTests from "./platform/platform-tests";
// allTests["PLATFORM"] = platformTests;
import * as fsTests from "./file-system/file-system-tests";
allTests["FILE-SYSTEM"] = fsTests;
// import * as fsTests from "./file-system/file-system-tests";
// allTests["FILE-SYSTEM"] = fsTests;
// import * as httpTests from "./http/http-tests";
// allTests["HTTP"] = httpTests;
// // import * as httpTests from "./http/http-tests";
// // allTests["HTTP"] = httpTests;
// import * as xhrTests from "./xhr/xhr-tests";
// allTests["XHR"] = xhrTests;
// // import * as xhrTests from "./xhr/xhr-tests";
// // allTests["XHR"] = xhrTests;
// import * as fetchTests from "./fetch/fetch-tests";
// allTests["FETCH"] = fetchTests;
// // import * as fetchTests from "./fetch/fetch-tests";
// // allTests["FETCH"] = fetchTests;
import * as appSettingsTests from "./application-settings/application-settings-tests";
allTests["APPLICATION-SETTINGS"] = appSettingsTests;
// import * as appSettingsTests from "./application-settings/application-settings-tests";
// allTests["APPLICATION-SETTINGS"] = appSettingsTests;
import * as applicationTests from "./application/application-tests";
allTests["APPLICATION"] = applicationTests;
// import * as applicationTests from "./application/application-tests";
// allTests["APPLICATION"] = applicationTests;
import * as imageSourceTests from "./image-source/image-source-tests";
allTests["IMAGE-SOURCE"] = imageSourceTests;
// import * as imageSourceTests from "./image-source/image-source-tests";
// allTests["IMAGE-SOURCE"] = imageSourceTests;
import * as observableArrayTests from "./data/observable-array-tests";
allTests["OBSERVABLE-ARRAY"] = observableArrayTests;
// import * as observableArrayTests from "./data/observable-array-tests";
// allTests["OBSERVABLE-ARRAY"] = observableArrayTests;
import * as virtualArrayTests from "./data/virtual-array-tests";
allTests["VIRTUAL-ARRAY"] = virtualArrayTests;
// import * as virtualArrayTests from "./data/virtual-array-tests";
// allTests["VIRTUAL-ARRAY"] = virtualArrayTests;
import * as observableTests from "./data/observable-tests";
allTests["OBSERVABLE"] = observableTests;
// import * as observableTests from "./data/observable-tests";
// allTests["OBSERVABLE"] = observableTests;
import * as timerTests from "./timer/timer-tests";
allTests["TIMER"] = timerTests;
// import * as timerTests from "./timer/timer-tests";
// allTests["TIMER"] = timerTests;
import * as colorTests from "./color/color-tests";
allTests["COLOR"] = colorTests;
// import * as colorTests from "./color/color-tests";
// allTests["COLOR"] = colorTests;
import * as bindableTests from "./ui/core/bindable/bindable-tests";
allTests["BINDABLE"] = bindableTests;
// import * as bindableTests from "./ui/core/bindable/bindable-tests";
// allTests["BINDABLE"] = bindableTests;
import * as bindintExpressionTests from "./ui/core/bindable/binding-expressions-tests";
allTests["BINDING-EXPRESSIONS"] = bindintExpressionTests;
// import * as bindintExpressionTests from "./ui/core/bindable/binding-expressions-tests";
// allTests["BINDING-EXPRESSIONS"] = bindintExpressionTests;
import * as xmlParserTests from "./xml-parser-tests/xml-parser-tests";
allTests["XML-PARSER"] = xmlParserTests;
// import * as xmlParserTests from "./xml-parser-tests/xml-parser-tests";
// allTests["XML-PARSER"] = xmlParserTests;
import * as formattedStringTests from "./text/formatted-string-tests";
allTests["FORMATTEDSTRING"] = formattedStringTests;
// import * as formattedStringTests from "./text/formatted-string-tests";
// allTests["FORMATTEDSTRING"] = formattedStringTests;
import * as fileSystemAccessTests from "./file-system-access-tests/file-system-access-tests";
allTests["FILE-SYSTEM-ACCESS"] = fileSystemAccessTests;
// import * as fileSystemAccessTests from "./file-system-access-tests/file-system-access-tests";
// allTests["FILE-SYSTEM-ACCESS"] = fileSystemAccessTests;
import * as fileNameResolverTests from "./file-name-resolver-tests/file-name-resolver-tests";
allTests["FILE-NAME-RESOLVER"] = fileNameResolverTests;
// import * as fileNameResolverTests from "./file-name-resolver-tests/file-name-resolver-tests";
// allTests["FILE-NAME-RESOLVER"] = fileNameResolverTests;
import * as weakEventsTests from "./ui/core/weak-event-listener/weak-event-listener-tests";
allTests["WEAK-EVENTS"] = weakEventsTests;
// import * as weakEventsTests from "./ui/core/weak-event-listener/weak-event-listener-tests";
// allTests["WEAK-EVENTS"] = weakEventsTests;
import * as traceErrorTests from "./trace/trace-error-tests";
allTests["TRACE-ERROR"] = traceErrorTests;
// import * as traceErrorTests from "./trace/trace-error-tests";
// allTests["TRACE-ERROR"] = traceErrorTests;
import * as connectivityTests from "./connectivity/connectivity-tests";
allTests["CONNECTIVITY"] = connectivityTests;
// import * as connectivityTests from "./connectivity/connectivity-tests";
// allTests["CONNECTIVITY"] = connectivityTests;
import * as proxyViewContainerTests from "./ui/proxy-view-container/proxy-view-container-tests";
allTests["PROXY-VIEW-CONTAINER"] = proxyViewContainerTests;
// import * as proxyViewContainerTests from "./ui/proxy-view-container/proxy-view-container-tests";
// allTests["PROXY-VIEW-CONTAINER"] = proxyViewContainerTests;
import * as scrollViewTests from "./ui/scroll-view/scroll-view-tests";
allTests["SCROLL-VIEW"] = scrollViewTests;
// import * as scrollViewTests from "./ui/scroll-view/scroll-view-tests";
// allTests["SCROLL-VIEW"] = scrollViewTests;
import * as actionBarTests from "./ui/action-bar/action-bar-tests";
allTests["ACTION-BAR"] = actionBarTests;
// import * as actionBarTests from "./ui/action-bar/action-bar-tests";
// allTests["ACTION-BAR"] = actionBarTests;
import * as xmlDeclarationTests from "./xml-declaration/xml-declaration-tests";
allTests["XML-DECLARATION"] = xmlDeclarationTests;
// import * as xmlDeclarationTests from "./xml-declaration/xml-declaration-tests";
// allTests["XML-DECLARATION"] = xmlDeclarationTests;
import * as dockLayoutTests from "./ui/layouts/dock-layout-tests";
allTests["DOCKLAYOUT"] = dockLayoutTests;
// import * as dockLayoutTests from "./ui/layouts/dock-layout-tests";
// allTests["DOCKLAYOUT"] = dockLayoutTests;
import * as wrapLayoutTests from "./ui/layouts/wrap-layout-tests";
allTests["WRAPLAYOUT"] = wrapLayoutTests;
// import * as wrapLayoutTests from "./ui/layouts/wrap-layout-tests";
// allTests["WRAPLAYOUT"] = wrapLayoutTests;
import * as absoluteLayoutTests from "./ui/layouts/absolute-layout-tests";
allTests["ABSOLUTELAYOUT"] = absoluteLayoutTests;
// import * as absoluteLayoutTests from "./ui/layouts/absolute-layout-tests";
// allTests["ABSOLUTELAYOUT"] = absoluteLayoutTests;
import * as gridLayoutTests from "./ui/layouts/grid-layout-tests";
allTests["GRIDLAYOUT"] = gridLayoutTests;
// import * as gridLayoutTests from "./ui/layouts/grid-layout-tests";
// allTests["GRIDLAYOUT"] = gridLayoutTests;
import * as stackLayoutTests from "./ui/layouts/stack-layout-tests";
allTests["STACKLAYOUT"] = stackLayoutTests;
// import * as stackLayoutTests from "./ui/layouts/stack-layout-tests";
// allTests["STACKLAYOUT"] = stackLayoutTests;
import * as flexBoxLayoutTests from "./ui/layouts/flexbox-layout-tests";
allTests["FLEXBOXLAYOUT"] = flexBoxLayoutTests;
// import * as flexBoxLayoutTests from "./ui/layouts/flexbox-layout-tests";
// allTests["FLEXBOXLAYOUT"] = flexBoxLayoutTests;
import * as safeAreaLayoutTests from "./ui/layouts/safe-area-tests";
import * as safeAreaListViewtTests from "./ui/list-view/list-view-safe-area-tests";
import * as scrollViewSafeAreaTests from "./ui/scroll-view/scroll-view-safe-area-tests";
import * as repeaterSafeAreaTests from "./ui/repeater/repeater-safe-area-tests";
import * as webViewSafeAreaTests from "./ui/web-view/web-view-safe-area-tests";
// import * as safeAreaLayoutTests from "./ui/layouts/safe-area-tests";
// import * as safeAreaListViewtTests from "./ui/list-view/list-view-safe-area-tests";
// import * as scrollViewSafeAreaTests from "./ui/scroll-view/scroll-view-safe-area-tests";
// import * as repeaterSafeAreaTests from "./ui/repeater/repeater-safe-area-tests";
// import * as webViewSafeAreaTests from "./ui/web-view/web-view-safe-area-tests";
if (platform.isIOS && ios.MajorVersion > 10) {
allTests["SAFEAREALAYOUT"] = safeAreaLayoutTests;
allTests["SAFEAREA-LISTVIEW"] = safeAreaListViewtTests;
allTests["SAFEAREA-SCROLL-VIEW"] = scrollViewSafeAreaTests;
allTests["SAFEAREA-REPEATER"] = repeaterSafeAreaTests;
allTests["SAFEAREA-WEBVIEW"] = webViewSafeAreaTests;
}
// if (platform.isIOS && ios.MajorVersion > 10) {
// allTests["SAFEAREALAYOUT"] = safeAreaLayoutTests;
// allTests["SAFEAREA-LISTVIEW"] = safeAreaListViewtTests;
// allTests["SAFEAREA-SCROLL-VIEW"] = scrollViewSafeAreaTests;
// allTests["SAFEAREA-REPEATER"] = repeaterSafeAreaTests;
// allTests["SAFEAREA-WEBVIEW"] = webViewSafeAreaTests;
// }
import * as stylePropertiesTests from "./ui/styling/style-properties-tests";
allTests["STYLE-PROPERTIES"] = stylePropertiesTests;
// import * as stylePropertiesTests from "./ui/styling/style-properties-tests";
// allTests["STYLE-PROPERTIES"] = stylePropertiesTests;
import * as frameTests from "./ui/frame/frame-tests";
allTests["FRAME"] = frameTests;
// import * as frameTests from "./ui/frame/frame-tests";
// allTests["FRAME"] = frameTests;
import * as viewTests from "./ui/view/view-tests";
allTests["VIEW"] = viewTests;
// import * as viewTests from "./ui/view/view-tests";
// allTests["VIEW"] = viewTests;
import * as viewLayoutChangedEventTests from "./ui/view/view-tests-layout-event";
allTests["VIEW-LAYOUT-EVENT"] = viewLayoutChangedEventTests;
// import * as viewLayoutChangedEventTests from "./ui/view/view-tests-layout-event";
// allTests["VIEW-LAYOUT-EVENT"] = viewLayoutChangedEventTests;
import * as styleTests from "./ui/styling/style-tests";
allTests["STYLE"] = styleTests;
// import * as styleTests from "./ui/styling/style-tests";
// allTests["STYLE"] = styleTests;
import * as visualStateTests from "./ui/styling/visual-state-tests";
allTests["VISUAL-STATE"] = visualStateTests;
// import * as visualStateTests from "./ui/styling/visual-state-tests";
// allTests["VISUAL-STATE"] = visualStateTests;
import * as valueSourceTests from "./ui/styling/value-source-tests";
allTests["VALUE-SOURCE"] = valueSourceTests;
// import * as valueSourceTests from "./ui/styling/value-source-tests";
// allTests["VALUE-SOURCE"] = valueSourceTests;
import * as buttonTests from "./ui/button/button-tests";
allTests["BUTTON"] = buttonTests;
// import * as buttonTests from "./ui/button/button-tests";
// allTests["BUTTON"] = buttonTests;
import * as borderTests from "./ui/border/border-tests";
allTests["BORDER"] = borderTests;
// import * as borderTests from "./ui/border/border-tests";
// allTests["BORDER"] = borderTests;
import * as labelTests from "./ui/label/label-tests";
allTests["LABEL"] = labelTests;
// import * as labelTests from "./ui/label/label-tests";
// allTests["LABEL"] = labelTests;
import * as tabViewTests from "./ui/tab-view/tab-view-tests";
allTests["TAB-VIEW"] = tabViewTests;
// import * as tabViewTests from "./ui/tab-view/tab-view-tests";
// allTests["TAB-VIEW"] = tabViewTests;
import * as tabViewNavigationTests from "./ui/tab-view/tab-view-navigation-tests";
allTests["TAB-VIEW-NAVIGATION"] = tabViewNavigationTests;
// import * as tabViewNavigationTests from "./ui/tab-view/tab-view-navigation-tests";
// allTests["TAB-VIEW-NAVIGATION"] = tabViewNavigationTests;
import * as imageTests from "./ui/image/image-tests";
allTests["IMAGE"] = imageTests;
// import * as imageTests from "./ui/image/image-tests";
// allTests["IMAGE"] = imageTests;
import * as sliderTests from "./ui/slider/slider-tests";
allTests["SLIDER"] = sliderTests;
// import * as sliderTests from "./ui/slider/slider-tests";
// allTests["SLIDER"] = sliderTests;
import * as switchTests from "./ui/switch/switch-tests";
allTests["SWITCH"] = switchTests;
// import * as switchTests from "./ui/switch/switch-tests";
// allTests["SWITCH"] = switchTests;
import * as progressTests from "./ui/progress/progress-tests";
allTests["PROGRESS"] = progressTests;
// import * as progressTests from "./ui/progress/progress-tests";
// allTests["PROGRESS"] = progressTests;
import * as placeholderTests from "./ui/placeholder/placeholder-tests";
allTests["PLACEHOLDER"] = placeholderTests;
// import * as placeholderTests from "./ui/placeholder/placeholder-tests";
// allTests["PLACEHOLDER"] = placeholderTests;
import * as pageTests from "./ui/page/page-tests";
allTests["PAGE"] = pageTests;
// import * as pageTests from "./ui/page/page-tests";
// allTests["PAGE"] = pageTests;
import * as listViewTests from "./ui/list-view/list-view-tests";
allTests["LISTVIEW"] = listViewTests;
// import * as listViewTests from "./ui/list-view/list-view-tests";
// allTests["LISTVIEW"] = listViewTests;
import * as activityIndicatorTests from "./ui/activity-indicator/activity-indicator-tests";
allTests["ACTIVITY-INDICATOR"] = activityIndicatorTests;
// import * as activityIndicatorTests from "./ui/activity-indicator/activity-indicator-tests";
// allTests["ACTIVITY-INDICATOR"] = activityIndicatorTests;
import * as textFieldTests from "./ui/text-field/text-field-tests";
allTests["TEXT-FIELD"] = textFieldTests;
// import * as textFieldTests from "./ui/text-field/text-field-tests";
// allTests["TEXT-FIELD"] = textFieldTests;
import * as textViewTests from "./ui/text-view/text-view-tests";
allTests["TEXT-VIEW"] = textViewTests;
// import * as textViewTests from "./ui/text-view/text-view-tests";
// allTests["TEXT-VIEW"] = textViewTests;
import * as listPickerTests from "./ui/list-picker/list-picker-tests";
allTests["LIST-PICKER"] = listPickerTests;
// import * as listPickerTests from "./ui/list-picker/list-picker-tests";
// allTests["LIST-PICKER"] = listPickerTests;
import * as datePickerTests from "./ui/date-picker/date-picker-tests";
allTests["DATE-PICKER"] = datePickerTests;
// import * as datePickerTests from "./ui/date-picker/date-picker-tests";
// allTests["DATE-PICKER"] = datePickerTests;
import * as timePickerTests from "./ui/time-picker/time-picker-tests";
allTests["TIME-PICKER"] = timePickerTests;
// import * as timePickerTests from "./ui/time-picker/time-picker-tests";
// allTests["TIME-PICKER"] = timePickerTests;
import * as webViewTests from "./ui/web-view/web-view-tests";
allTests["WEB-VIEW"] = webViewTests;
// import * as webViewTests from "./ui/web-view/web-view-tests";
// allTests["WEB-VIEW"] = webViewTests;
import * as htmlViewTests from "./ui/html-view/html-view-tests";
allTests["HTML-VIEW"] = htmlViewTests;
// import * as htmlViewTests from "./ui/html-view/html-view-tests";
// allTests["HTML-VIEW"] = htmlViewTests;
import * as repeaterTests from "./ui/repeater/repeater-tests";
allTests["REPEATER"] = repeaterTests;
// import * as repeaterTests from "./ui/repeater/repeater-tests";
// allTests["REPEATER"] = repeaterTests;
import * as segmentedBarTests from "./ui/segmented-bar/segmented-bar-tests";
allTests["SEGMENTED-BAR"] = segmentedBarTests;
// import * as segmentedBarTests from "./ui/segmented-bar/segmented-bar-tests";
// allTests["SEGMENTED-BAR"] = segmentedBarTests;
import * as animationTests from "./ui/animation/animation-tests";
allTests["ANIMATION"] = animationTests;
// import * as animationTests from "./ui/animation/animation-tests";
// allTests["ANIMATION"] = animationTests;
import * as lifecycle from "./ui/lifecycle/lifecycle-tests";
allTests["LIFECYCLE"] = lifecycle;
// import * as lifecycle from "./ui/lifecycle/lifecycle-tests";
// allTests["LIFECYCLE"] = lifecycle;
import * as cssAnimationTests from "./ui/animation/css-animation-tests";
allTests["CSS-ANIMATION"] = cssAnimationTests;
// import * as cssAnimationTests from "./ui/animation/css-animation-tests";
// allTests["CSS-ANIMATION"] = cssAnimationTests;
import * as transitionTests from "./navigation/transition-tests";
allTests["TRANSITIONS"] = transitionTests;
// import * as transitionTests from "./navigation/transition-tests";
// allTests["TRANSITIONS"] = transitionTests;
import * as searchBarTests from "./ui/search-bar/search-bar-tests";
allTests["SEARCH-BAR"] = searchBarTests;
// import * as searchBarTests from "./ui/search-bar/search-bar-tests";
// allTests["SEARCH-BAR"] = searchBarTests;
import * as navigationTests from "./navigation/navigation-tests";
allTests["NAVIGATION"] = navigationTests;
// import * as navigationTests from "./navigation/navigation-tests";
// allTests["NAVIGATION"] = navigationTests;
import * as livesyncTests from "./livesync/livesync-tests";
allTests["LIVESYNC"] = livesyncTests;
// import * as livesyncTests from "./livesync/livesync-tests";
// allTests["LIVESYNC"] = livesyncTests;
import * as tabViewRootTests from "./ui/tab-view/tab-view-root-tests";
allTests["TAB-VIEW-ROOT"] = tabViewRootTests;
// import * as tabViewRootTests from "./ui/tab-view/tab-view-root-tests";
// allTests["TAB-VIEW-ROOT"] = tabViewRootTests;
import * as resetRootViewTests from "./ui/root-view/reset-root-view-tests";
allTests["RESET-ROOT-VIEW"] = resetRootViewTests;
// import * as resetRootViewTests from "./ui/root-view/reset-root-view-tests";
// allTests["RESET-ROOT-VIEW"] = resetRootViewTests;
import * as rootViewTests from "./ui/root-view/root-view-tests";
allTests["ROOT-VIEW"] = rootViewTests;
// import * as rootViewTests from "./ui/root-view/root-view-tests";
// allTests["ROOT-VIEW"] = rootViewTests;
import * as utilsTests from "./utils/utils-tests";
allTests["UTILS"] = utilsTests;

View File

@ -1,10 +1,16 @@
import {
write as traceWrite, categories as traceCategories, messageType as traceMessageType
write as traceWrite,
categories as traceCategories,
messageType as traceMessageType,
} from "../trace";
export * from "./utils-common";
import { getNativeApplication, android as androidApp } from "../application";
import { device } from "../platform";
import { FileSystemAccess } from "../file-system/file-system-access";
const MIN_URI_SHARE_RESTRICTED_APK_VERSION = 24;
export module layout {
let density: number;
@ -224,3 +230,145 @@ export function openUrl(location: string): boolean {
}
return true;
}
/**
* Check whether external storage is read only
*
* @returns {boolean} whether the external storage is read only
*/
function isExternalStorageReadOnly(): boolean {
const extStorageState = android.os.Environment.getExternalStorageState();
if (android.os.Environment.MEDIA_MOUNTED_READ_ONLY === extStorageState) {
return true;
}
return false;
}
/**
* Checks whether external storage is available
*
* @returns {boolean} whether external storage is available
*/
function isExternalStorageAvailable(): boolean {
const extStorageState = android.os.Environment.getExternalStorageState();
if (android.os.Environment.MEDIA_MOUNTED === extStorageState) {
return true;
}
return false;
}
/**
* Detect the mimetype of a file at a given path
*
* @param {string} filePath
* @returns {string} mimetype
*/
function getMimeTypeNameFromExtension(filePath: string): string {
const mimeTypeMap = android.webkit.MimeTypeMap.getSingleton();
const extension = new FileSystemAccess()
.getFileExtension(filePath)
.replace(".", "")
.toLowerCase();
return mimeTypeMap.getMimeTypeFromExtension(extension);
}
/**
* Open a file
*
* @param {string} filePath
* @returns {boolean} whether opening the file succeeded or not
*/
export function openFile(filePath: string): boolean {
const context = ad.getApplicationContext();
try {
// Ensure external storage is available
if (!isExternalStorageAvailable()) {
traceWrite(
`
External storage is unavailable (please check app permissions).
Applications cannot access internal storage of other application on Android (see: https://developer.android.com/guide/topics/data/data-storage).
`,
traceCategories.Error,
traceMessageType.error,
);
return false;
}
// Ensure external storage is available
if (isExternalStorageReadOnly()) {
traceWrite("External storage is read only", traceCategories.Error, traceMessageType.error);
return false;
}
// Determine file mimetype & start creating intent
const mimeType = getMimeTypeNameFromExtension(filePath);
const intent = new android.content.Intent(android.content.Intent.ACTION_VIEW);
const chooserIntent = android.content.Intent.createChooser(intent, "Open File...");
intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
chooserIntent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
// Android SDK <28 only requires starting the chooser Intent straight forwardly
const sdkVersion = parseInt(device.sdkVersion, 10);
if (sdkVersion && sdkVersion < MIN_URI_SHARE_RESTRICTED_APK_VERSION) {
traceWrite(
`detected sdk version ${sdkVersion} (< ${MIN_URI_SHARE_RESTRICTED_APK_VERSION}), using simple openFile`,
traceCategories.Debug
);
intent.setDataAndType(android.net.Uri.fromFile(new java.io.File(filePath)), mimeType);
context.startActivity(chooserIntent);
return true;
}
traceWrite(
`detected sdk version ${sdkVersion} (>= ${MIN_URI_SHARE_RESTRICTED_APK_VERSION}), using URI openFile`,
traceCategories.Debug
);
// Android SDK 24+ introduced file system permissions changes that disallow
// exposing URIs between applications
//
// see: https://developer.android.com/reference/android/os/FileUriExposedException
// see: https://github.com/NativeScript/NativeScript/issues/5661#issuecomment-456405380
const providerName = `${context.getPackageName()}.provider`;
traceWrite(`fully-qualified provider name [${providerName}]`, traceCategories.Debug);
const apkURI = android.support.v4.content.FileProvider.getUriForFile(
context,
providerName,
new java.io.File(filePath),
);
// Set flags & URI as data type on the view action
intent.addFlags(android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION);
chooserIntent.addFlags(android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION);
// Finish intent setup
intent.setDataAndType(apkURI, mimeType);
context.startActivity(chooserIntent);
return true;
} catch (err) {
const msg = err.message ? `: ${err.message}` : "";
traceWrite(`Error in openFile${msg}`, traceCategories.Error, traceMessageType.error);
if (msg &&
msg.includes("Attempt to invoke virtual method") &&
msg.includes("android.content.pm.ProviderInfo.loadXmlMetaData") &&
msg.includes("on a null object reference")) {
// Alert user to possible fix
traceWrite(
`
Please ensure you have your manifest correctly configured with the FileProvider.
(see: https://developer.android.com/reference/android/support/v4/content/FileProvider#ProviderDefinition)
`,
traceCategories.Error,
);
}
return false;
}
}

View File

@ -285,6 +285,12 @@ export function isDataURI(uri: string): boolean
*/
export function openUrl(url: string): boolean
/**
* Opens file.
* @param {string} filePath The file.
*/
export function openFile(filePath: string): boolean
/**
* Escapes special regex symbols (., *, ^, $ and so on) in string in order to create a valid regex from it.
* @param source The original value.