You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

194 lines
6.5 KiB

import Intent from 'android.content.Intent';
import ClipData from 'android.content.ClipData';
import Uri from 'android.net.Uri';
import InputStream from 'java.io.InputStream';
import OpenableColumns from 'android.provider.OpenableColumns';
import Cursor from 'android.database.Cursor';
import File from 'java.io.File';
import FileInputStream from 'java.io.FileInputStream';
import FileOutputStream from 'java.io.FileOutputStream';
import BufferedOutputStream from 'java.io.BufferedOutputStream';
import ByteArrayInputStream from 'java.io.ByteArrayInputStream';
import { ChooseFileOption, ChooseFile, ChooseFileSuccessCallbackResult } from '../interface'
import { GeneralCallbackResultImpl } from '../unierror'
const REQUEST_CODE_CHOOSE_FILE : Int = 42
let resultFunction : ((requestCode : Int, resultCode : Int, data ?: Intent) => void) | null = null
class ChooseFileImpl implements ChooseFile {
name : string = ''
path : string = ''
// private _path : string = ''
size : number = 0
time : number = 0
type : string = 'file'
// private uri : Uri
constructor(uri : Uri, options : ChooseFileOption) {
// this.uri = uri
this.time = Date.now()
this.type = this.getFileTypeFromUri(uri);
// this._path = uri.getPath() ?? ''
this.getFileInfoFromUri(uri)
if (this.isCache(options)) {
console.log('isCache')
this.copyFileToCache(uri)
}
}
private isCache(options : ChooseFileOption) : boolean {
const extension = this.getFileExtension(this.name)
const extensions = options.extension
const type = options.type ?? 'all'
const hasExtension = extensions != null && extension != '' && extensions.includes(extension)
const isVideoOrImage = ['video', 'image'].includes(type)
const isFileAndNotVideoOrImage = type == 'file' && !['video', 'image'].includes(this.type);
if ((type == 'all' || isVideoOrImage || isFileAndNotVideoOrImage) && !hasExtension) {
return true
} else {
return false
}
}
private getFileExtension(fileName : string) : string {
const lastDotIndex = fileName.lastIndexOf(".");
if (lastDotIndex == -1) {
return "";
}
return fileName.substring(lastDotIndex + 1);
}
private copyFileToCache(uri : Uri) {
const cacheDir = UTSAndroid.getAppCachePath();
const context = UTSAndroid.getAppContext();
if(cacheDir != null) {
const path = new File(cacheDir);
if (!path.exists()) {
path.mkdir();
}
}
const destFile = new File(cacheDir, this.name);
try {
const inputStream = context!.getContentResolver().openInputStream(uri)
const outputStream = new FileOutputStream(destFile)
if (inputStream != null) {
let buffer = ByteArray(1024);
let c = inputStream.read(buffer)
while (c > 0) {
outputStream.write(buffer, 0, c);
c = inputStream.read(buffer)
}
}
this.path = cacheDir + this.name
} catch (e) {
}
}
private getFileTypeFromUri(uri : Uri) : string {
const context = UTSAndroid.getAppContext();
let fileType = 'file'
let mimeType = context!.getContentResolver().getType(uri);
if (mimeType != null) {
if (mimeType.startsWith("video")) {
fileType = "video";
} else if (mimeType.startsWith("image")) {
fileType = "image";
}
}
return fileType;
}
private getFileInfoFromUri(uri : Uri) {
const context = UTSAndroid.getAppContext();
let cursor = context!.getContentResolver().query(uri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
this.name = cursor.getString(cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME))
const fileSize = cursor.getLong(cursor.getColumnIndexOrThrow(OpenableColumns.SIZE));
this.size = Number.from(fileSize)
cursor.close();
} else if ("file".equals(uri.getScheme())) {
this.name = uri.getLastPathSegment() ?? '';
const file = new File(uri.getPath() ?? '');
const fileSize = file.length();
this.size = Number.from(fileSize)
}
}
}
export function chooseFile(options : ChooseFileOption) {
if (resultFunction != null) {
UTSAndroid.offAppActivityResult(resultFunction!)
}
const type = options.type ?? 'all'
const intent = new Intent(Intent.ACTION_GET_CONTENT);
if (type.equals("all") || type.equals("file")) {
intent.setType("*/*");
} else if (type.equals("video")) {
intent.setType("video/*");
} else if (type.equals("image")) {
intent.setType("image/*");
}
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, options.count == 1 ? false : true); // 允许多选
resultFunction = (requestCode : Int, resultCode : Int, data ?: Intent) => {
if (requestCode == REQUEST_CODE_CHOOSE_FILE) {
UTSAndroid.offAppActivityResult(resultFunction!);
if (resultCode == -1 && data != null) {
const clipData = data.getClipData();
const tempFiles : ChooseFile[] = []
if (clipData != null) {
// 多选
// const itemCount = clipData.getItemCount();
// if (options.count != null && options.count! > itemCount) {
// const err = new GeneralCallbackResultImpl(9010002, `选中文件数量超过${options.count}`)
// options.fail?.(err)
// options.complete?.(err)
// return
// }
for (let i = 0; i < clipData.getItemCount(); i++) {
const uri = clipData.getItemAt(i.toInt()).getUri();
const chooseFile = new ChooseFileImpl(uri, options);
if(chooseFile.path !=''){
tempFiles.push(chooseFile)
}
}
} else {
// 单选
const uri = data.getData();
if (uri != null) {
const chooseFile = new ChooseFileImpl(uri, options)
if(chooseFile.path !='' ){
tempFiles.push(chooseFile)
}
}
}
const count = options.count ?? Integer.MAX_VALUE // Number.MAX_VALUE
if(tempFiles.length > 0 && count >= tempFiles.length){
options.success?.({
tempFiles,
errMsg: 'chooseFile:ok'
} as ChooseFileSuccessCallbackResult)
} else {
const err = new GeneralCallbackResultImpl(9010002, `没有可用的文件或文件超过设置数量`)
options.fail?.(err)
options.complete?.(err)
}
} else {
const err = new GeneralCallbackResultImpl(9010002, `没有可用的文件`)
options.fail?.(err)
options.complete?.(err)
}
} else {
const err = new GeneralCallbackResultImpl(9010002, `没有可用的文件`)
options.fail?.(err)
options.complete?.(err)
}
}
UTSAndroid.onAppActivityResult(resultFunction!)
UTSAndroid.getUniActivity()!.startActivityForResult(Intent.createChooser(intent, "选择文件"), REQUEST_CODE_CHOOSE_FILE)
// UTSAndroid.getUniActivity()!.overridePendingTransition((10).toInt(), (0).toInt());
}