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

參考文章


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM