killapp/Assets/Plugins/Android/FilePicker.java

251 lines
10 KiB
Java
Raw Normal View History

2026-03-30 16:25:00 +08:00
package com.unity.filepicker;
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.provider.OpenableColumns;
import android.util.Log;
import com.unity3d.player.UnityPlayer;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
public class FilePicker {
private static final String TAG = "[FILE-PICKER]";
private static final int REQUEST_CODE_PICK_FILE = 1001;
private static FilePickerCallback callback;
public interface FilePickerCallback {
void onFileSelected(String filePath, String fileName, byte[] fileData);
void onFileSelectCanceled();
void onError(String error);
}
/**
* 打开文件选择器
*/
public static void pickFile(String[] mimeTypes, FilePickerCallback cb) {
Log.d(TAG, "[JAVA] pickFile() 被调用");
callback = cb;
try {
Activity activity = UnityPlayer.currentActivity;
if (activity == null) {
Log.e(TAG, "[JAVA] UnityPlayer.currentActivity 为 null");
if (callback != null) {
callback.onError("无法获取当前Activity");
}
return;
}
Log.d(TAG, "[JAVA] 获取到当前Activity: " + activity.getClass().getName());
// 设置回调到 Activity
setupActivityCallback(activity);
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
// 设置可选的MIME类型
if (mimeTypes != null && mimeTypes.length > 0) {
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
Log.d(TAG, "[JAVA] 设置MIME类型: " + java.util.Arrays.toString(mimeTypes));
}
intent.addCategory(Intent.CATEGORY_OPENABLE);
// 创建选择器
Intent chooser = Intent.createChooser(intent, "选择固件文件");
Log.d(TAG, "[JAVA] 创建文件选择器Intent成功");
// 启动文件选择器
Log.d(TAG, "[JAVA] 启动文件选择器requestCode=" + REQUEST_CODE_PICK_FILE);
activity.startActivityForResult(chooser, REQUEST_CODE_PICK_FILE);
Log.d(TAG, "[JAVA] startActivityForResult 调用成功");
} catch (Exception e) {
Log.e(TAG, "[JAVA] 打开文件选择器失败: " + e.getMessage());
e.printStackTrace();
if (callback != null) {
callback.onError("打开文件选择器失败: " + e.getMessage());
}
}
}
/**
* 设置Activity回调
*/
private static void setupActivityCallback(Activity activity) {
Log.d(TAG, "[JAVA] 设置Activity回调...");
// 使用反射设置回调
try {
// 检查是否是 UnityActivityCallback 类型
if (activity instanceof UnityActivityCallback) {
Log.d(TAG, "[JAVA] Activity 是 UnityActivityCallback 类型");
((UnityActivityCallback) activity).setCallback(new UnityActivityCallback.FilePickerResultCallback() {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "[JAVA] UnityActivityCallback.onActivityResult: requestCode=" + requestCode + ", resultCode=" + resultCode);
handleActivityResult(requestCode, resultCode, data);
}
});
} else {
Log.w(TAG, "[JAVA] Activity 不是 UnityActivityCallback 类型,尝试使用反射");
// 尝试使用反射设置静态回调
UnityActivityCallback.setCallback(new UnityActivityCallback.FilePickerResultCallback() {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "[JAVA] 通过反射回调: requestCode=" + requestCode + ", resultCode=" + resultCode);
handleActivityResult(requestCode, resultCode, data);
}
});
}
Log.d(TAG, "[JAVA] Activity回调设置成功");
} catch (Exception e) {
Log.e(TAG, "[JAVA] 设置Activity回调失败: " + e.getMessage());
e.printStackTrace();
}
}
/**
* 处理Activity结果 - 这个方法会被UnityActivityCallback调用
*/
public static void handleActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "[JAVA] handleActivityResult: requestCode=" + requestCode + ", resultCode=" + resultCode);
if (requestCode != REQUEST_CODE_PICK_FILE) {
Log.d(TAG, "[JAVA] requestCode不匹配忽略");
return;
}
if (resultCode != Activity.RESULT_OK || data == null) {
Log.d(TAG, "[JAVA] 用户取消选择或data为null, resultCode=" + resultCode);
if (callback != null) {
callback.onFileSelectCanceled();
}
return;
}
// 在后台线程读取文件,避免阻塞主线程
final Activity activity = UnityPlayer.currentActivity;
final Uri uri = data.getData();
if (uri == null) {
Log.e(TAG, "[JAVA] 无法获取文件URI");
if (callback != null) {
callback.onError("无法获取文件URI");
}
return;
}
Log.d(TAG, "[JAVA] 文件URI: " + uri.toString());
Log.d(TAG, "[JAVA] 在后台线程读取文件...");
new Thread(new Runnable() {
@Override
public void run() {
try {
// 获取文件名
Log.d(TAG, "[JAVA] 获取文件名...");
final String fileName = getFileName(activity, uri);
Log.d(TAG, "[JAVA] 文件名: " + fileName);
// 读取文件数据
Log.d(TAG, "[JAVA] 读取文件数据...");
final byte[] fileData = readFileData(activity, uri);
Log.d(TAG, "[JAVA] 文件数据读取成功,大小: " + fileData.length);
// 获取文件路径
final String filePath = uri.toString();
Log.d(TAG, "[JAVA] 选择文件成功: " + fileName + ", 大小: " + fileData.length);
// 在主线程回调
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (callback != null) {
Log.d(TAG, "[JAVA] 调用回调 onFileSelected");
callback.onFileSelected(filePath, fileName, fileData);
} else {
Log.e(TAG, "[JAVA] callback 为 null");
}
}
});
} catch (final Exception e) {
Log.e(TAG, "[JAVA] 读取文件失败: " + e.getMessage());
e.printStackTrace();
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (callback != null) {
callback.onError("读取文件失败: " + e.getMessage());
}
}
});
}
}
}).start();
}
/**
* 获取文件名
*/
private static String getFileName(Activity activity, Uri uri) {
String result = null;
if (uri.getScheme().equals("content")) {
Log.d(TAG, "[JAVA] URI scheme is content, querying ContentResolver...");
try (Cursor cursor = activity.getContentResolver().query(uri, null, null, null, null)) {
if (cursor != null && cursor.moveToFirst()) {
int index = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
if (index >= 0) {
result = cursor.getString(index);
Log.d(TAG, "[JAVA] 从ContentResolver获取文件名: " + result);
}
}
} catch (Exception e) {
Log.e(TAG, "[JAVA] 查询ContentResolver失败: " + e.getMessage());
}
}
if (result == null) {
result = uri.getLastPathSegment();
Log.d(TAG, "[JAVA] 从URI path获取文件名: " + result);
}
return result != null ? result : "unknown";
}
/**
* 读取文件数据
*/
private static byte[] readFileData(Activity activity, Uri uri) throws Exception {
Log.d(TAG, "[JAVA] 开始读取文件数据...");
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try (InputStream inputStream = activity.getContentResolver().openInputStream(uri)) {
if (inputStream == null) {
throw new Exception("无法打开文件输入流");
}
byte[] buffer = new byte[4096];
int bytesRead;
int totalBytes = 0;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
totalBytes += bytesRead;
}
Log.d(TAG, "[JAVA] 文件读取完成,总字节数: " + totalBytes);
} catch (Exception e) {
Log.e(TAG, "[JAVA] 读取文件时发生错误: " + e.getMessage());
throw e;
}
return outputStream.toByteArray();
}
}