|
@@ -0,0 +1,285 @@
|
|
|
+// index.uts
|
|
|
+
|
|
|
+// 引用android api
|
|
|
+import { UTSAndroid } from "io.dcloud.uts";
|
|
|
+import ActivityCompat from "androidx.core.app.ActivityCompat";
|
|
|
+import { Context, Intent, ContentUris, ContentResolver } from "android.content";
|
|
|
+import { Settings } from "android.provider";
|
|
|
+import Uri from "android.net.Uri";
|
|
|
+import FileUtils from "android.os.FileUtils";
|
|
|
+import { DocumentsContract, MediaStore } from "android.provider";
|
|
|
+import { File, FileOutputStream } from "java.io";
|
|
|
+import Activity from "android.app.Activity";
|
|
|
+import Manifest from "android.Manifest";
|
|
|
+import Cursor from "android.database.Cursor";
|
|
|
+import { Build, Environment } from "android.os";
|
|
|
+
|
|
|
+
|
|
|
+type InfoOptions = {
|
|
|
+ scope?:string,
|
|
|
+ permission ?: boolean,
|
|
|
+ mimetype?:string,
|
|
|
+ success ?: (res : object) => void
|
|
|
+ fail ?: (res : object) => void
|
|
|
+ complete ?: (res : object) => void
|
|
|
+}
|
|
|
+export default function fileSelect(options : InfoOptions) {
|
|
|
+ UTSAndroid.onAppActivityRequestPermissionsResult((requestCode : number,
|
|
|
+ permissions : MutableList<string>,
|
|
|
+ grantResults : MutableList<number>) => {
|
|
|
+ UTSAndroid.offAppActivityRequestPermissionsResult();
|
|
|
+ if ((requestCode !== 1001) && (grantResults[0] === -1)) {
|
|
|
+ options.fail?.({
|
|
|
+ code: "1001",
|
|
|
+ errMsg: 'fileselect:fail',
|
|
|
+ detail:"未授权文件读取权限"
|
|
|
+ })
|
|
|
+ const permission=options.permission;
|
|
|
+ if(permission!=null&&permission){
|
|
|
+ const intent = new Intent();
|
|
|
+ intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
|
|
+ const uri = Uri.fromParts("package", UTSAndroid.getUniActivity()?.getPackageName(), "");
|
|
|
+ intent.setData(uri);
|
|
|
+ UTSAndroid.getUniActivity()?.startActivity(intent);
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ fileSelectStart(options);
|
|
|
+
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 请求权限
|
|
|
+ ActivityCompat.requestPermissions(UTSAndroid.getUniActivity()!, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 1001)
|
|
|
+
|
|
|
+}
|
|
|
+ function fileSelectStart(options : InfoOptions) {
|
|
|
+ const FILE_SELECT_REQUEST_CODE = 110
|
|
|
+ const context = UTSAndroid.getAppContext();
|
|
|
+ if (context != null) {
|
|
|
+ if(options.scope!=null){
|
|
|
+ let strPath=options.scope
|
|
|
+ strPath=strPath?.replaceAll("/","%2F")
|
|
|
+ console.log(strPath);
|
|
|
+ let uri1:Uri = Uri.parse("content://com.android.externalstorage.documents/document/primary%3A"+strPath);
|
|
|
+ let intent1:Intent = new Intent(Intent.ACTION_GET_CONTENT);
|
|
|
+ intent1.addCategory(Intent.CATEGORY_OPENABLE);
|
|
|
+ if(options.mimetype!=null){
|
|
|
+ intent1.setType(options.mimetype);
|
|
|
+ }else{
|
|
|
+ intent1.setType("*/*");
|
|
|
+ }
|
|
|
+ intent1.putExtra(DocumentsContract.EXTRA_INITIAL_URI, uri1);
|
|
|
+ UTSAndroid.getUniActivity()?.startActivityForResult(intent1, FILE_SELECT_REQUEST_CODE);
|
|
|
+
|
|
|
+ }else{
|
|
|
+ const intent = new Intent(Intent.ACTION_GET_CONTENT);
|
|
|
+ intent.setType("*/*");
|
|
|
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
|
|
|
+ if(options.mimetype!=null){
|
|
|
+ intent.setType(options.mimetype);
|
|
|
+ }
|
|
|
+ UTSAndroid.getUniActivity()?.startActivityForResult(intent, FILE_SELECT_REQUEST_CODE)
|
|
|
+ }
|
|
|
+
|
|
|
+ UTSAndroid.onAppActivityResult((requestCode : Int, resultCode : Int, data ?: Intent) => {
|
|
|
+ // let eventName = "onAppActivityResult - requestCode:" + requestCode + " -resultCode:"+resultCode + " -data:"+JSON.stringify(data);
|
|
|
+ UTSAndroid.offAppActivityResult();
|
|
|
+ if (requestCode == FILE_SELECT_REQUEST_CODE && resultCode == Activity.RESULT_OK && data != null) {
|
|
|
+ const fileUri = data.getData();
|
|
|
+
|
|
|
+ if (fileUri != null) {
|
|
|
+ // console.log('文件选择器:【文件相对路径】', fileUri.getPath());
|
|
|
+ let path = getRealPathFromURI(context, fileUri)
|
|
|
+ const file = new File(path)
|
|
|
+ if (file.exists()) {
|
|
|
+ let upLoadFilePath = file.toString();
|
|
|
+ let upLoadFileName = file.getName();
|
|
|
+ let fileSize = file.length();
|
|
|
+ const extIdx= upLoadFilePath.lastIndexOf(".");
|
|
|
+ let fileType =extIdx!=-1?upLoadFilePath.substring(extIdx+1):""
|
|
|
+ const res = {
|
|
|
+ code: "0",
|
|
|
+ filePath: upLoadFilePath,
|
|
|
+ fileName: upLoadFileName,
|
|
|
+ fileSize:fileSize,
|
|
|
+ fileType:fileType,
|
|
|
+ errMsg: 'fileselect:ok',
|
|
|
+ detail:"文件读取成功"
|
|
|
+ }
|
|
|
+ options.success?.(res)
|
|
|
+ options.complete?.(res)
|
|
|
+ } else {
|
|
|
+ const res2 = {
|
|
|
+ code: "1002",
|
|
|
+ errMsg: 'fileselect:fail',
|
|
|
+ detail:"文件不存在"
|
|
|
+ }
|
|
|
+ options.fail?.(res2)
|
|
|
+ options.complete?.(res2)
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ const res3 = {
|
|
|
+ code: "1002",
|
|
|
+ errMsg: 'fileselect:fail',
|
|
|
+ detail:"文件不存在"
|
|
|
+ }
|
|
|
+ options.fail?.(res3)
|
|
|
+ options.complete?.(res3)
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+function getRealPathFromURI(context : Context, uri : Uri) : string {
|
|
|
+ const isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
|
|
|
+ //4.4以下的版本:不支持
|
|
|
+ //大于4.4
|
|
|
+ // DocumentProvider
|
|
|
+ if (isKitKat) {
|
|
|
+ if (DocumentsContract.isDocumentUri(context, uri)) {
|
|
|
+ if (isExternalStorageDocument(uri)) {
|
|
|
+ const docId : string = DocumentsContract.getDocumentId(uri);
|
|
|
+ const split : string[] = docId.split(":");
|
|
|
+ console.log(docId, split);
|
|
|
+ if ("primary".equals(split[0])) {
|
|
|
+ return Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + split[1];
|
|
|
+ } else {
|
|
|
+ return "/storage/" + split[0] + "/" + split[1]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // DownloadsProvider
|
|
|
+ else if (isDownloadsDocument(uri)) {
|
|
|
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
|
+ return saveFileFromUri(context, uri)
|
|
|
+ }
|
|
|
+ const downloadPath: string = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
|
|
|
+ const fileName:string = getFileName(context, uri);
|
|
|
+ return downloadPath+"/"+fileName
|
|
|
+ }
|
|
|
+ // MediaProvider
|
|
|
+ else if (isMediaDocument(uri)) {
|
|
|
+ let docId : string = DocumentsContract.getDocumentId(uri);
|
|
|
+ let split : string[] = docId.split(":");
|
|
|
+ let type : string = split[0];
|
|
|
+ let contentUri : Uri | null = null;
|
|
|
+
|
|
|
+ if ("image".equals(type)) {
|
|
|
+ contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
|
|
|
+ } else if ("video".equals(type)) {
|
|
|
+ contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
|
|
|
+ } else if ("audio".equals(type)) {
|
|
|
+ contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
|
|
+ }
|
|
|
+ else if ("document".equals(type)) {
|
|
|
+ // 安卓系统版本大于等于10
|
|
|
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
|
+ return saveFileFromUri(context, uri)
|
|
|
+ }
|
|
|
+ return ""
|
|
|
+ }
|
|
|
+ const selection : string = "_id=?";
|
|
|
+ const selectionArgs : String[] = [split[1]];
|
|
|
+ if (contentUri != null) {
|
|
|
+ return getDataColumn(context, contentUri, selection, selectionArgs);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //其他 content
|
|
|
+ else if ("content".equals(uri.getScheme())) {
|
|
|
+ return getDataColumn(context, uri, null, null);
|
|
|
+
|
|
|
+ }
|
|
|
+ //其他 file
|
|
|
+ else if ("file".equals(uri.getScheme())) {
|
|
|
+ return uri.getPath() as string;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ""
|
|
|
+
|
|
|
+}
|
|
|
+function isExternalStorageDocument(uri : Uri) : boolean {
|
|
|
+ return "com.android.externalstorage.documents".equals(uri.getAuthority());
|
|
|
+}
|
|
|
+
|
|
|
+function isDownloadsDocument(uri : Uri) : boolean {
|
|
|
+ return "com.android.providers.downloads.documents".equals(uri.getAuthority());
|
|
|
+}
|
|
|
+function isMediaDocument(uri : Uri) : boolean {
|
|
|
+ return "com.android.providers.media.documents".equals(uri.getAuthority());
|
|
|
+}
|
|
|
+
|
|
|
+function getDataColumn(context : Context, uri : Uri, selection : string | null, selectionArgs : String[] | null) : string {
|
|
|
+ let column = "_data";
|
|
|
+ let projection = arrayOf<string>(column)
|
|
|
+ let cursor : Cursor | null = null;
|
|
|
+ const _selectionArgs = selectionArgs != null ? selectionArgs.toTypedArray() : null
|
|
|
+
|
|
|
+ try {
|
|
|
+
|
|
|
+ cursor = context.getContentResolver().query(uri, projection, selection, _selectionArgs, null);
|
|
|
+
|
|
|
+ if (cursor != null && cursor.moveToFirst()) {
|
|
|
+ const column_index = cursor.getColumnIndexOrThrow(column);
|
|
|
+ return cursor.getString(column_index);
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e);
|
|
|
+ } finally {
|
|
|
+ if (cursor != null) {
|
|
|
+ cursor.close();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return "";
|
|
|
+}
|
|
|
+function getFileName(context : Context, uri : Uri) : string {
|
|
|
+ let projection = arrayOf(MediaStore.Images.ImageColumns.DISPLAY_NAME)
|
|
|
+ let cursor = context.getContentResolver().query(uri, projection, null, null, null)
|
|
|
+ try {
|
|
|
+ if (cursor != null && cursor.moveToFirst()) {
|
|
|
+
|
|
|
+ let name_col_index = cursor.getColumnIndex(projection[0])
|
|
|
+
|
|
|
+ return cursor.getString(name_col_index)
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e);
|
|
|
+
|
|
|
+ } finally {
|
|
|
+ cursor?.close()
|
|
|
+ }
|
|
|
+ return ""
|
|
|
+}
|
|
|
+
|
|
|
+function saveFileFromUri(context : Context, uri : Uri) : string {
|
|
|
+ let file : File;
|
|
|
+ const contentResolver : ContentResolver = context.getContentResolver();
|
|
|
+ const cursor : Cursor | null = contentResolver.query(uri, null, null, null, null);
|
|
|
+ if (cursor != null && cursor.moveToFirst()) {
|
|
|
+ const displayName = getFileName(context, uri)
|
|
|
+ try {
|
|
|
+
|
|
|
+ const is = contentResolver.openInputStream(uri);
|
|
|
+ if (is != null) {
|
|
|
+ const file1 : File = new File(context.getExternalCacheDir()?.getAbsolutePath() + "/" + System.currentTimeMillis());
|
|
|
+ if (!file1.exists()) {
|
|
|
+ file1.mkdir();
|
|
|
+ }
|
|
|
+ const cache : File = new File(file1.getPath(), displayName);
|
|
|
+ const fos = new FileOutputStream(cache);
|
|
|
+ FileUtils.copy(is, fos);
|
|
|
+ file = cache;
|
|
|
+ fos.close();
|
|
|
+ is.close();
|
|
|
+ return file.getAbsolutePath();
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ return ""
|
|
|
+}
|