Unity 大版本更新之APK的下載與覆蓋安裝


  作為一個游戲開發者,更新這個技能是必不可少的!更新分為游戲內的更新,也就是所謂的資源熱更包括AssetBundle更新和代碼更新,代碼其實也是所謂的二進制文件,在安卓上和普通資源文件毫無差異,然而在IOS上差別大來個去了,由於蘋果爸爸所謂出於安全性的考慮,不支持JIT,我們也很無奈啊! 如今能繞過去的,只能靠解釋器去執行這部分被視為另類的代碼文件了,能解決的也就是今天各種版本的Lua和ILRuntime了!好了,夜已深,廢話不多說了,開始今天正題!!!

1,如何通過Unity進行應用內更新?

  應用內的更新也就所謂的資源熱更了,從CDN上直接下載就完事了,下載的方式有很多,WWW,WebRequest,HttpWebRequest等,最不推薦的就是WWW,原因一: www.bytes這家伙很占內存,句柄有限,在IOS上文件過多,開的WWW超過句柄限制會有意想不到的驚喜(Bug),Unity官方已逐漸適應WebRequest取而代之了,推薦使用HttpWebRequest,支持斷點續傳,很是方便!

2,何時進行大版本更新,該如何更新呢?

  這個大版本更新要看如何設計了,我們游戲是采用高中低三位來決定該更新哪些東西,例如:當前版本號1.0.1,下次客戶端提高版本號到1.0.2或者1.1.0都是資源更新,如果大版本好改為2.x.x則進行大版本更新,如何更新呢?兩種方法,一通過"market://details?id=com.xxx.xxx"標記使用Android代碼打開應用市場內的應用,那么有經驗同學就看到了問題,如果我裝的不是本應用商店的應用呢,那不就涼了!!!是的,裝的不是手機應用商店的肯定涼不了啊,我們還有方法二呢,前往你下載的對應版本的cdn上直接下載就可以了啊!至於怎么下載請轉到1.

3,下載完了,我該怎么安裝呢?

  不要着急,安裝及其的簡單,Android原生提供了很好API,如果你的Android OS低於7.0那么只需要這幾行代碼就OK了!

    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    File apkFile = new File(apkFullPath);
    Uri uri = null; uri = Uri.fromFile(apkFile);
    intent.setDataAndType(uri, "application/vnd.android.package-archive");
    MainActivity.instance.startActivity(intent);

 

  為什么我強調了下是7.0的呢,因為Android 7.0 行為變更了所以這么寫會報錯的,嘗試傳遞 file://URI可能會觸發FileUriExposedException。不要慌,那么如何解決呢?我們首先需要在 AndroidManifest里添加 provider 標簽,通過這個標簽將apk所在路徑的share出去,這樣本次就能訪問該路徑下的apk了,那么這個錯誤也就引刃而解了!如何使用這個provider呢,別着急,手把手教你如何使用provider。

第一步:先在AndroidManfiest.xml添加provider標簽,位置在 application內即可!

    <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.wuzhang.testandroid.fileProvider"
            android:grantUriPermissions="true"
            android:exported="false">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths" />
      </provider>

別忘記還要加個安裝的權限: <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/> 

第二步:指定共享目錄,在res下創建/xml/provider_paths.xml,路徑見下圖

provider_paths.xml文件

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="publicDir" path=""/>
</paths>

解釋下,此處name="publicDir"無實際意義,就是一個解釋而已,path=“”;表示的是這個目錄是當前根目錄下的不再添加子目錄等價於Unity中的Application.persistentDataPath也就是安卓設備上的storage/0/android/data/com.wuzhang.testandroid/files/

第三步:再次調用apk安裝代碼

    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    File apkFile = new File(apkFullPath);
    Uri uri = null;
    String path = MainActivity.instance.getApplicationContext().getPackageName() + ".fileProvider";
    uri = FileProvider.getUriForFile(MainActivity.instance, path,apkFile);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent.setDataAndType(uri, "application/vnd.android.package-archive");
    MainActivity.instance.startActivity(intent);

PS:這里有個地方需要注意,為何非要是這個順序???

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

  ...

  ...

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

為什么setFlag放到上面就可以,addFlag放上面就不行呢???原因很簡單,當setFlag時會先清空intent下之前所有的flag,所以addFlag的FLAG_GRANT_READ_URI_PERMISSION就無效了,本人親自踩的坑,多么痛的禮物!

這一切到搞定了,打包真機測試,android 7.0的果然好了,年輕人,別高興的太早,說完又遇到一個坑,8.0以上的系統死活不會彈出安裝界面,一首涼涼送給自己,,,但是馬上就要看到勝利的曙光了,一定要淡定,車到山前必有路,辦法總比困難多!!!

最終安裝代碼,完美兼容,Android 7.0,8.0

public static void installApk(String apkFullPath)
{
    try
    {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        Log.v("android", apkFullPath);
        onCoderReturn(apkFullPath);
        File apkFile = new File(apkFullPath);
        Uri uri = null;
        if (Build.VERSION.SDK_INT >= 24)
        {
            String path = MainActivity.instance.getApplicationContext().getPackageName() + ".fileProvider";
            Log.v("android", path);
            uri = FileProvider.getUriForFile(MainActivity.instance, path, apkFile);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }
        else
        {
            uri = Uri.fromFile(apkFile);
            Log.v("android", apkFile.getAbsolutePath());
        }
        onCoderReturn("install" + uri.getPath());
        intent.setDataAndType(uri, "application/vnd.android.package-archive");
        //解決安卓8.0安裝界面不彈出
        //查詢所有符合 intent 跳轉目標應用類型的應用,注意此方法必須放置在 setDataAndType 方法之后
        List<ResolveInfo> resolveLists = MainActivity.instance.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        // 然后全部授權
        for (ResolveInfo resolveInfo : resolveLists)
        {
            String packageName = resolveInfo.activityInfo.packageName;
            MainActivity.instance.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        }
        MainActivity.instance.startActivity(intent);
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}

好了,到此基本上真的結束了,還有一個可優化的是安裝完成可以做個自動啟動app就完美了,這個有時間繼續完善!時間過得好快1點開始寫的,現在都快3點半了,困的不行了,得睡覺了,祝大家小長假玩的愉快,有問題可以聯系我一起探討!



免責聲明!

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



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