Unity Android交互自动安装更新

🤔开始做一个安卓小游戏,没有想到要去热更新它,结果做完才想到,有bug怎么办…

于是就有了下面的踩坑之旅。

版本环境
  • Unity 2020.3.20f1c1
  • Android Studio 4.1.3
踩坑之旅
Unity调用Android的方法
  1. 新建一个Empty Activity项目

  2. 点击完成后,删除红框内容无用内容

    变更后的AndroidManifest.xml文件

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="cn.linyisonger.callme">
    
        <application >
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                </intent-filter>
            </activity>
        </application>
    </manifest>
    
  3. 添加一个测试的静态方法

    image

  4. 修改继承自Activity

    image

  5. 修改构建文件

  6. 构建arr包

  7. 新建一个Unity工程

    image

  8. Build Settings… Ctrl+Shift+B

    image

    切换至Android平台

  9. 将生成好的arr包放入Plugins\Android目录下

    image

  10. 新建脚本调用它

    image

    新建Test脚本文件

    using UnityEngine;
    using UnityEngine.UI;
    
    public class Test : MonoBehaviour
    {
        public Text showResult;
    
        private void Start()
        {
            var jo = new AndroidJavaObject("cn.linyisonger.android.MainActivity");
            int sum = jo.CallStatic<int>("add", 1, 3);
            showResult.text = sum.ToString();
        }
    }
    

    新建一个Text随便改改样式、将脚本挂在Canvas上(😎当然挂在那里都是可以的,我就随便挂一下)、将Text组件拖至脚本的showResult字段上。

  11. 打包测试

    image

    添加场景、选择运行设备、构建并运行

  12. 效果

    image

Unity自动更新并调用安装

示意图 😂有点糙

image

  1. classes.jar包引入项目中来D:\Unity\2020.3.20f1c1\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes

    image

    右键添加类库

    image

  2. 将classes.jar设置为仅编译时构建,打包时不包含此文件(Unity打包会带上)

    implementation files('libs\\classes.jar') // 当前
    compileOnly fileTree(dir: "libs",includes: ["*.jar"]) // 修改
    

    image

  3. 添加安装方法

    MainActivity.java

    package cn.linyisonger.callme;
     
    import androidx.core.content.FileProvider;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Bundle;
    
    import com.unity3d.player.UnityPlayer;
    
    import java.io.File;
    
    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
    
        public static int add(int a, int b) {
            return a + b;
        }
    
        public static void install(String apkFullPath){
            Intent intent = new Intent(Intent.ACTION_VIEW);
            File file = new File(apkFullPath);
            if (Build.VERSION.SDK_INT >= 24) {
                Uri apkUri = FileProvider.getUriForFile(UnityPlayer.currentActivity.getApplicationContext(), UnityPlayer.currentActivity.getPackageName() +".fileprovider", file);
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
            } else {
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                Uri uri = Uri.fromFile(file);
                intent.setDataAndType(uri, "application/vnd.android.package-archive");
            }
            UnityPlayer.currentActivity.startActivity(intent);
        }
    
    }
    
  4. 构建arr包放置在Unity工程中

  5. 设置包名

    image

  6. 添加filepaths.xml文件,放在Android/res/xml下

    <?xml version="1.0" encoding="utf-8"?>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
        <external-path name="download" path="Android/data/cn.LinYisonger.CallAndroid/files/"/>
    </paths>
    

    image

  7. 添加AndroidManifest.xml文件,放在Android下

    <?xml version="1.0" encoding="utf-8"?>
    <!-- GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN-->
    <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player"
        xmlns:tools="http://schemas.android.com/tools">
        
        <uses-permission android:name="android.permission.INTERNET"></uses-permission>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
        <uses-permission android:name="android.permission.CALL_PHONE"/>
        <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
    
    
    
        <application>
            <provider android:name="androidx.core.content.FileProvider" android:authorities="cn.LinYisonger.CallAndroid.fileprovider" android:grantUriPermissions="true" android:exported="false" android:usesCleartextTraffic="true">
                <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/filepaths" />
            </provider>
            <activity android:name="com.unity3d.player.UnityPlayerActivity" android:theme="@style/UnityThemeSelector">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
                <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
            </activity>
        </application>
    </manifest>
    
  8. 添加更新脚本

    using System;
    using System.Collections;
    using System.IO;
    using UnityEngine;
    using UnityEngine.Networking;
    using UnityEngine.UI;
    
    public class Test1 : MonoBehaviour
    {
    
        /// <summary>
        /// 版本模型
        /// </summary> 
        public class VersionModel
        {
            /// <summary>
            /// Id
            /// </summary>
            public long id;
            /// <summary>
            /// 程序Key值
            /// </summary>
            public string key;
            /// <summary>
            /// 编号
            /// </summary>
            public string no;
            /// <summary>
            /// 描述
            /// </summary>
            public string desc;
            /// <summary>
            ///  安卓包路径
            /// </summary>
            public string apkUrl;
        }
        public delegate void LoadingAction(float progress);
        public delegate void VersionAction(VersionModel version);
        private VersionModel CurrentVersion;
    
        private string path => Application.persistentDataPath + "/update.apk";
    
        public Text UpdateText;
    
    
        private void Start()
        {
            StartCoroutine(GetCurrentVersion((v) =>
            {
                if (v.no != Application.version)
                {
                    StartCoroutine(Download((p) =>
                    {
                        // 下载进度
                        UpdateText.text = (p * 100).ToString("0.00");
                    },
                    () =>
                    {
                        // 下载完成
                        UpdateText.text = "下载完成";
                        // 安装
                        Install();
                    }));
                }
            }));
    
    
    
        }
    
        public IEnumerator GetCurrentVersion(VersionAction action)
        {
            UnityWebRequest webRequest = UnityWebRequest.Get("http://y.linyisonger.cn/api/version/GetTheLatestVersion?key=cn.LinYisonger.CallAndroid");
            yield return webRequest.SendWebRequest();
            CurrentVersion = JsonUtility.FromJson<VersionModel>(webRequest.downloadHandler.text);
            action.Invoke(CurrentVersion);
        }
        public IEnumerator Download(LoadingAction loading, Action done)
        {
            UnityWebRequest webRequest = UnityWebRequest.Get(CurrentVersion.apkUrl);
            webRequest.SendWebRequest();
            while (!webRequest.isDone)
            {
                loading(webRequest.downloadProgress);
                yield return 0;
            }
            File.WriteAllBytes(path, webRequest.downloadHandler.data);
            done();
            yield return null;
        }
        public void Install()
        {
            var jo = new AndroidJavaObject("cn.linyisonger.callme.MainActivity");
            jo.CallStatic("install", path);
        }
    }
    

    image

  9. 构建调试然后就会报错🤨

    WARNING: The option setting 'android.enableR8=false' is deprecated.
    It will be removed in version 5.0 of the Android Gradle plugin.
    You will no longer be able to disable R8
    

    image

    将构建的版本调整为3.4.0

    image

  10. 构建调试打开应用闪退啦! 😲

    找了很久原来是少引用了依赖库

    image

    # 添加依赖支持
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    

    image

  11. 构建调试

    image

参考文章
  • https://blog.csdn.net/wodownload2/article/details/118081593
  • https://www.jianshu.com/p/a6cad97ea54f
  • https://www.cnblogs.com/wuzhang/p/wuzhang20190405.html
  • https://blog.csdn.net/zhangjinlong1234/article/details/108569607
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林一怂儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值