You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Meta Quest 2中通过自定义启动器安装APK?技术实现求助

Meta Quest平台Unity VR启动器APK安装问题排查与解决方案

我开发了一款VR游戏启动器,用户安装后可访问我开发的所有VR游戏。这个启动器在PICO平台借助官方API运行流畅,但到Meta Quest平台遇到了瓶颈——Quest的游戏只能通过Oculus Store、App Lab或SideQuest安装,没有直接的程序化安装路径。我尝试过调用SideQuest的安装能力,没能成功;也写了一段Unity调用Android Intent的代码,同样失效:

public void InstallApp(string apkPath, Action<int> instalationCallback)
{
    AndroidJavaClass intentClass = new AndroidJavaClass("android.content.Intent");
    AndroidJavaObject intentObject = new AndroidJavaObject("android.content.Intent");

    string uriString = apkPath;
    AndroidJavaObject uriObject = new AndroidJavaObject("android.net.Uri", uriString);

    intentObject.Call<AndroidJavaObject>("setAction", intentClass.GetStatic<string>("ACTION_VIEW"));
    intentObject.Call<AndroidJavaObject>("setDataAndType", uriObject, "application/vnd.android.package-archive");

    AndroidJavaClass unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    AndroidJavaObject unityActivityObject = unityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity");

    unityActivityObject.Call("startActivity", intentObject);
}

代码失效的核心原因

这段代码没生效主要是踩了Meta Quest Android系统的几个限制坑:

  • URI权限不足:Android 7.0+(Quest基于该版本)禁止直接传递本地文件路径的Uri,必须用FileProvider生成带临时权限的Content Uri,否则系统会拦截文件访问请求
  • 缺少权限标记:没给Intent添加FLAG_GRANT_READ_URI_PERMISSION,系统安装器无法读取APK文件
  • 未处理异常:Quest系统对第三方安装请求管控严格,直接启动Activity可能抛出权限异常,没有捕获就无法定位问题
  • Quest政策限制:Meta默认禁止第三方应用直接触发安装,需要用户手动开启「未知来源应用」权限

修正后的代码实现

using UnityEngine;
using System;
using System.IO;

public class ApkInstaller : MonoBehaviour
{
    public void InstallApp(string apkPath, Action<int> installationCallback)
    {
        // 先检查APK文件是否存在
        if (!File.Exists(apkPath))
        {
            installationCallback?.Invoke(-1); // 返回错误码:文件不存在
            return;
        }

        try
        {
            AndroidJavaClass intentClass = new AndroidJavaClass("android.content.Intent");
            AndroidJavaObject intentObject = new AndroidJavaObject("android.content.Intent");
            AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
            AndroidJavaClass fileProviderClass = new AndroidJavaClass("androidx.core.content.FileProvider");

            // 用FileProvider生成合法的Content Uri
            AndroidJavaObject fileObject = new AndroidJavaObject("java.io.File", apkPath);
            AndroidJavaObject uriObject = fileProviderClass.CallStatic<AndroidJavaObject>(
                "getUriForFile", 
                currentActivity, 
                currentActivity.Call<string>("getPackageName") + ".fileprovider", 
                fileObject
            );

            // 配置Intent参数
            intentObject.Call<AndroidJavaObject>("setAction", intentClass.GetStatic<string>("ACTION_VIEW"));
            intentObject.Call<AndroidJavaObject>("setDataAndType", uriObject, "application/vnd.android.package-archive");
            // 添加文件读取权限标记
            intentObject.Call<AndroidJavaObject>("addFlags", intentClass.GetStatic<int>("FLAG_GRANT_READ_URI_PERMISSION"));
            // 避免Activity栈冲突
            intentObject.Call<AndroidJavaObject>("addFlags", intentClass.GetStatic<int>("FLAG_ACTIVITY_NEW_TASK"));

            // 启动系统安装界面
            currentActivity.Call("startActivity", intentObject);
            installationCallback?.Invoke(0); // 返回成功码
        }
        catch (Exception e)
        {
            Debug.LogError("安装失败:" + e.Message);
            installationCallback?.Invoke(-2); // 返回错误码:调用异常
        }
    }
}

必须补充的配置步骤

  1. 修改AndroidManifest.xml
    要添加FileProvider的声明,否则无法生成合法的Content Uri:

    <application>
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>
    </application>
    
  2. 创建文件路径配置文件
    在res/xml目录下新建file_paths.xml,指定APK所在的存储目录(示例为Unity的外部文件目录):

    <?xml version="1.0" encoding="utf-8"?>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
        <external-files-path name="apk_files" path="." />
    </paths>
    

Meta Quest平台额外注意事项

  • 引导用户开启权限:必须让用户在Quest设置中开启「未知来源应用」(路径:设置 > 安全与隐私 > 未知来源应用),否则安装请求会被系统直接拦截
  • 符合Meta政策:如果是面向公开用户分发,更推荐将游戏发布到App Lab,然后在启动器中引导用户跳转至App Lab页面完成安装,避免违反Meta的开发者政策导致应用下架
  • SideQuest替代方案:SideQuest没有公开的程序化安装API,只能引导用户手动使用SideQuest的「安装APK」功能,或让用户开启ADB调试后使用SideQuest的CLI工具批量安装

内容的提问来源于stack exchange,提问作者Txomin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 12:25:33