index.uts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. // index.uts
  2. // 引用android api
  3. import { UTSAndroid } from "io.dcloud.uts";
  4. import { ActivityCompat } from "androidx.core.app";
  5. import AlertDialog from 'android.app.AlertDialog';
  6. import { Context, Intent, ContentUris, ContentResolver } from "android.content";
  7. import Uri from "android.net.Uri";
  8. import FileUtils from "android.os.FileUtils";
  9. import { DocumentsContract, MediaStore } from "android.provider";
  10. import { File, FileOutputStream } from "java.io";
  11. import Activity from "android.app.Activity";
  12. import Cursor from "android.database.Cursor";
  13. import { Build, Environment, Bundle } from "android.os";
  14. import DialogInterface from 'android.content.DialogInterface';
  15. import JSONObject from 'com.alibaba.fastjson.JSONObject';
  16. class FileActivity extends Activity {
  17. constructor() {
  18. super();
  19. }
  20. override onCreate(savedInstanceState ?: Bundle) : void {
  21. super.onCreate(savedInstanceState)
  22. var dataUri = this.getIntent().getData()
  23. transUriStart(this, dataUri)
  24. }
  25. // override onResume() {
  26. // super.onResume()
  27. // var dataUri=this.getIntent().getData()
  28. // console.log(dataUri.toString())
  29. // }
  30. }
  31. type InfoOptions = {
  32. scope ?: string,
  33. permission ?: boolean,
  34. mimetype ?: string,
  35. action ?: string,
  36. success ?: (res : object) => void
  37. fail ?: (res : object) => void
  38. complete ?: (res : object) => void
  39. }
  40. const FILE_SELECT_REQUEST_CODE = 110
  41. export default function fileSelect(options : InfoOptions) {
  42. let permissionList = ["android.permission.READ_EXTERNAL_STORAGE"]
  43. const permission = options.permission;
  44. if (permission != null && permission) {
  45. UTSAndroid.gotoSystemPermissionActivity(UTSAndroid.getUniActivity()!, permissionList)
  46. return;
  47. }
  48. // 请求权限
  49. UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!, permissionList, function (allRight : boolean, grantedList : string[]) {
  50. if (allRight) {
  51. // 用户同意了全部权限
  52. if (options.action != null&&options.action=="openWithFile") {
  53. let prefs = UTSAndroid.getUniActivity()?.getSharedPreferences("lemonjkReceive",Context.MODE_PRIVATE)
  54. let res = prefs?.getString("receiveFromOtherApp","")
  55. if(res!=null&&res!=''){
  56. options.success?.(JSONObject.parse(res))
  57. options.complete?.(JSONObject.parse(res))
  58. }else{
  59. const res2 = {
  60. code: "1002",
  61. errMsg: 'fileselect:fail',
  62. detail: "文件不存在"
  63. }
  64. options.fail?.(res2)
  65. options.complete?.(res2)
  66. }
  67. }
  68. else if(options.action=='fk'){
  69. let fuck_intent = new Intent(UTSAndroid.getUniActivity(), FileActivity().javaClass);
  70. }
  71. else {
  72. fileSelectStart(options);
  73. }
  74. } else {
  75. // 用户仅同意了 grantedList中的权限
  76. options.fail?.({
  77. code: "1001",
  78. errMsg: 'fileselect:fail',
  79. detail: "未授权文件读取权限"
  80. })
  81. }
  82. }, function (doNotAskAgain : boolean, grantedList : string[]) {
  83. // 用户拒绝了部分权限,仅允许了grantedList中的权限
  84. // if (doNotAskAgain) {
  85. // // 用户拒绝了权限,并且选择不再询问
  86. // }
  87. options.fail?.({
  88. code: "1001",
  89. errMsg: 'fileselect:fail',
  90. detail: "未授权文件读取权限"
  91. })
  92. })
  93. }
  94. /**
  95. * 用户输入对话框监听器
  96. */
  97. class DialogListener extends DialogInterface.OnClickListener {
  98. callback : () => void
  99. constructor(cb : () => void) {
  100. super();
  101. this.callback = cb;
  102. }
  103. override onClick(_dialog : DialogInterface, _arg1 : Int) : void {
  104. // //数据获取
  105. // let input = this.inputET.getText().toString()
  106. this.callback();
  107. // Toast.makeText(UTSAndroid.getUniActivity(), input,
  108. // Toast.LENGTH_LONG).show();
  109. }
  110. }
  111. function transUriStart(context : Context, myUri ?: Uri) {
  112. let fileActivity = context as FileActivity;
  113. if (myUri != null) {
  114. // console.log(getRealPathFromURI(context, myUri))
  115. const newFile = new File(getRealPathFromURI(context, myUri));
  116. if (newFile.exists()) {
  117. let filePath = newFile.toString();
  118. let fileName = newFile.getName();
  119. let fileSize = newFile.length();
  120. const extIdx = fileName.lastIndexOf(".");
  121. let fileExt = extIdx != -1 ? fileName.substring(extIdx + 1) : ""
  122. const res = {
  123. code: "0",
  124. filePath: filePath,
  125. fileName: fileName,
  126. fileSize: fileSize,
  127. fileExt: fileExt,
  128. rawPath:myUri.toString(),
  129. errMsg: 'fileselect:ok',
  130. detail: "文件读取成功"
  131. }
  132. let editor=context.getSharedPreferences("lemonjkReceive",Context.MODE_PRIVATE).edit();
  133. editor.putString("receiveFromOtherApp", JSON.stringify(res))
  134. editor.apply();
  135. new AlertDialog.Builder(fileActivity)
  136. .setTitle("文件打开成功")
  137. .setMessage("[" + fileName + "]" + "已保存到应用中")
  138. .setPositiveButton("确定", new DialogListener(() => {
  139. fileActivity.finish();
  140. })).show();
  141. } else {
  142. const res2 = {
  143. code: "1002",
  144. errMsg: 'fileselect:fail',
  145. detail: "文件不存在"
  146. }
  147. new AlertDialog.Builder(fileActivity)
  148. .setTitle("文件打开失败")
  149. .setMessage("文件不存在")
  150. .setPositiveButton("确定", new DialogListener(() => {
  151. fileActivity.finish();
  152. })).show();
  153. console.log(res2)
  154. }
  155. } else {
  156. const res3 = {
  157. code: "1005",
  158. errMsg: 'fileselect:fail',
  159. detail: "文件选取出错:myUri为null"
  160. }
  161. new AlertDialog.Builder(fileActivity)
  162. .setTitle("文件打开失败")
  163. .setMessage("文件不存在")
  164. .setPositiveButton("确定", new DialogListener(() => {
  165. fileActivity.finish();
  166. })).show();
  167. console.log(res3)
  168. }
  169. }
  170. function fileSelectStart(options : InfoOptions) {
  171. const context = UTSAndroid.getAppContext();
  172. if (context != null) {
  173. const intent = new Intent(Intent.ACTION_GET_CONTENT);
  174. if (options.scope != null) {
  175. let strPath = options.scope
  176. strPath = strPath?.replaceAll("/", "%2F");
  177. let uriByScope : Uri = Uri.parse("content://com.android.externalstorage.documents/document/primary%3A" + strPath);
  178. intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, uriByScope);
  179. }
  180. var mimeType = "*/*";
  181. const mimetypeTemp = options.mimetype;
  182. if (mimetypeTemp != null) {
  183. mimeType = mimetypeTemp;
  184. }
  185. intent.setType(mimeType);
  186. intent.addCategory(Intent.CATEGORY_OPENABLE);
  187. UTSAndroid.getUniActivity()?.startActivityForResult(intent, FILE_SELECT_REQUEST_CODE);
  188. UTSAndroid.onAppActivityResult((requestCode : Int, resultCode : Int, data ?: Intent) => {
  189. UTSAndroid.offAppActivityResult(null);
  190. if (requestCode == FILE_SELECT_REQUEST_CODE && resultCode == Activity.RESULT_OK && data != null) {
  191. const fileUri = data.getData();
  192. // console.log(fileUri?.toString());
  193. if (fileUri != null) {
  194. let path = getRealPathFromURI(context, fileUri)
  195. const file = new File(path)
  196. if (file.exists()) {
  197. let upLoadFilePath = file.toString();
  198. let upLoadFileName = file.getName();
  199. let fileSize = file.length();
  200. const extIdx = upLoadFileName.lastIndexOf(".");
  201. let fileExt = extIdx != -1 ? upLoadFileName.substring(extIdx + 1) : ""
  202. const res = {
  203. code: "0",
  204. filePath: upLoadFilePath,
  205. fileName: upLoadFileName,
  206. fileSize: fileSize,
  207. fileExt: fileExt,
  208. errMsg: 'fileselect:ok',
  209. detail: "文件读取成功"
  210. }
  211. options.success?.(res)
  212. options.complete?.(res)
  213. } else {
  214. const res2 = {
  215. code: "1002",
  216. errMsg: 'fileselect:fail',
  217. detail: "文件不存在"
  218. }
  219. options.fail?.(res2)
  220. options.complete?.(res2)
  221. }
  222. }
  223. }
  224. });
  225. } else {
  226. const res3 = {
  227. code: "1005",
  228. errMsg: 'fileselect:fail',
  229. detail: "文件选取出错:context为null"
  230. }
  231. options.fail?.(res3)
  232. options.complete?.(res3)
  233. }
  234. }
  235. function getRealPathFromURI(context : Context, uri : Uri) : string {
  236. const isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
  237. //4.4以下的版本:不支持
  238. //大于4.4
  239. // DocumentProvider
  240. if (isKitKat) {
  241. if (DocumentsContract.isDocumentUri(context, uri)) {
  242. if (isExternalStorageDocument(uri)) {
  243. console.log("isExternalStorageDocument")
  244. return saveFileFromUri(context, uri)
  245. }
  246. // DownloadsProvider
  247. else if (isDownloadsDocument(uri)) {
  248. console.log("isDownloadsDocument")
  249. return saveFileFromUri(context, uri)
  250. }
  251. // MediaProvider
  252. else if (isMediaDocument(uri)) {
  253. console.log("isMediaDocument")
  254. return saveFileFromUri(context, uri)
  255. }
  256. }
  257. //其他 content
  258. else if ("content".equals(uri.getScheme())) {
  259. // return getDataColumn(context, uri, null, null);
  260. console.log("content")
  261. return saveFileFromUri(context, uri)
  262. }
  263. //其他 file
  264. else if ("file".equals(uri.getScheme())) {
  265. console.log("file")
  266. return uri.getPath() as string;
  267. }
  268. }
  269. return ""
  270. }
  271. function isExternalStorageDocument(uri : Uri) : boolean {
  272. return "com.android.externalstorage.documents".equals(uri.getAuthority());
  273. }
  274. function isDownloadsDocument(uri : Uri) : boolean {
  275. return "com.android.providers.downloads.documents".equals(uri.getAuthority());
  276. }
  277. function isMediaDocument(uri : Uri) : boolean {
  278. return "com.android.providers.media.documents".equals(uri.getAuthority());
  279. }
  280. // function getDataColumn(context : Context, uri : Uri, selection : string | null, selectionArgs : String[] | null) : string {
  281. // let column = "_data";
  282. // let projection = arrayOf<string>(column)
  283. // let cursor : Cursor | null = null;
  284. // const _selectionArgs = selectionArgs != null ? selectionArgs.toTypedArray() : null
  285. // try {
  286. // cursor = context.getContentResolver().query(uri, projection, selection, _selectionArgs, null);
  287. // if (cursor != null && cursor.moveToFirst()) {
  288. // const column_index = cursor.getColumnIndexOrThrow(column);
  289. // return cursor.getString(column_index);
  290. // }
  291. // } catch (e) {
  292. // console.log(e);
  293. // } finally {
  294. // if (cursor != null) {
  295. // cursor.close();
  296. // }
  297. // }
  298. // return "";
  299. // }
  300. function getFileName(context : Context, uri : Uri) : string {
  301. let projection = arrayOf(MediaStore.Images.ImageColumns.DISPLAY_NAME)
  302. let cursor = context.getContentResolver().query(uri, projection, null, null, null)
  303. try {
  304. if (cursor != null && cursor.moveToFirst()) {
  305. let name_col_index = cursor.getColumnIndex(projection[0])
  306. return cursor.getString(name_col_index)
  307. }
  308. } catch (e) {
  309. console.log(e);
  310. } finally {
  311. cursor?.close()
  312. }
  313. return ""
  314. }
  315. function saveFileFromUri(context : Context, uri : Uri) : string {
  316. let file : File;
  317. const contentResolver : ContentResolver = context.getContentResolver();
  318. const cursor : Cursor | null = contentResolver.query(uri, null, null, null, null);
  319. if (cursor != null && cursor.moveToFirst()) {
  320. const displayName = getFileName(context, uri)
  321. try {
  322. const is = contentResolver.openInputStream(uri);
  323. if (is != null) {
  324. const file1 : File = new File(context.getExternalCacheDir()?.getAbsolutePath() + "/" + System.currentTimeMillis());
  325. if (!file1.exists()) {
  326. file1.mkdir();
  327. }
  328. const cache : File = new File(file1.getPath(), displayName);
  329. const fos = new FileOutputStream(cache);
  330. FileUtils.copy(is, fos);
  331. file = cache;
  332. fos.close();
  333. is.close();
  334. return file.getAbsolutePath();
  335. }
  336. } catch (e) {
  337. console.log(e);
  338. }
  339. }
  340. return ""
  341. }