killapp/Assets/Plugins/Android/FilePicker.java
2026-03-30 16:25:00 +08:00

251 lines
10 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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();
}
}