美文网首页
Unity2019.2.9 安卓调用安装apk,安卓全版本适用

Unity2019.2.9 安卓调用安装apk,安卓全版本适用

作者: Walk_In_Jar | 来源:发表于2020-03-12 10:21 被阅读0次

    安卓7的三星s7,redmi k20 pro 安卓10测试通过
    找到了个老机器,安卓5.1的某为,安装后居然粉屏了,但等待一会后也弹出了安装界面,功能应该是没问题了。

    首先确定包名,我用的是com.chengdu.sichuan。以免混淆。
    apk地址在是qq的下载地址

    https://qd.myapp.com/myapp/qqteam/QQ_JS/qqlite_4.0.0.1025_537062065.apk

    备用。

    Android Studio创建工程,详细步骤参考上一篇制作aar包教程

    修改AndroidManife.xml
    使用provider和添加一些权限


    image.png

    xml/filepaths的意思是在main/res目录下创建xml文件夹,创建filepaths.xml文件


    image.png
    完整filepaths.xml如下
    <?xml version="1.0" encoding="utf-8"?>
    <paths>
        <external-path
            name="external_storage_root"
            path="." />
        <files-path
            name="files-path"
            path="." />
        <cache-path
            name="cache-path"
            path="." />
        <!--/storage/emulated/0/Android/data/...-->
        <external-files-path
            name="external_file_path"
            path="." />
        <!--代表app 外部存储区域根目录下的文件 Context.getExternalCacheDir目录下的目录-->
        <external-cache-path
            name="external_cache_path"
            path="." />
        <!--配置root-path。这样子可以读取到sd卡和一些应用分身的目录,否则微信分身保存的图片,就会导致 java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/999/tencent/MicroMsg/WeiXin/export1544062754693.jpg,在小米6的手机上微信分身有这个crash,华为没有
    -->
        <root-path
            name="root-path"
            path="" />
        </paths>
    
    

    完整Androidmanife.xml如下

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.chengdu.sichuan">
    
        <application
            android:allowBackup="true"
            android:label="@string/app_name"
            android:supportsRtl="true"
            >
            <activity android:name=".MainActivity">
                <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>
    
            <provider
                android:name="androidx.core.content.FileProvider"
                android:authorities="com.chengdu.sichuan.fileprovider"
                android:grantUriPermissions="true"
                android:exported="false">
                <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/filepaths" />
            </provider>
    
        </application>
    
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.REPLACE_EXISTING_PACKAGE"/>
        <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
    </manifest>
    

    FileProvider报红的话,回到MainActivity.java

    import androidx.core.content.FileProvider;

    提供方法InstallApkUnity,参数是apk保存的路径


    image.png

    完整如下

    package com.chengdu.sichuan;
    //import androidx.appcompat.app.AppCompatActivity;
    import android.content.Intent;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Bundle;
    import android.widget.Toast;
    //import androidx.core.content.FileProvider;
    import androidx.core.content.FileProvider;
    import com.unity3d.player.UnityPlayer;
    import com.unity3d.player.UnityPlayerActivity;
    import java.io.File;
    public class MainActivity extends UnityPlayerActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
           // setContentView(R.layout.activity_main);
        }
      public void InstallApkUnity(String apkPath){
          UnityPlayer.UnitySendMessage("_gameController", "CallUnity",  apkPath);
          //这一行的目的是调用unity的方法,可以不要
          File file = new File(apkPath);
          Intent intent = new Intent(Intent.ACTION_VIEW);
          if(Build.VERSION.SDK_INT>=24) { //Android 7.0及以上
              intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
              Uri apkUri = FileProvider.getUriForFile(getApplicationContext(), UnityPlayer.currentActivity.getPackageName() +".fileprovider", file);//记住修改包名
              //对目标应用临时授权该Uri所代表的文件
              intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
          }else{
              intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
              intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
          }
          this.startActivity(intent);
      }
    //显示提示信息
        public void ShowToast(final String msg){
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(getApplicationContext(),msg,Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
    

    androidx.core是安卓10相关的类库
    按住Ctrl点击core,左边就会导航到这个文件

    image.png

    unity需要这个文件,右键Show in Explorer


    image.png

    这个文件备用。
    Make Project 一下,找到到aar包与AndroidManifest.xml文件

    新建unity工程,包名保持一致com.chengdu.sichuan

    image.png

    Plugins下创建Android/lib放入刚刚找到的classes.jar
    放入aar包与AndroidManifest.xml文件
    不要忘了打开aar文件,将里面的classes.jar里的BuildCongfig.class删除,关闭bandzip保存

    image.png

    创建Text用来显示内容


    image.png

    GameMama.cs内容如下

    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using UnityEngine;
    using UnityEngine.UI;
    public class GameMana : MonoBehaviour
    {
        HTTPDownLoad downLoad;
        AndroidJavaObject currentActivity;
        public Text text;
        private string action = "";
        private void Start()
        {
            if (Application.platform == RuntimePlatform.Android)
            {
                AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
                currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
            }
            string s = "https://qd.myapp.com/myapp/qqteam/QQ_JS/qqlite_4.0.0.1025_537062065.apk";
            DownLoadFile(s);
        }
        public void DownLoadFile(string url)//下载指定文件
        {
            action = "";
            downLoad = new HTTPDownLoad(url, Application.persistentDataPath + "/download/", 5000);
            downLoad.loadedEvent = ((string fm) =>
            {
                action = fm;
                Debug.Log("  下载完成" + fm);
            });
        }
        private void Update()
        {
            if (!string.IsNullOrEmpty(action))
            {
                 if (currentActivity != null)
                    currentActivity.Call("InstallApkUnity", action);
                action = "";
            }
        }
        public void CallUnity(string s)
        {
            text.text = s;
        }
    }
    

    HTTPDownLoad.cs内容如下

    using System;
    using System.Net;
    using System.IO;
    using System.Threading;
    using UnityEngine;
    /// <summary>
    /// 文件下载
    /// </summary>
    public class HTTPDownLoad
    {
        public delegate void OnDownLoadedEvent(string fm);
    
        public OnDownLoadedEvent loadedEvent;
    
        private string postfix = ".temp";//临时文件后缀名
        // 下载进度
        public float Progress
        {
            get;
            private set;
        }
        // 状态 0 正在下载 1 下载完成 -1 下载出错
        public int Status
        {
            get;
            private set;
        }
        // 错误信息
        public string Error
        {
            get;
            set;
        }
        // 总长度
        public long TotalLength
        {
            get;
            private set;
        }
        // 保存路径
        private string savePath;
        // url地址
        private string url;
        // 超时时间
        private int timeout;
        // 子线程
        private Thread thread;
        // 子线程是否停止标志
        public bool isStop;
    
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="url">url地址</param>
        /// <param name="timeout">超时时间</param>
        /// <param name="callback">回调函数</param>
        public HTTPDownLoad(string _url, string _savePath, int _timeout)
        {
            savePath = _savePath;
            url = _url;
            timeout = _timeout;
            DownLoad();
        }
        /// <summary>
        /// 开启下载
        /// </summary>
        void DownLoad()
        {
            Status = 0;
            isStop = false;
    
            // 开启线程下载
            thread = new Thread(StartDownLoad);
            thread.IsBackground = true;
            thread.Start();
        }
        public int poo = -1;
        /// <summary>
        /// 开始下载
        /// </summary>
        private void StartDownLoad()
        {
    
            try
            {
                if (!Directory.Exists(savePath))
                {
                    Directory.CreateDirectory(savePath);
                }
                string fileName = url.Split('/')[url.Split('/').Length - 1];
                string pathName = savePath + "/" + ErasePostfix(fileName) + postfix;
    
                // 构建文件流
                FileStream fs = new FileStream(pathName, FileMode.OpenOrCreate, FileAccess.Write);
                // 文件当前长度
                long fileLength = fs.Length;
                // 文件总长度
                TotalLength = GetDownLoadFileSize();
                // Debug.LogFormat("fileLen:{0}", TotalLength);
                if (fileLength < TotalLength)
                {
                    // 没有下载完成
                    fs.Seek(fileLength, SeekOrigin.Begin);
                    // 发送请求开始下载
                    HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
                    request.AddRange((int)fileLength);
                    request.Timeout = timeout;
                    // 读取文件内容
                    Stream stream = request.GetResponse().GetResponseStream();
                    if (stream.CanTimeout)
                    {
                        stream.ReadTimeout = timeout;
                    }
                    byte[] buff = new byte[4096];
                    int len = -1;
                    while ((len = stream.Read(buff, 0, buff.Length)) > 0)
                    {
                        if (isStop)
                        {
                            break;
                        }
                        fs.Write(buff, 0, len);
                        fileLength += len;
                        Progress = fileLength * 1.0f / TotalLength;
                       // Debug.Log(Progress);
                    }
                    stream.Close();
                    stream.Dispose();
                }
                else
                {
                    Progress = 1;
                }
                fs.Close();
                fs.Dispose();
                // 标记下载完成
                if (Progress == 1)
                {
                    Status = 1;
                    
                    string filepathName = savePath + "/" + fileName;
                    
                    if (File.Exists(filepathName))//删除原来的
                        File.Delete(filepathName);
                    File.Move(pathName, filepathName);
    
                    loadedEvent?.Invoke(filepathName);
                }
            }
            catch (Exception e)
            {
                Error = e.Message;
                Status = -1;
                Debug.Log(Error);
            }
        }
        /// <summary>
        /// 获取下载的文件大小
        /// </summary>
        /// <returns>文件大小</returns>
        public long GetDownLoadFileSize()
        {
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            request.Method = "HEAD";
            request.Timeout = timeout;
            HttpWebResponse response = request.GetResponse() as HttpWebResponse;
            return response.ContentLength;
        }
        /// <summary>
        /// 停止下载
        /// </summary>
        public void Close()
        {
            isStop = true;
        }
        private string ErasePostfix(string filePath)
        {
            return filePath.Substring(0, filePath.LastIndexOf('.'));
        }
    }
    
    image.png

    下载完成后会调用InstallApkUnity方法来安装,安卓10验证通过。
    安卓调用unity中的方法

        public void CallUnity(string s)
        {
            text.text = s;
        }
    
    image.png

    不要忘了在other Setting中设置读写外部存储


    image.png

    完整的安卓工程与unity资源包如下地址

    链接:https://pan.baidu.com/s/106HfAKDCMj0ABPCLtDD2-g
    提取码:3zt0

    相关文章

      网友评论

          本文标题:Unity2019.2.9 安卓调用安装apk,安卓全版本适用

          本文链接:https://www.haomeiwen.com/subject/hfmwdhtx.html