Skip to content

Commit a88ff19

Browse files
committed
update: handle permissions changes when targeting API 34
1 parent 283005f commit a88ff19

File tree

4 files changed

+101
-91
lines changed

4 files changed

+101
-91
lines changed

apps/demo/src/plugin-demos/nativescript-filepicker.ts

Lines changed: 84 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable @nrwl/nx/enforce-module-boundaries */
12
import { EventData, Page, File, Frame, StackLayout, Color, Label, Image, alert, isAndroid, Device } from '@nativescript/core';
23
import { DemoSharedNativescriptFilepicker } from '@demo/shared';
34
import { filePicker, galleryPicker, MediaType, getFreeMBs } from '@voicethread/nativescript-filepicker';
@@ -9,83 +10,6 @@ export function navigatingTo(args: EventData) {
910
page.bindingContext = new DemoModel();
1011
}
1112
export class DemoModel extends DemoSharedNativescriptFilepicker {
12-
async pickDoc() {
13-
let pickedFiles: File[];
14-
try {
15-
pickedFiles = await filePicker(MediaType.DOCUMENT, false);
16-
} catch (err) {
17-
if (err) alert(err?.message);
18-
} finally {
19-
this.handleFiles(pickedFiles);
20-
}
21-
}
22-
23-
async pickImage() {
24-
let pickedFiles: File[];
25-
try {
26-
pickedFiles = await filePicker(MediaType.IMAGE, false);
27-
} catch (err) {
28-
if (err) alert(err?.message);
29-
} finally {
30-
this.handleFiles(pickedFiles);
31-
}
32-
}
33-
34-
async pickImages() {
35-
let pickedFiles: File[];
36-
try {
37-
pickedFiles = await filePicker(MediaType.IMAGE, true);
38-
} catch (err) {
39-
if (err) alert(err?.message);
40-
} finally {
41-
this.handleFiles(pickedFiles);
42-
}
43-
}
44-
45-
async pickVideo() {
46-
let pickedFiles: File[];
47-
48-
try {
49-
let tempPath = TempFile.getPath('tempfile', 'tmp');
50-
let freeSpace = getFreeMBs(tempPath);
51-
52-
console.log('free MBs on file picker temp directory', freeSpace);
53-
console.log('temp directory path: ', tempPath);
54-
if (freeSpace > 400) {
55-
//check before allowing picker to create temp copy of selected files
56-
pickedFiles = await filePicker(MediaType.VIDEO, false);
57-
} else alert('Low free space on device, picking not allowed');
58-
} catch (err) {
59-
if (err) alert(err?.message);
60-
} finally {
61-
this.handleFiles(pickedFiles);
62-
}
63-
}
64-
65-
async pickAudio() {
66-
let pickedFiles: File[];
67-
68-
try {
69-
pickedFiles = await filePicker(MediaType.AUDIO, false);
70-
} catch (err) {
71-
if (err) alert(err?.message);
72-
} finally {
73-
this.handleFiles(pickedFiles);
74-
}
75-
}
76-
77-
async pickArchive() {
78-
let pickedFiles: File[];
79-
80-
try {
81-
pickedFiles = await filePicker(MediaType.ARCHIVE, false);
82-
} catch (err) {
83-
if (err) alert(err?.message);
84-
} finally {
85-
this.handleFiles(pickedFiles);
86-
}
87-
}
88-
8913
async pickAllOne() {
9014
let pickedFiles: File[];
9115

@@ -116,8 +40,8 @@ export class DemoModel extends DemoSharedNativescriptFilepicker {
11640
});
11741
}
11842
console.log('canPick?:', canPick);
119-
} else if (isAndroid) {
120-
//just request external_storage perms otherwise
43+
} else if (isAndroid && +Device.sdkVersion < 26) {
44+
//request external_storage perms for API <26 devices when targeting API34+
12145
const result = await checkPermission('storage');
12246
if (result['storage'] != 'authorized') console.log('No storage permission, requesting...');
12347
await request('storage').then(result => {
@@ -164,8 +88,8 @@ export class DemoModel extends DemoSharedNativescriptFilepicker {
16488
});
16589
}
16690
console.log('canPick?:', canPick);
167-
} else if (isAndroid) {
168-
//just request external_storage perms otherwise
91+
} else if (isAndroid && +Device.sdkVersion < 26) {
92+
//request external_storage perms for API <26 devices when targeting API34+
16993
const result = await checkPermission('storage');
17094
if (result['storage'] != 'authorized') console.log('No storage permission, requesting...');
17195
await request('storage').then(result => {
@@ -203,6 +127,85 @@ export class DemoModel extends DemoSharedNativescriptFilepicker {
203127
});
204128
}
205129

130+
//The following examples may require permissions depending on the platform, OS version and build target,
131+
// check the Readme for more information or look at the examples above.
132+
async pickDoc() {
133+
let pickedFiles: File[];
134+
try {
135+
pickedFiles = await filePicker(MediaType.DOCUMENT, false);
136+
} catch (err) {
137+
if (err) alert(err?.message);
138+
} finally {
139+
this.handleFiles(pickedFiles);
140+
}
141+
}
142+
143+
async pickImage() {
144+
let pickedFiles: File[];
145+
try {
146+
pickedFiles = await filePicker(MediaType.IMAGE, false);
147+
} catch (err) {
148+
if (err) alert(err?.message);
149+
} finally {
150+
this.handleFiles(pickedFiles);
151+
}
152+
}
153+
154+
async pickImages() {
155+
let pickedFiles: File[];
156+
try {
157+
pickedFiles = await filePicker(MediaType.IMAGE, true);
158+
} catch (err) {
159+
if (err) alert(err?.message);
160+
} finally {
161+
this.handleFiles(pickedFiles);
162+
}
163+
}
164+
165+
async pickVideo() {
166+
let pickedFiles: File[];
167+
168+
try {
169+
const tempPath = TempFile.getPath('tempfile', 'tmp');
170+
const freeSpace = getFreeMBs(tempPath);
171+
172+
console.log('free MBs on file picker temp directory', freeSpace);
173+
console.log('temp directory path: ', tempPath);
174+
if (freeSpace > 400) {
175+
//check before allowing picker to create temp copy of selected files
176+
pickedFiles = await filePicker(MediaType.VIDEO, false);
177+
} else alert('Low free space on device, picking not allowed');
178+
} catch (err) {
179+
if (err) alert(err?.message);
180+
} finally {
181+
this.handleFiles(pickedFiles);
182+
}
183+
}
184+
185+
async pickAudio() {
186+
let pickedFiles: File[];
187+
188+
try {
189+
pickedFiles = await filePicker(MediaType.AUDIO, false);
190+
} catch (err) {
191+
if (err) alert(err?.message);
192+
} finally {
193+
this.handleFiles(pickedFiles);
194+
}
195+
}
196+
197+
async pickArchive() {
198+
let pickedFiles: File[];
199+
200+
try {
201+
pickedFiles = await filePicker(MediaType.ARCHIVE, false);
202+
} catch (err) {
203+
if (err) alert(err?.message);
204+
} finally {
205+
this.handleFiles(pickedFiles);
206+
}
207+
}
208+
206209
handleFiles(results: File[]): void {
207210
console.log('showed the picker, results:', results);
208211
const itemList: StackLayout = Frame.topmost().getViewById('pickedFiles');

apps/demo/src/plugin-demos/nativescript-filepicker.xml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
tap="{{ pickDoc }}"/>
1616
<Button text="Pick Image"
1717
tap="{{ pickImage }}"/>
18-
<Button text="Pick Image\n (Multiple - Android+iOS14+ only)"
18+
<Button text="Pick Image (Multiple - Android/iOS14+ only)"
1919
tap="{{ pickImages }}"
2020

2121
textWrap = "true"/>
@@ -27,10 +27,9 @@
2727
tap="{{ pickArchive }}"/>
2828
<Button text="Pick All"
2929
tap="{{ pickAllOne }}" />
30-
<Button text="Pick All\n (Multiple - Android+iOS14+ only)"
30+
<Button text="Pick All (Multiple - Android/iOS14+ only)"
3131
tap="{{ pickAll }}"
3232

33-
3433
textWrap = "true"/>
3534

3635
<Label text="iOS Gallery Picker - requests permission first (Android will just use filePicker internally)"

packages/nativescript-filepicker/README.md

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ try {
6969
7070
### Android Permissions
7171
72-
To request permissions in the demo app, we use the @nativescript-community [perms plugin](https://github.com/nativescript-community/perms). While this is not required for all OS versions and their system pickers, just to be safe you should request it so user is aware.
72+
To request permissions in the demo app, we use the @nativescript-community [perms plugin](https://github.com/nativescript-community/perms). What's actually required to be granted by the user depends on the target API version and the device API version.
7373
74-
Be sure to have permissions add the following lines in AndroidManifest.xml if targeting API 26+.
74+
If targeting API 25-33, be sure to have the legacy storage permission declared in your app by adding the following lines in AndroidManifest.xml.
7575
7676
```xml
7777
<manifest ... >
@@ -83,23 +83,30 @@ Be sure to have permissions add the following lines in AndroidManifest.xml if ta
8383
</manifest>
8484
```
8585
86-
For API 33+, you'll also need to add the following to the Android Manifest as well as request additional permissions:
86+
*NOTE*: When targeting API 34+, the legacy permission has been deprecated on devices running API 26-32, but still requires the user to grant for API <26 devices.
87+
88+
To request the legacy permission, use the following before opening the picker:
89+
```javascript
90+
request('storage');
91+
```
92+
93+
To support API 33+ devices, you'll also need to add the following to the Android Manifest and request the new permissions:
8794
8895
```xml
8996
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
9097
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
9198
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
9299
```
93100
94-
Before launching the picker on API 33+, you'll need to request the following permissions to allow picker access to all file types:
101+
Before launching the picker on API 33+ devices, you'll need to request the following permissions to allow picker access to all file types:
95102
96103
```javascript
97104
request('photo');
98105
request('video');
99106
request('audio');
100107
```
101108
102-
For an example, look at the `pickAll` function inside the `filepicker.ts` file in the dmeo app.
109+
For a working permissions example, look at the `pickAll` function inside the `filepicker.ts` file in the demo app.
103110
104111
### iOS Permissions
105112
@@ -131,13 +138,13 @@ Each platform natively supports a different set of file/mime types, you can see
131138
132139
The Android stock file picker also supports selecting files from Google Photos and Google Drive if you have an account signed in on the Android device. Other document provider apps installed on your device may also offer additional services.
133140
134-
Tested and working on Android API 25-33.
141+
Tested and working on Android API 25-34.
135142
136143
## iOS
137144
138145
The iOS pickers also support selecting files from an associated iCloud account if the user has signed in on the device. Note that for a production application, you'll need to add the iCloud capability to your iOS application, and register that entitlement via the Apple Developer site for that package id. After that, update the relevant keys as shown in the demo application's `Info.plist`.
139146
140-
Tested and working on iOS 12.x-16.x
147+
Tested and working on iOS 12.0-17.2
141148
142149
## Additional Utils
143150

packages/nativescript-filepicker/index.android.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable prefer-const */
12
import { MediaType } from './index.common';
23
import { AndroidApplication, AndroidActivityResultEventData, Application, Device, File, Utils } from '@nativescript/core';
34
import { TempFile } from './files';

0 commit comments

Comments
 (0)