支持SMB的手机VR播放器(三):接收隐式intent

接前文,为了实现一个较为完整的播放器,需要支持从文件管理器中打开文件,而这一过程是通过接收隐式 intent 实现的。我们需要让 Unity 接收该隐式 intent。

声明 intent-filter

文件管理器打开一个应用时,会发送一个隐式 intent,系统会在应用的 AndroidManifest 中查找并匹配 intent-filter,之后将匹配成功的应用列出来供你选择(匹配规则见安卓开发文档)。

我们可以在 Unity Asset 目录的Plugins/Android/AndroidMainfest.xml中声明所需的 intent-filter,如下所示:

安卓文件管理器中打开对应文件时,会弹出选择应用的弹窗:

接收 intent

接收 intent 单靠 Unity C# 是实现不了的,需要写一些安卓代码,同时也需要一些 C# 代码配合。我们的目的是,应用开启时判断自身是否是由隐式 intent 拉起的,如果是,则将 intent 中的参数传递给 Unity。

打开 AndroidStudio,新建空工程,创建一个 Module,之后写几行简单的 Java 代码(本人 Unity C# 脚本小子,对 Java 不熟,勿喷脚本质量):

public class MiaoPlayerEngine {
    static MiaoPlayerEngine _instance;
    protected  Activity _unityActivity;
    //获取单例
    public static MiaoPlayerEngine getInstance(Context unityActivity){
        if(_instance == null){
            _instance = new MiaoPlayerEngine();
            _instance._unityActivity = (Activity) unityActivity;
        }
        return _instance;
    }
    //获取 ActivityIntent
    public String getActivityIntent(){
        Intent intent = _instance._unityActivity.getIntent();

        if(intent != null && intent.getData() != null){
            //TODO:only for test, 对于 uri content://media/external/xxx 来说需要处理才能给 Unity 用
            try {
                return getRealPath(intent.getData());
            }catch(Exception e){
                System.err.println(e.toString());
                return intent.getData().toString();
            }
        }else{
            System.out.println("getIntentIs Null");
            return "";
        }
    }
//https://stackoverflow.com/a/10564727,测试代码,将 content://media/external/xxx 转成绝对路径
    public String getRealPath(Uri contentUri){
        String[] proj = { MediaStore.Images.Media.DATA };
        CursorLoader loader = new CursorLoader(_unityActivity.getApplicationContext(), contentUri, proj, null, null, null);
        Cursor cursor = loader.loadInBackground();
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        String result = cursor.getString(column_index);
        cursor.close();
        return result;
    }

    public void OnDestroy(){
        _instance = null;
    }
}

之后写一段 C# 代码用来生成上面的 Java 类,并调用其方法获取 intent 数据,关键代码如下:

public void Awake(){
        AndroidJavaClass playerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject activity = playerClass.GetStatic<AndroidJavaObject>("currentActivity");
        jc = new AndroidJavaClass("com.azimiao.miaoplayerhelper.MiaoPlayerEngine");
        jo = jc?.CallStatic<AndroidJavaObject>("getInstance", activity);
        if(jo == null)
        {
            Debug.LogError("ZAX MiaoPlayerEngine obj is null");
        }
}

public string GetIntent()
{
    if(jo != null)
    {
        string f = jo?.Call<string>("getActivityIntent");
        if (!string.IsNullOrEmpty(f))
        {
            Debug.Log("GetIntent is:" + f);
        }
        else
        {
            Debug.Log("GetIntent is empty");
        }
        return f;
    }
    return string.Empty;
}

真机运行

真机运行时,直接打开应用,获取 intent 数据为空:

通过文件管理器以打开方式弹窗的形式打开应用,获取到了 intent 路径数据:

至此,完成了 Unity 接收隐式 intent 的关键一步。

其他

虽然成功拿到了 intent 数据,但因为 Unity 端无法直接使用content://xxx这种媒体库形式的链接,后续还需要解决 intent 中的 uri 路径处理问题。

梓喵出没博客(azimiao.com)版权所有,转载请注明链接:https://www.azimiao.com/8316.html
欢迎加入梓喵出没博客交流群:313732000

我来吐槽

*

*