nativescript-mediafilepicker icon indicating copy to clipboard operation
nativescript-mediafilepicker copied to clipboard

Android 11: Custom File Picker not showing files

Open jajatismail opened this issue 3 years ago • 22 comments

The plugin can run normally as if there were no errors. But when the popup window appeared, there weren't any files listed.

Also I found this bug on Android 10. But there it can be solved by simply adding android:requestLegacyExternalStorage="true" to the manifest file. That way doesn't work on Android 11.

✔ Component nativescript has 7.0.10 version and is up to date. ✔ Component @nativescript/core has 7.0.11 version and is up to date. ✔ Component @nativescript/android has 7.0.0 version and is up to date.

jajatismail avatar Oct 21 '20 11:10 jajatismail

This is because of the new android scoped storage

Upd4ting avatar Dec 17 '20 16:12 Upd4ting

is it something that going to be solved? do I need to change something to support android 11?

kislasi avatar Mar 10 '21 13:03 kislasi

I have the same problem, it was working on 10 but no longer works on 11. Should we change configuration files?

giog12 avatar Apr 11 '21 13:04 giog12

I see that Google has set May 5th as the deadline for removing requestLegacyExternalStorage from the manifest. What to do?

sublime392 avatar Apr 16 '21 18:04 sublime392

Any update on this? Could anybody provide an alternative version of the plugin which allows to select arbitrary files?

SergeyMell avatar May 08 '21 16:05 SergeyMell

Any update to support android 11 for camera and file picker ?

itsmerockingagain avatar Jun 09 '21 03:06 itsmerockingagain

any update?

nituwda avatar Sep 12 '21 07:09 nituwda

This is because of the new android scoped storage

have you learned how to solve it?

nituwda avatar Sep 12 '21 09:09 nituwda

It doesn't work for me either with Android 11 SDK 30 I see that the official nativescript plugin https://github.com/NativeScript/plugins/tree/main/packages/imagepicker give solution in an update https://github.com/NativeScript / plugins / issues / 93

JonasLykkeIOspect commented on 22 Feb Hi. First of all, thanks for fixing the Android 11 problem. But its not "all done" yet :)

For it to work, you need to have a FileProvider in your AndroidManifest.

@NativeScript/camera comes with one. So if you're already using that one. Change line 160 in the index.android.js:

From: return FileProviderPackageName.FileProvider.getUriForFile(Application.android.context, Application.android.nativeApp.getPackageName() + '.fileprovider', file);

To: return FileProviderPackageName.FileProvider.getUriForFile(Application.android.context, Application.android.nativeApp.getPackageName() + '.provider', file);

'.provider' is the FileProvider that @NativeScript/camera makes. So you can reuse that.

This is a fix, until the plugin is updated with a FileProvider :)

xpalacincreditoh avatar Sep 13 '21 10:09 xpalacincreditoh

It doesn't work for me either with Android 11 SDK 30 I see that the official nativescript plugin https://github.com/NativeScript/plugins/tree/main/packages/imagepicker give solution in an update https://github.com/NativeScript / plugins / issues / 93

JonasLykkeIOspect commented on 22 Feb Hi. First of all, thanks for fixing the Android 11 problem. But its not "all done" yet :)

For it to work, you need to have a FileProvider in your AndroidManifest.

@NativeScript/camera comes with one. So if you're already using that one. Change line 160 in the index.android.js:

From: return FileProviderPackageName.FileProvider.getUriForFile(Application.android.context, Application.android.nativeApp.getPackageName() + '.fileprovider', file);

To: return FileProviderPackageName.FileProvider.getUriForFile(Application.android.context, Application.android.nativeApp.getPackageName() + '.provider', file);

'.provider' is the FileProvider that @NativeScript/camera makes. So you can reuse that.

This is a fix, until the plugin is updated with a FileProvider :)

how can u apply code from here? sorry im just so lost

nituwda avatar Sep 13 '21 11:09 nituwda

Hi, i´ve implemented this soloution, its working for me in mediafilepicker.android.js "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var observable_1 = require("tns-core-modules/data/observable"); var app = require("tns-core-modules/application"); var utils = require("tns-core-modules/utils/utils"); var permissions = require("nativescript-permissions"); const FILE = require("tns-core-modules/file-system"); const fs = require("tns-core-modules/file-system"); var AudioPickActivity = com.vincent.filepicker.activity.AudioPickActivity; var ImagePickActivity = com.vincent.filepicker.activity.ImagePickActivity; var NormalFilePickActivity = com.vincent.filepicker.activity.NormalFilePickActivity; var VideoPickActivity = com.vincent.filepicker.activity.VideoPickActivity; var Constant = com.vincent.filepicker.Constant; var Util = com.vincent.filepicker.Util; var Intent = android.content.Intent; var MediaStore = android.provider.MediaStore; var Environment = android.os.Environment; var File = java.io.File; var ContentValues = android.content.ContentValues; var Uri = android.net.Uri; var FileUtils = android.os.FileUtils; var Mediafilepicker = (function (_super) { __extends(Mediafilepicker, _super); function Mediafilepicker() { return _super.call(this) || this; } Mediafilepicker.prototype.openImagePicker = function (params) { var intent, pickerType, options = params.android; if (options.isCaptureMood) { this.performCapturing("image", options); return; } intent = new Intent( app.android.foregroundActivity, ImagePickActivity.class ); options.isNeedCamera ? intent.putExtra(ImagePickActivity.IS_NEED_CAMERA, true) : intent.putExtra(ImagePickActivity.IS_NEED_CAMERA, false); options.maxNumberFiles ? intent.putExtra(Constant.MAX_NUMBER, options.maxNumberFiles) : intent.putExtra(Constant.MAX_NUMBER, 99); options.isNeedFolderList ? intent.putExtra(ImagePickActivity.IS_NEED_FOLDER_LIST, true) : intent.putExtra(ImagePickActivity.IS_NEED_FOLDER_LIST, false); pickerType = Constant.REQUEST_CODE_PICK_IMAGE; this.callIntent(intent, pickerType); }; `` Mediafilepicker.prototype.openVideoPicker = function (params) { var intent, pickerType, options = params.android; if (options.isCaptureMood) { this.performCapturing("video", options); return; } intent = new Intent( app.android.foregroundActivity, VideoPickActivity.class ); options.isNeedCamera ? intent.putExtra(VideoPickActivity.IS_NEED_CAMERA, true) : intent.putExtra(VideoPickActivity.IS_NEED_CAMERA, false); options.maxNumberFiles ? intent.putExtra(Constant.MAX_NUMBER, options.maxNumberFiles) : intent.putExtra(Constant.MAX_NUMBER, 99); options.isNeedFolderList ? intent.putExtra(VideoPickActivity.IS_NEED_FOLDER_LIST, true) : intent.putExtra(VideoPickActivity.IS_NEED_FOLDER_LIST, false); if (options.maxDuration > 0) { intent.putExtra(Constant.MAX_VIDEO_DURATION, options.maxDuration); } intent.putExtra(Constant.VIDEO_QUALITY, 1); if (options.videoQuality === 0) { intent.putExtra(Constant.VIDEO_QUALITY, 0); } pickerType = Constant.REQUEST_CODE_PICK_VIDEO; this.callIntent(intent, pickerType); }; `` Mediafilepicker.prototype.openAudioPicker = function (params) { var intent, pickerType, options = params.android; if (options.isCaptureMood) { this.performCapturing("audio", options); return; } intent = new Intent( app.android.foregroundActivity, AudioPickActivity.class ); options.isNeedRecorder ? intent.putExtra(AudioPickActivity.IS_NEED_RECORDER, true) : intent.putExtra(AudioPickActivity.IS_NEED_RECORDER, false); options.maxNumberFiles ? intent.putExtra(Constant.MAX_NUMBER, options.maxNumberFiles) : intent.putExtra(Constant.MAX_NUMBER, 99); options.isNeedFolderList ? intent.putExtra(AudioPickActivity.IS_NEED_FOLDER_LIST, true) : intent.putExtra(AudioPickActivity.IS_NEED_FOLDER_LIST, false); if (options.maxSize > 0) { intent.putExtra(Constant.MAX_AUDIO_SIZE, options.maxSize); } intent.putExtra(AudioPickActivity.IS_TAKEN_AUTO_SELECTED, true); pickerType = Constant.REQUEST_CODE_PICK_AUDIO; this.callIntent(intent, pickerType); }; `` Mediafilepicker.prototype.openFilePicker = function (params) { var intent, pickerType, options = params.android, extensions; if (options.extensions.length > 0) { extensions = Array.create(java.lang.String, options.extensions.length); for (var i = 0; i < options.extensions.length; i++) { extensions[i] = options.extensions[i]; } } intent = new android.content.Intent( android.content.Intent.ACTION_GET_CONTENT ); intent.setType("*/*"); intent.putExtra(NormalFilePickActivity.SUFFIX, extensions); intent.addCategory(android.content.Intent.CATEGORY_OPENABLE); intent.setAction(android.content.Intent.ACTION_OPEN_DOCUMENT); pickerType = Constant.REQUEST_CODE_PICK_FILE; this.callIntent(intent, pickerType); }; `` Mediafilepicker.prototype.performCapturing = function (type, options) { var t = this; var requestPermissions = [ android.Manifest.permission.WRITE_EXTERNAL_STORAGE, ]; if (type === "image" || type === "video") { requestPermissions.push(android.Manifest.permission.CAMERA); } else if (type === "audio") { requestPermissions.push(android.Manifest.permission.RECORD_AUDIO); } permissions .requestPermission( requestPermissions, "Need these permissions to access files" ) .then(function () { t.handleOnlyCaptureMode(type, options); }) .catch(function () { t.msg = "Permission Error!"; t.notify({ eventName: "error", object: t, }); }); }; `` Mediafilepicker.prototype.handleOnlyCaptureMode = function (type, options) { var context = app.android.context, t = this, intent, date, timeStamp, contentValues, file, uri; switch (type) { case "image": intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); date = new Date(); timeStamp = date.getFullYear() + "" + (date.getMonth() + 1) + "" + date.getDate() + "_" + date.getHours() + "" + date.getMinutes() + "" + date.getSeconds(); file = new File( Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_DCIM ).getAbsolutePath() + "/IMG_" + timeStamp + ".jpg" ); var mImagePath = file.getAbsolutePath(); this.captureFilePath = mImagePath; contentValues = new ContentValues(1); contentValues.put(MediaStore.Images.Media.DATA, mImagePath); var mImageUri = context .getContentResolver() .insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); this.captureContentUrl = mImageUri; intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri); if (Util.detectIntent(context, intent)) { this.callIntent(intent, Constant.REQUEST_CODE_TAKE_IMAGE); } else { this.msg = "No photo capture app installed!"; this.notify({ eventName: "error", object: this, }); } break; case "video": intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); date = new Date(); timeStamp = date.getFullYear() + "" + (date.getMonth() + 1) + "" + date.getDate() + "_" + date.getHours() + "" + date.getMinutes() + "" + date.getSeconds(); file = new File( Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_DCIM ).getAbsolutePath() + "/VID_" + timeStamp + ".mp4" ); var mVideoPath = file.getAbsolutePath(); this.captureFilePath = mVideoPath; contentValues = new ContentValues(1); contentValues.put(MediaStore.Images.Media.DATA, mVideoPath); uri = context .getContentResolver() .insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); this.captureContentUrl = uri; intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); if (options.maxDuration > 0) { intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, options.maxDuration); } if (options.videoQuality === 0) { intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0); } if (Util.detectIntent(context, intent)) { this.callIntent(intent, Constant.REQUEST_CODE_TAKE_VIDEO); } else { this.msg = "No video recorder app installed!"; this.notify({ eventName: "error", object: this, }); } break; case "audio": intent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION); if (options.maxSize > 0) { var MAX_SIZE = android.provider.MediaStore.Audio.Media.EXTRA_MAX_BYTES; intent.putExtra(MAX_SIZE, options.maxSize); } if (Util.detectIntent(context, intent)) { this.callIntent(intent, Constant.REQUEST_CODE_TAKE_AUDIO); } else { this.msg = "No audio recorder app installed!"; this.notify({ eventName: "error", object: this, }); } break; } }; `` Mediafilepicker.prototype.callIntent = function (intent, pickerType) { var t = this; var requestPermissions = [ android.Manifest.permission.WRITE_EXTERNAL_STORAGE, ]; if ( pickerType === Constant.REQUEST_CODE_TAKE_IMAGE || pickerType === Constant.REQUEST_CODE_PICK_IMAGE || pickerType === Constant.REQUEST_CODE_TAKE_VIDEO || pickerType === Constant.REQUEST_CODE_PICK_VIDEO ) { requestPermissions.push(android.Manifest.permission.CAMERA); } else if ( pickerType === Constant.REQUEST_CODE_TAKE_AUDIO || pickerType === Constant.REQUEST_CODE_PICK_AUDIO ) { requestPermissions.push(android.Manifest.permission.RECORD_AUDIO); } permissions .requestPermission( requestPermissions, "Need these permissions to access files" ) .then(function () { app.android.foregroundActivity.startActivityForResult( intent, pickerType ); }) .catch(function () { t.msg = "Permission Error!"; t.notify({ eventName: "error", object: t, }); }); app.android.on(app.AndroidApplication.activityResultEvent, onResult); function onResult(args) { app.android.off(app.AndroidApplication.activityResultEvent, onResult); t.handleResults(args.requestCode, args.resultCode, args.intent); } }; `` Mediafilepicker.prototype.handleResults = function ( requestCode, resultCode, data ) { var _this = this; var androidAcivity = android.app.Activity; var context = app.android.context; var output = []; var t = this; switch (requestCode) { case Constant.REQUEST_CODE_PICK_IMAGE: if (resultCode === androidAcivity.RESULT_OK) { var list = data.getParcelableArrayListExtra( Constant.RESULT_PICK_IMAGE ); list = list.toArray(); for (var index_1 = 0; index_1 < list.length; index_1++) { var item = list[index_1]; var file = { type: "image", file: item.getPath(), rawData: item, }; output.push(file); } } break; case Constant.REQUEST_CODE_PICK_VIDEO: if (resultCode === androidAcivity.RESULT_OK) { var list = data.getParcelableArrayListExtra( Constant.RESULT_PICK_VIDEO ); list = list.toArray(); for (var index_2 = 0; index_2 < list.length; index_2++) { var item = list[index_2]; var file = { type: "video", file: item.getPath(), rawData: item, }; output.push(file); } } break; case Constant.REQUEST_CODE_PICK_AUDIO: if (resultCode === androidAcivity.RESULT_OK) { var list = data.getParcelableArrayListExtra( Constant.RESULT_PICK_AUDIO ); list = list.toArray(); for (var index_3 = 0; index_3 < list.length; index_3++) { var item = list[index_3]; var file = { type: "audio", file: item.getPath(), rawData: item, }; output.push(file); } } break; case Constant.REQUEST_CODE_PICK_FILE: if (resultCode === androidAcivity.RESULT_OK) { let storageFile, filePath; var uri = data.getData(); let cursor = context .getContentResolver() .query(uri, null, null, null, null); cursor.moveToFirst(); let nameIndex = cursor.getColumnIndex( android.provider.OpenableColumns.DISPLAY_NAME ); let name = cursor.getString(nameIndex); let documents = fs.knownFolders.documents(); // let folders= documents.getFolder("downloads").path; let folders = android.os.Environment.getExternalStoragePublicDirectory( android.os.Environment.DIRECTORY_DOWNLOADS ).getAbsolutePath(); let folderPathDocuments = android.os.Environment.getExternalStoragePublicDirectory( android.os.Environment.DIRECTORY_DOCUMENTS ).getAbsolutePath(); filePath = fs.path.join(folders, name); if (FILE.File.exists(filePath)) { storageFile = fs.File.fromPath(filePath); } else { filePath = fs.path.join(folderPathDocuments, name); storageFile = fs.File.fromPath(filePath); } let file = { type: storageFile.extension, file: storageFile.path, rawData: storageFile, }; output.push(file); } break; case Constant.REQUEST_CODE_TAKE_IMAGE: if (resultCode === androidAcivity.RESULT_OK) { var rawData = new File(this.captureFilePath); var file = { type: "capturedImage", file: this.captureFilePath, rawData: rawData, }; output.push(file); } else { utils.ad .getApplicationContext() .getContentResolver() .delete(this.captureContentUrl, null, null); } break; case Constant.REQUEST_CODE_TAKE_VIDEO: if (resultCode === androidAcivity.RESULT_OK) { var rawData = new File(this.captureFilePath); var file = { type: "capturedVideo", file: this.captureFilePath, rawData: rawData, }; output.push(file); } else { utils.ad .getApplicationContext() .getContentResolver() .delete(this.captureContentUrl, null, null); } break; case Constant.REQUEST_CODE_TAKE_AUDIO: if (resultCode === androidAcivity.RESULT_OK) { var rawData = Uri.parse(data.getData().toString()); var cursor = context .getContentResolver() .query(rawData, null, null, null, null); var column_index = cursor.getColumnIndex(MediaStore.Audio.Media.DATA); cursor.moveToFirst(); var file = { type: "capturedAudio", file: cursor.getString(column_index), rawData: rawData, }; output.push(file); cursor.close(); } break; } setTimeout(function () { _this.results = output; if (output.length > 0) { t.notify({ eventName: "getFiles", object: t, }); } else { t.msg = "Picker cancel or no file has been selected."; t.notify({ eventName: "cancel", object: t, }); } }, 300); }; `` Mediafilepicker.prototype.greet = function () { return "Hello, NS"; }; return Mediafilepicker; })(observable_1.Observable); exports.Mediafilepicker = Mediafilepicker; //# sourceMappingURL=mediafilepicker.android.js.map hope this OS helps and someone fork and update with this

calleja23 avatar Nov 04 '21 17:11 calleja23

@calleja23 I guess I'm using a newer version of NS and this plugin, so the code didn't work for me. Could you please clarify where did you change in this file? Thanks!

ianshi95 avatar Nov 04 '21 21:11 ianshi95

Looks like this repo is no longer maintained. TGIF. I found this plugin https://github.com/nativescript-community/ui-document-picker instead.. Easier to use.

jajatismail avatar Nov 05 '21 04:11 jajatismail

@calleja23 it didn't work, I'm testing with ns6

Ederagp avatar Nov 11 '21 17:11 Ederagp

Any progress on this?

OPADA-Eng avatar Nov 24 '21 11:11 OPADA-Eng

` "use strict"; Object.defineProperty(exports, "__esModule", { value: true });

var observable_1 = require("tns-core-modules/data/observable"); var app = require("@nativescript/core/application"); var utils = require("@nativescript/core/utils"); var permissions = require("nativescript-permissions"); const FILE = require("@nativescript/core/file-system"); const fs = require("@nativescript/core/file-system");

// import { Application, Observable, Utils, AndroidApplication } from "@nativescript/core"; // import { request as RequestPermission } from "@nativescript-community/perms";

var AudioPickActivity = com.vincent.filepicker.activity.AudioPickActivity; var ImagePickActivity = com.vincent.filepicker.activity.ImagePickActivity; var NormalFilePickActivity = com.vincent.filepicker.activity.NormalFilePickActivity; var VideoPickActivity = com.vincent.filepicker.activity.VideoPickActivity; var Constant = com.vincent.filepicker.Constant; var Util = com.vincent.filepicker.Util; var Intent = android.content.Intent; var MediaStore = android.provider.MediaStore; var Environment = android.os.Environment; var File = java.io.File; var ContentValues = android.content.ContentValues; var Uri = android.net.Uri; var FileUtils = android.os.FileUtils; var Mediafilepicker = (function (_super) { __extends(Mediafilepicker, _super);

function Mediafilepicker() { return _super.call(this) || this; } Mediafilepicker.prototype.openImagePicker = function (params) { var intent, pickerType, options = params.android; if (options.isCaptureMood) { this.performCapturing("image", options); return; } intent = new Intent(app.android.foregroundActivity, ImagePickActivity.class); options.isNeedCamera ? intent.putExtra(ImagePickActivity.IS_NEED_CAMERA, true) : intent.putExtra(ImagePickActivity.IS_NEED_CAMERA, false); options.maxNumberFiles ? intent.putExtra(Constant.MAX_NUMBER, options.maxNumberFiles) : intent.putExtra(Constant.MAX_NUMBER, 99); options.isNeedFolderList ? intent.putExtra(ImagePickActivity.IS_NEED_FOLDER_LIST, true) : intent.putExtra(ImagePickActivity.IS_NEED_FOLDER_LIST, false); pickerType = Constant.REQUEST_CODE_PICK_IMAGE; this.callIntent(intent, pickerType); }; Mediafilepicker.prototype.openVideoPicker = function (params) { var intent, pickerType, options = params.android; if (options.isCaptureMood) { this.performCapturing("video", options); return; } intent = new Intent(app.android.foregroundActivity, VideoPickActivity.class); options.isNeedCamera ? intent.putExtra(VideoPickActivity.IS_NEED_CAMERA, true) : intent.putExtra(VideoPickActivity.IS_NEED_CAMERA, false); options.maxNumberFiles ? intent.putExtra(Constant.MAX_NUMBER, options.maxNumberFiles) : intent.putExtra(Constant.MAX_NUMBER, 99); options.isNeedFolderList ? intent.putExtra(VideoPickActivity.IS_NEED_FOLDER_LIST, true) : intent.putExtra(VideoPickActivity.IS_NEED_FOLDER_LIST, false); if (options.maxDuration > 0) { intent.putExtra(Constant.MAX_VIDEO_DURATION, options.maxDuration); } intent.putExtra(Constant.VIDEO_QUALITY, 1); if (options.videoQuality === 0) { intent.putExtra(Constant.VIDEO_QUALITY, 0); } pickerType = Constant.REQUEST_CODE_PICK_VIDEO; this.callIntent(intent, pickerType); }; Mediafilepicker.prototype.openAudioPicker = function (params) { var intent, pickerType, options = params.android; if (options.isCaptureMood) { this.performCapturing("audio", options); return; } intent = new Intent(app.android.foregroundActivity, AudioPickActivity.class); options.isNeedRecorder ? intent.putExtra(AudioPickActivity.IS_NEED_RECORDER, true) : intent.putExtra(AudioPickActivity.IS_NEED_RECORDER, false); options.maxNumberFiles ? intent.putExtra(Constant.MAX_NUMBER, options.maxNumberFiles) : intent.putExtra(Constant.MAX_NUMBER, 99); options.isNeedFolderList ? intent.putExtra(AudioPickActivity.IS_NEED_FOLDER_LIST, true) : intent.putExtra(AudioPickActivity.IS_NEED_FOLDER_LIST, false); if (options.maxSize > 0) { intent.putExtra(Constant.MAX_AUDIO_SIZE, options.maxSize); } intent.putExtra(AudioPickActivity.IS_TAKEN_AUTO_SELECTED, true); pickerType = Constant.REQUEST_CODE_PICK_AUDIO; this.callIntent(intent, pickerType); };

Mediafilepicker.prototype.openFilePicker = function (params) { var intent, pickerType, options = params.android, extensions; if (options.extensions.length > 0) { extensions = Array.create(java.lang.String, options.extensions.length); for (var i = 0; i < options.extensions.length; i++) { extensions[i] = options.extensions[i]; } } intent = new android.content.Intent(android.content.Intent.ACTION_GET_CONTENT); intent.setType("application/pdf,image/jpeg,image/png"); // intent.setType("image/jpeg,image/png"); // intent.setType("application/pdf"); intent.putExtra(NormalFilePickActivity.SUFFIX, extensions); intent.addCategory(android.content.Intent.CATEGORY_OPENABLE); intent.setAction(android.content.Intent.ACTION_OPEN_DOCUMENT); pickerType = Constant.REQUEST_CODE_PICK_FILE; this.callIntent(intent, pickerType); }; Mediafilepicker.prototype.performCapturing = function (type, options) { var t = this; var requestPermissions = [android.Manifest.permission.WRITE_EXTERNAL_STORAGE, ]; if (type === "image" || type === "video") { requestPermissions.push(android.Manifest.permission.CAMERA); } else if (type === "audio") { requestPermissions.push(android.Manifest.permission.RECORD_AUDIO); } permissions.requestPermission(requestPermissions, "Need these permissions to access files").then(function () { t.handleOnlyCaptureMode(type, options); }).catch(function () { t.msg = "Permission Error!"; t.notify({ eventName: "error", object: t, }); }); }; Mediafilepicker.prototype.handleOnlyCaptureMode = function (type, options) { var context = app.android.context, t = this, intent, date, timeStamp, contentValues, file, uri; switch (type) { case "image": intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); date = new Date(); timeStamp = date.getFullYear() + "" + (date.getMonth() + 1) + "" + date.getDate() + "" + date.getHours() + "" + date.getMinutes() + "" + date.getSeconds(); file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath() + "/IMG" + timeStamp + ".jpg"); var mImagePath = file.getAbsolutePath(); this.captureFilePath = mImagePath; contentValues = new ContentValues(1); contentValues.put(MediaStore.Images.Media.DATA, mImagePath); var mImageUri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); this.captureContentUrl = mImageUri; intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri); if (Util.detectIntent(context, intent)) { this.callIntent(intent, Constant.REQUEST_CODE_TAKE_IMAGE); } else { this.msg = "No photo capture app installed!"; this.notify({ eventName: "error", object: this, }); } break; case "video": intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); date = new Date(); timeStamp = date.getFullYear() + "" + (date.getMonth() + 1) + "" + date.getDate() + "" + date.getHours() + "" + date.getMinutes() + "" + date.getSeconds(); file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath() + "/VID" + timeStamp + ".mp4"); var mVideoPath = file.getAbsolutePath(); this.captureFilePath = mVideoPath; contentValues = new ContentValues(1); contentValues.put(MediaStore.Images.Media.DATA, mVideoPath); uri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); this.captureContentUrl = uri; intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); if (options.maxDuration > 0) { intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, options.maxDuration); } if (options.videoQuality === 0) { intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0); } if (Util.detectIntent(context, intent)) { this.callIntent(intent, Constant.REQUEST_CODE_TAKE_VIDEO); } else { this.msg = "No video recorder app installed!"; this.notify({ eventName: "error", object: this, }); } break; case "audio": intent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION); if (options.maxSize > 0) { var MAX_SIZE = android.provider.MediaStore.Audio.Media.EXTRA_MAX_BYTES; intent.putExtra(MAX_SIZE, options.maxSize); } if (Util.detectIntent(context, intent)) { this.callIntent(intent, Constant.REQUEST_CODE_TAKE_AUDIO); } else { this.msg = "No audio recorder app installed!"; this.notify({ eventName: "error", object: this, }); } break; } }; Mediafilepicker.prototype.callIntent = function (intent, pickerType) { var t = this; var requestPermissions = [android.Manifest.permission.WRITE_EXTERNAL_STORAGE, ]; if (pickerType === Constant.REQUEST_CODE_TAKE_IMAGE || pickerType === Constant.REQUEST_CODE_PICK_IMAGE || pickerType === Constant.REQUEST_CODE_TAKE_VIDEO || pickerType === Constant.REQUEST_CODE_PICK_VIDEO) { requestPermissions.push(android.Manifest.permission.CAMERA); } else if (pickerType === Constant.REQUEST_CODE_TAKE_AUDIO || pickerType === Constant.REQUEST_CODE_PICK_AUDIO) { requestPermissions.push(android.Manifest.permission.RECORD_AUDIO); } permissions.requestPermission(requestPermissions, "Need these permissions to access files").then(function () { app.android.foregroundActivity.startActivityForResult(intent, pickerType); }).catch(function () { t.msg = "Permission Error!"; t.notify({ eventName: "error", object: t, }); }); app.android.on(app.AndroidApplication.activityResultEvent, onResult);

function onResult(args) {
  app.android.off(app.AndroidApplication.activityResultEvent, onResult);
  t.handleResults(args.requestCode, args.resultCode, args.intent);
}

}; Mediafilepicker.prototype.handleResults = function (requestCode, resultCode, data) { var _this = this; var androidAcivity = android.app.Activity; var context = app.android.context; var output = []; var t = this; switch (requestCode) { case Constant.REQUEST_CODE_PICK_IMAGE: if (resultCode === androidAcivity.RESULT_OK) { var list = data.getParcelableArrayListExtra(Constant.RESULT_PICK_IMAGE); list = list.toArray(); for (var index_1 = 0; index_1 < list.length; index_1++) { var item = list[index_1]; var file = { type: "image", file: item.getPath(), rawData: item, }; output.push(file); } } break; case Constant.REQUEST_CODE_PICK_VIDEO: if (resultCode === androidAcivity.RESULT_OK) { var list = data.getParcelableArrayListExtra(Constant.RESULT_PICK_VIDEO); list = list.toArray(); for (var index_2 = 0; index_2 < list.length; index_2++) { var item = list[index_2]; var file = { type: "video", file: item.getPath(), rawData: item, }; output.push(file); } } break; case Constant.REQUEST_CODE_PICK_AUDIO: if (resultCode === androidAcivity.RESULT_OK) { var list = data.getParcelableArrayListExtra(Constant.RESULT_PICK_AUDIO); list = list.toArray(); for (var index_3 = 0; index_3 < list.length; index_3++) { var item = list[index_3]; var file = { type: "audio", file: item.getPath(), rawData: item, }; output.push(file); } } break; case Constant.REQUEST_CODE_PICK_FILE: if (resultCode === androidAcivity.RESULT_OK) { let storageFile, filePath; var uri = data.getData(); let cursor = context.getContentResolver().query(uri, null, null, null, null); cursor.moveToFirst(); let nameIndex = cursor.getColumnIndex(android.provider.OpenableColumns.DISPLAY_NAME); let name = cursor.getString(nameIndex); let documents = fs.knownFolders.documents(); // let folders= documents.getFolder("downloads").path; let folders = android.os.Environment.getExternalStoragePublicDirectory(android.os.Environment.DIRECTORY_DOWNLOADS).getAbsolutePath(); let folderPathDocuments = android.os.Environment.getExternalStoragePublicDirectory(android.os.Environment.DIRECTORY_DOCUMENTS).getAbsolutePath(); filePath = fs.path.join(folders, name); if (FILE.File.exists(filePath)) { storageFile = fs.File.fromPath(filePath); } else { filePath = fs.path.join(folderPathDocuments, name); storageFile = fs.File.fromPath(filePath); } let file = { type: storageFile.extension, file: storageFile.path, rawData: storageFile, }; output.push(file); } break; case Constant.REQUEST_CODE_TAKE_IMAGE: if (resultCode === androidAcivity.RESULT_OK) { var rawData = new File(this.captureFilePath); var file = { type: "capturedImage", file: this.captureFilePath, rawData: rawData, }; output.push(file); } else { utils.ad.getApplicationContext().getContentResolver().delete(this.captureContentUrl, null, null); } break; case Constant.REQUEST_CODE_TAKE_VIDEO: if (resultCode === androidAcivity.RESULT_OK) { var rawData = new File(this.captureFilePath); var file = { type: "capturedVideo", file: this.captureFilePath, rawData: rawData, }; output.push(file); } else { utils.ad.getApplicationContext().getContentResolver().delete(this.captureContentUrl, null, null); } break; case Constant.REQUEST_CODE_TAKE_AUDIO: if (resultCode === androidAcivity.RESULT_OK) { var rawData = Uri.parse(data.getData().toString()); var cursor = context.getContentResolver().query(rawData, null, null, null, null); var column_index = cursor.getColumnIndex(MediaStore.Audio.Media.DATA); cursor.moveToFirst(); var file = { type: "capturedAudio", file: cursor.getString(column_index), rawData: rawData, }; output.push(file); cursor.close(); } break; } setTimeout(function () { _this.results = output; if (output.length > 0) { t.notify({ eventName: "getFiles", object: t, }); } else { t.msg = "Picker cancel or no file has been selected."; t.notify({ eventName: "cancel", object: t, }); } }, 300); }; Mediafilepicker.prototype.greet = function () { return "Hello, NS"; }; return Mediafilepicker; })(observable_1.Observable); exports.Mediafilepicker = Mediafilepicker; //# sourceMappingURL=mediafilepicker.android.js.map `

@calleja23 Thanks this code worked but extensions are not taking but i'm able to see pdf files
installed tns-core-modules package along with above code

manojpraharsha avatar Dec 14 '21 11:12 manojpraharsha

Finally I use for NS8

  • "@nativescript/camera": "^5.0.10"
  • "@nativescript/imagepicker": "^1.0.6"
  • "@nativescript-community/ui-document-picker": "^1.1.7"

xpalacincreditoh avatar Dec 14 '21 12:12 xpalacincreditoh

       if(!android.os.Environment.isExternalStorageManager()){
            let intent = new Intent(android.provider.Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);

            const activity = Application.android.foregroundActivity || Application.android.startActivity;

            activity.startActivityForResult(intent,0);

       }

Need have this permission for accesing files it worked for me in android 11 and above
need android sdk 30 for 'ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION' Add this in maifest. <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>

manojpraharsha avatar Sep 27 '22 12:09 manojpraharsha

Google does not like to grant ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION, my app was rejected because of that last week.

No idea yet if it will work, but I'll try https://github.com/pierremacedo/nativescript-android-fs next.

ray007 avatar Oct 24 '22 09:10 ray007

"@angular/core": "~14.0.0", "@nativescript-community/ui-document-picker": "~1.1.12", "@nativescript/core": "~8.3.4",

works fine on real device!!!

"@nativescript/core": "~8.2.5" -> not Work

Ederagp avatar Oct 24 '22 16:10 Ederagp

For me its working on the physical device with the mediafilepicker now.

"@angular/core": "^12.2.0", "nativescript-mediafilepicker": "^4.0.2", "@nativescript/core": "^8.3.1",

AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

android:requestLegacyExternalStorage="true"

Maxeeezy avatar Oct 27 '22 11:10 Maxeeezy

We have problems with several phones too. Using a custom file picker shows zero files. We would need to see XLSX files downloaded from a website. My old Note shows the files, other phones show zero files. @jibon57

csimpi avatar Dec 31 '22 22:12 csimpi