| |
| export function openFileManager() { |
| return new Promise(async (resolve, reject) => { |
| try { |
| await requestPermission(); |
| |
| |
| const main = plus.android.runtimeMainActivity(); |
| |
| |
| const Intent = plus.android.importClass('android.content.Intent'); |
| |
| |
| |
| const intent = new Intent(Intent.ACTION_GET_CONTENT); |
| |
| intent.addCategory(Intent.CATEGORY_OPENABLE); |
| |
| intent.setType('*/*'); |
| |
| intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); |
| |
| const REQUEST_CODE = 1; |
| |
| main.onActivityResult = (requestCode, code, data) => { |
| |
| const Activity = plus.android.importClass('android.app.Activity'); |
| plus.android.importClass('android.net.Uri'); |
| |
| |
| |
| let filePathList = []; |
| |
| |
| if (code === Activity.RESULT_OK && requestCode === REQUEST_CODE) { |
| |
| let Uri = data.getData(); |
| |
| if (!Uri) { |
| let ClipData = plus.android.importClass('android.content.ClipData'); |
| let clipData = new ClipData(); |
| clipData = data.getClipData(); |
| |
| if (clipData) { |
| |
| const count = clipData.getItemCount(); |
| for (let i = 0; i < count; i++) { |
| const item = clipData.getItemAt(i); |
| const uri = item.getUri(); |
| const filePath = getFilePath(main, uri); |
| filePathList.push(filePath); |
| } |
| } |
| } else { |
| filePathList.push(getFilePath(main, Uri)); |
| } |
| } |
| |
| resolve(filePathList); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| }; |
| |
| |
| |
| main.startActivityForResult(intent, REQUEST_CODE); |
| |
| } catch (e) { |
| reject(e); |
| } |
| }); |
| } |
| |
| |
| |
| |
| |
| |
| function getFilePath(main, Uri) { |
| const Build = plus.android.importClass('android.os.Build'); |
| const DocumentsContract = plus.android.importClass('android.provider.DocumentsContract'); |
| |
| const IS_DOUMENT_TYPE = DocumentsContract.isDocumentUri(main, Uri); |
| const scheme = Uri.getScheme(); |
| |
| |
| |
| |
| |
| |
| const IS_KITKAT = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; |
| |
| |
| |
| if (IS_KITKAT) { |
| if (IS_DOUMENT_TYPE) { |
| |
| const docId = DocumentsContract.getDocumentId(Uri); |
| const [type, id] = docId.split(':'); |
| |
| |
| const authority = Uri.getAuthority(); |
| |
| |
| const AUTHORITY_DOCUMENT_TYPE = { |
| MEDIA: 'com.android.providers.media.documents', |
| DOWNLOAD: 'com.android.providers.downloads.documents', |
| EXTERNAL: 'com.android.externalstorage.documents', |
| }; |
| |
| const authorityFn = { |
| [AUTHORITY_DOCUMENT_TYPE.DOWNLOAD]: getDownloadDocument, |
| [AUTHORITY_DOCUMENT_TYPE.MEDIA]: getMediaDocument, |
| [AUTHORITY_DOCUMENT_TYPE.EXTERNAL]: getExternalDocument, |
| }; |
| return authorityFn[authority]?.({ main, Uri, docId, type, id }); |
| } else if (scheme === 'content') { |
| |
| |
| return getDataColumn(main, Uri); |
| } else if (scheme === 'file') { |
| return Uri.getPath(); |
| } |
| } else { |
| |
| const MediaStore = plus.android.importClass('android.provider.MediaStore'); |
| const columns = [MediaStore.Images.Media.DATA]; |
| const cursor = contentResolver.query(Uri, columns, null, null, null); |
| if (cursor !== null && cursor.moveToFirst()) { |
| const column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); |
| const filePath = cursor.getString(column_index); |
| cursor.close(); |
| return filePath; |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function getExternalDocument(options) { |
| const { type, id } = options; |
| const Environment = plus.android.importClass('android.os.Environment'); |
| |
| let path = ''; |
| if (type === 'primary') { |
| |
| path = `${Environment.getExternalStorageDirectory()}/${id}`; |
| } else { |
| const System = plus.android.importClass('java.lang.System'); |
| path = `${System.getenv('SECONDARY_STORAGE')}/${id}`; |
| } |
| return path; |
| } |
| |
| |
| |
| |
| function getMediaDocument(options) { |
| const { main, id, type } = options; |
| const MediaStore = plus.android.importClass('android.provider.MediaStore'); |
| const MEDIA_TYPE = { |
| image: MediaStore.Images.Media.EXTERNAL_CONTENT_URI, |
| video: MediaStore.Video.Media.EXTERNAL_CONTENT_URI, |
| audio: MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, |
| document: MediaStore.Files.getContentUri('external'), |
| }; |
| |
| const uri = MEDIA_TYPE[type] || null; |
| return getDataColumn(main, uri, '_id=?', [id]); |
| } |
| |
| |
| |
| |
| function getDownloadDocument(options) { |
| const { main, Uri, id } = options; |
| |
| if (id) { |
| return id; |
| } |
| |
| const ContentUris = plus.android.importClass('android.content.ContentUris'); |
| |
| |
| |
| const originId = Uri.parse('content://downloads/public_downloads'); |
| const newId = ContentUris.parseId(Uri); |
| const uri = ContentUris.withAppendedId(originId, newId); |
| return getDataColumn(main, uri); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| function getDataColumn(context, uri, selection = null, selectionArgs = null) { |
| |
| plus.android.importClass(context.getContentResolver()); |
| |
| const _columns = ['_data']; |
| |
| const Cursor = context.getContentResolver().query(uri, _columns, selection, selectionArgs, null); |
| |
| |
| Cursor && plus.android.importClass(Cursor); |
| |
| let filePath = ''; |
| |
| if (Cursor !== null && Cursor.moveToFirst()) { |
| |
| const columnIndex = Cursor.getColumnIndexOrThrow(_columns[0]); |
| |
| filePath = Cursor.getString(columnIndex); |
| |
| Cursor.close(); |
| } |
| return filePath; |
| } |
| |
| const PERMISSION_TYPE = { |
| |
| PERMISSION_GRANTED: 0, |
| |
| PERMISSION_DENIED: 1, |
| |
| PERMISSION_DENIED_FOREVER: 2, |
| }; |
| |
| |
| function requestPermission() { |
| return new Promise((resolve, reject) => { |
| plus.android.requestPermissions( |
| ['android.permission.READ_EXTERNAL_STORAGE'], |
| (e) => { |
| if (e.deniedAlways.length > 0) { |
| |
| |
| |
| reject({ |
| code: PERMISSION_TYPE.PERMISSION_DENIED_FOREVER, |
| msg: '未授权且不再询问', |
| }); |
| } |
| if (e.deniedPresent.length > 0) { |
| |
| |
| |
| |
| reject({ |
| code: PERMISSION_TYPE.PERMISSION_DENIED, |
| msg: '未授权', |
| }); |
| } |
| if (e.granted.length > 0) { |
| |
| |
| |
| resolve({ |
| code: PERMISSION_TYPE.PERMISSION_GRANTED, |
| msg: '已授权', |
| }); |
| } |
| }, |
| (e) => { |
| |
| reject(e); |
| } |
| ); |
| }); |
| } |
| |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了