155 lines
4.3 KiB
C#
155 lines
4.3 KiB
C#
using System;
|
||
using UnityEngine;
|
||
|
||
/// <summary>
|
||
/// Android文件选择器 - 调用Android原生文件选择器
|
||
/// </summary>
|
||
public class AndroidFilePicker : MonoBehaviour
|
||
{
|
||
public static AndroidFilePicker Instance { get; private set; }
|
||
|
||
// 回调事件
|
||
public event Action<string, string, byte[]> OnFileSelected; // 文件路径, 文件名, 文件数据
|
||
public event Action OnFileSelectCanceled;
|
||
public event Action<string> OnError;
|
||
|
||
private AndroidJavaClass _filePickerClass;
|
||
|
||
private void Awake()
|
||
{
|
||
if (Instance == null)
|
||
{
|
||
Instance = this;
|
||
DontDestroyOnLoad(gameObject);
|
||
}
|
||
else
|
||
{
|
||
Destroy(gameObject);
|
||
}
|
||
}
|
||
|
||
private void OnDestroy()
|
||
{
|
||
if (Instance == this)
|
||
{
|
||
Instance = null;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 打开文件选择器
|
||
/// </summary>
|
||
/// <param name="mimeTypes">可选的MIME类型过滤器,如 "application/octet-stream"</param>
|
||
public void PickFile(string[] mimeTypes = null)
|
||
{
|
||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||
Debug.Log("[FILE-PICKER] [CS] PickFile() 被调用");
|
||
try
|
||
{
|
||
if (_filePickerClass == null)
|
||
{
|
||
Debug.Log("[FILE-PICKER] [CS] 初始化 FilePicker Java类...");
|
||
_filePickerClass = new AndroidJavaClass("com.unity.filepicker.FilePicker");
|
||
Debug.Log("[FILE-PICKER] [CS] FilePicker Java类初始化成功");
|
||
}
|
||
|
||
// 创建回调代理
|
||
Debug.Log("[FILE-PICKER] [CS] 创建回调代理...");
|
||
FilePickerCallbackProxy callbackProxy = new FilePickerCallbackProxy(this);
|
||
Debug.Log("[FILE-PICKER] [CS] 回调代理创建成功");
|
||
|
||
// 调用Java方法
|
||
Debug.Log("[FILE-PICKER] [CS] 调用Java方法 pickFile...");
|
||
_filePickerClass.CallStatic("pickFile", mimeTypes, callbackProxy);
|
||
|
||
Debug.Log("[FILE-PICKER] [CS] 打开文件选择器成功");
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"[FILE-PICKER] [CS] 打开文件选择器失败: {e.Message}\n{e.StackTrace}");
|
||
OnError?.Invoke($"打开文件选择器失败: {e.Message}");
|
||
}
|
||
#else
|
||
Debug.LogWarning("[FILE-PICKER] [CS] 仅在Android平台可用");
|
||
OnError?.Invoke("文件选择器仅在Android平台可用");
|
||
#endif
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从Unity接收文件选择结果
|
||
/// </summary>
|
||
public void OnFileSelectedFromJava(string filePath, string fileName, byte[] fileData)
|
||
{
|
||
Debug.Log($"[FILE-PICKER] [CS] 选择文件成功: {fileName}, 大小: {fileData?.Length ?? 0}");
|
||
|
||
// 在主线程执行回调
|
||
Loom.QueueOnMainThread(() =>
|
||
{
|
||
OnFileSelected?.Invoke(filePath, fileName, fileData);
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从Unity接收取消事件
|
||
/// </summary>
|
||
public void OnFileSelectCanceledFromJava()
|
||
{
|
||
Debug.Log("[FILE-PICKER] [CS] 用户取消选择");
|
||
|
||
Loom.QueueOnMainThread(() =>
|
||
{
|
||
OnFileSelectCanceled?.Invoke();
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从Unity接收错误
|
||
/// </summary>
|
||
public void OnErrorFromJava(string error)
|
||
{
|
||
Debug.LogError($"[FILE-PICKER] [CS] 错误: {error}");
|
||
|
||
Loom.QueueOnMainThread(() =>
|
||
{
|
||
OnError?.Invoke(error);
|
||
});
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 文件选择器回调代理 - 用于Java到C#的回调
|
||
/// </summary>
|
||
public class FilePickerCallbackProxy : AndroidJavaProxy
|
||
{
|
||
private AndroidFilePicker _picker;
|
||
|
||
public FilePickerCallbackProxy(AndroidFilePicker picker) : base("com.unity.filepicker.FilePicker$FilePickerCallback")
|
||
{
|
||
_picker = picker;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 文件选择成功回调
|
||
/// </summary>
|
||
public void onFileSelected(string filePath, string fileName, byte[] fileData)
|
||
{
|
||
_picker?.OnFileSelectedFromJava(filePath, fileName, fileData);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 用户取消回调
|
||
/// </summary>
|
||
public void onFileSelectCanceled()
|
||
{
|
||
_picker?.OnFileSelectCanceledFromJava();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 错误回调
|
||
/// </summary>
|
||
public void onError(string error)
|
||
{
|
||
_picker?.OnErrorFromJava(error);
|
||
}
|
||
}
|