久久精品国产亚洲高清|精品日韩中文乱码在线|亚洲va中文字幕无码久|伊人久久综合狼伊人久久|亚洲不卡av不卡一区二区|精品久久久久久久蜜臀AV|国产精品19久久久久久不卡|国产男女猛烈视频在线观看麻豆

    1. <style id="76ofp"></style>

      <style id="76ofp"></style>
      <rt id="76ofp"></rt>
      <form id="76ofp"><optgroup id="76ofp"></optgroup></form>
      1. 千鋒教育-做有情懷、有良心、有品質(zhì)的職業(yè)教育機構

        手機站
        千鋒教育

        千鋒學習站 | 隨時隨地免費學

        千鋒教育

        掃一掃進入千鋒手機站

        領取全套視頻
        千鋒教育

        關注千鋒學習站小程序
        隨時隨地免費學習課程

        當前位置:首頁  >  技術干貨  > Unity使用Obb擴展包的正確姿勢

        Unity使用Obb擴展包的正確姿勢

        來源:千鋒教育
        發(fā)布人:qyf
        時間: 2022-08-18 17:35:00 1660815300

        未命名圖片 (3)

          由于Google Play上不能上傳大于100M的包,所以需要將應用進行Obb分包,資源文件打包到Obb中,在Apk啟動的時候再從Obb擴展文件中加載資源。

          如何生成Obb擴展資源文件

          Unity可以自動為你進行分包操作,只需要你在發(fā)布安卓版本的時候進行簡單的設置,當然也可以自己根據(jù)需求通過以下命令進行分包。

          // jobb 命令在sdk\tools目錄下jobb -pn-pv-d \資源 -o G:\輸出包名(如main.1.com.google.obb)

          obb擴展文件的命名規(guī)則為:

          main文件:main...obb

          patch文件:patch...obb

          按照Unity分包的規(guī)則,主APK文件主要包括Java、Native代碼、游戲腳本、插件以及第一個場景包含的所有資源。Obb包主要是資源文件,在Unity打包Apk過程中,會把所有的資源文件(包括 streaming Assets)打包到Assets目錄下,而Obb分包后會將第一個場景以外的資源都打包到Obb目錄中,在Apk啟動后,會根據(jù)相應命名規(guī)則從Obb中加載資源文件。而在Unity里面為了安全性還封裝了一些校驗規(guī)則,下面會提取出相關的校驗規(guī)則供我們下載校驗(這只針對通過Unity直接打包會生成相關的校驗規(guī)則,如果你是導出工程然后再進行分包、打包那么Unity這套規(guī)則并不直接適用于你,為了安全性你可以自己實現(xiàn)一套類似的規(guī)則)。

          如何使用Obb擴展資源文件

          大多數(shù)情況下,當用戶從Google Play上下載應用時,Google Play會自動將APK文件和擴展文件同時下載下來,至于具體是哪些cases下Google Play無法下載擴展文件并沒有說明,此外即使Google Play正確的下載了擴展文件,但是由于擴展文件存放的目錄是可以被用戶和其他應用訪問的。但是Google Play并不總是保證一定會下載擴展文件,一般情況下我們需要將生成的apk以及obb下載下來的擴展文件有可能會被用戶或其他應用刪除。

          其次,我們的安裝包除了在Google Play平臺,也會在其他渠道上架,所以為了保證用戶下載簡潔可靠,我們需要在應用中自行實現(xiàn)擴展文件完整性檢查和下載的機制。

          如何手動下載Obb資源擴展文件

          1.如果你的Obb擴展文件上傳到Google平臺,那么你可以使用Android中提供的APK擴展文件下載庫Downloader Library來簡化擴展文件檢查和下載的邏輯,具體可以參考以及Google Play APK擴展文件機制及開發(fā)流程詳解,然而這種方式限制多多,需要支持google框架,不能應用于其他渠道等等...

          2.將擴展文件上傳到自己的服務器,原理上就可以適用于所有的渠道,需要的就是實現(xiàn)一個網(wǎng)絡下載器。

          手動校驗Obb是否已經(jīng)下載完成

          UnityPlayer是一個UI場景類,在UnityPlayerActivity會初始化該類,在進入游戲前,這個類里面會讀取本地Obb文件生成校驗碼并與打包Apk時,配置在setting.xml中的校驗表對比,如果校驗失敗,則不會進入游戲場景,配置表如下:

          Assets/bin/Data/Setting.xml

        <?xml version="1.0" encoding="UTF-8"?><settings>  <integer name="splash_mode">0</integer>  <bool name="useObb">True</bool>  <bool name="9f6f9912e7e5c791037078042be85f73">True</bool></settings>

          splash_mode:應該是定義啟動模式

          useObb:是否使用Obb,如果沒有使用Unity進行Obb分包,那么該選項始終是False。

          9f6f9912e7e5c791037078042be85f73:表示加密算法生成的校驗碼。

          項目中需要做的是在進入游戲后去進行一次Obb校驗,防止用戶重復下載Obb,如果校驗失敗就需要我們在游戲中自動去下載Obb包,我們把Unity中校驗Obb的步驟拎出來,一共三部。

          檢測Obb文件是否存在

          根據(jù)Obb文件生成校驗碼

          讀取setting.xml文件,并與校驗碼做對比

          下面的具體的一些代碼,主要規(guī)則來源于UnityPlayer。

          獲取Obb文件

          /**

          * 獲取應用obb位置

          * @param paramContext

          * @return

          */

          private static String[] getObbPath(Context paramContext) { String str1 = paramContext.getPackageName();

          VectorlocalVector = new Vector(); try {

          int i1 = paramContext.getPackageManager().getPackageInfo(str1, 0).versionCode; if (Environment.getExternalStorageState().equals("mounted")) {

          File localFile1 = Environment.getExternalStorageDirectory();

          File localFile2 = new File(localFile1.toString()

          + "/Android/obb/" + str1); if (localFile2.exists()) { if (i1 > 0) { String str3 = localFile2 + File.separator + "main."

          + i1 + "." + str1 + ".obb"; if (new File(str3).isFile()) {

          localVector.add(str3);

          }

          } if (i1 > 0) { String str2 = localFile2 + File.separator + "patch."

          + i1 + "." + str1 + ".obb"; if (new File(str2).isFile()) {

          localVector.add(str2);

          }

          }

          }

          } String[] arrayOfString = new String[localVector.size()];

          localVector.toArray(arrayOfString); return arrayOfString;

          } catch (PackageManager.NameNotFoundException localNameNotFoundException) {

          } return new String[0];

          }

          加密生成校驗碼算法:

          /**

          * 通過obb文件獲取加密MD5

          * @param paramString

          * @return

          */

          private static String getMd5(String paramString) { try {

          Log.d("WARX", "path = " + paramString);

          MessageDigest localMessageDigest = MessageDigest.getInstance("MD5");

          FileInputStream localFileInputStream = new FileInputStream(

          paramString); long lenght = new File(paramString).length();

          localFileInputStream.skip(lenght - Math.min(lenght, 65558L)); byte[] arrayOfByte = new byte[1024]; for (int i2 = 0; i2 != -1; i2 = localFileInputStream

          .read(arrayOfByte)) {

          localMessageDigest.update(arrayOfByte, 0, i2);

          }

          BigInteger bi = new BigInteger(1, localMessageDigest.digest());

          Log.d("WARX", "md5 = " + bi.toString(16)); return bi.toString(16);

          } catch (FileNotFoundException localFileNotFoundException) {

          } catch (IOException localIOException) {

          } catch (NoSuchAlgorithmException localNoSuchAlgorithmException) {

          } return null;

          }

          這里主要是根據(jù)文件的長度生成的一個md校驗碼。

          解析XML算法:

          private static Bundle getXml(Context context) {

          Bundle bundle = new Bundle();

          XmlPullParser localXmlPullParser; // int i1;

          String str; try {

          File localFile = new File(context.getPackageCodePath(), "assets/bin/Data/settings.xml"); Object localObject1; if (localFile.exists())

          localObject1 = new FileInputStream(localFile); else

          localObject1 = context.getAssets()

          .open("bin/Data/settings.xml");

          XmlPullParserFactory localXmlPullParserFactory = XmlPullParserFactory

          .newInstance();

          localXmlPullParserFactory.setNamespaceAware(true);

          localXmlPullParser = localXmlPullParserFactory.newPullParser();

          localXmlPullParser.setInput((InputStream) localObject1,null);

          int type = localXmlPullParser.getEventType(); Object localObject2 = null;

          str = null; while (type!=1) { switch (type) { case 2: if (localXmlPullParser.getAttributeCount()==0) {

          type = localXmlPullParser.next(); continue;

          }

          str = localXmlPullParser.getName();

          localObject2 = localXmlPullParser.getAttributeName(0); if (!localXmlPullParser.getAttributeName(0).equals("name")){

          type = localXmlPullParser.next(); continue;

          }

          localObject2 = localXmlPullParser.getAttributeValue(0); if (str.equalsIgnoreCase("integer")) {

          bundle.putInt((String) localObject2,

          Integer.parseInt(localXmlPullParser.nextText()));

          } else if (str.equalsIgnoreCase("string")) {

          bundle.putString((String) localObject2,

          localXmlPullParser.nextText());

          } else if (str.equalsIgnoreCase("bool")) {

          bundle.putBoolean((String) localObject2, Boolean

          .parseBoolean(localXmlPullParser.nextText()));

          } else if (str.equalsIgnoreCase("float")) {

          bundle.putFloat((String) localObject2,

          Float.parseFloat(localXmlPullParser.nextText()));

          } break; default: break;

          }

          type = localXmlPullParser.next();

          }

          } catch (Exception localException) {

          localException.printStackTrace();

          } return bundle;

          }

          這里將xml中的數(shù)據(jù)讀取到一個Bundle中進行保存,Bundle內(nèi)部實現(xiàn)是Map。最后我們可以將生成的校驗碼與setting.xml中獲取的校驗碼進行對比,如果校驗失敗就可以啟動下載流程了,下載完成后重啟Activity,重新讀取Obb文件并加載資源。

          /**

          * 重啟Activity

          * @param context

          */

          public static void restartApplication(Activity context) {

          PackageManager packageManager = context.getPackageManager();

          Intent intent = packageManager.getLaunchIntentForPackage(context.getPackageName());

          ComponentName componentName = intent.getComponent();

          Intent mainIntent = IntentCompat.makeRestartActivityTask(componentName);

          mainIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);

          context.startActivity(mainIntent);

          System.exit(0);

          }

          關于使用obb所涉及到的權限問題

          最近需要把應用所用的權限最小化,那么獲取obb是否需要權限,這是一個非??拥臇|西,先看看官方的文檔。

          從文檔上可以看出來,是android 6.0需要權限,除了6.0都無需權限,但是使用我們手里的6.0設備去嘗試沒有權限都可以下載obb正常進行游戲,但是使用google play下載之后部分6.0機型讀取bugly上報訪問obb路徑被拒絕了,使用測試機也發(fā)現(xiàn)是偶發(fā)現(xiàn)象,下載了多次游戲,第一次的時候出現(xiàn)了訪問路徑拒絕,這就非常的蛋疼了。加上權限是肯定不會出問題的,我們剔除權限前游戲從未上報過這個問題,目前我們是增加了用戶讀取內(nèi)存權限解決問題。

          更多關于unity培訓的問題,歡迎咨詢千鋒教育在線名師。千鋒教育擁有多年IT培訓服務經(jīng)驗,采用全程面授高品質(zhì)、高體驗培養(yǎng)模式,擁有國內(nèi)一體化教學管理及學員服務,助力更多學員實現(xiàn)高薪夢想。

        tags:
        聲明:本站稿件版權均屬千鋒教育所有,未經(jīng)許可不得擅自轉(zhuǎn)載。
        10年以上業(yè)內(nèi)強師集結,手把手帶你蛻變精英
        請您保持通訊暢通,專屬學習老師24小時內(nèi)將與您1V1溝通
        免費領取
        今日已有369人領取成功
        劉同學 138****2860 剛剛成功領取
        王同學 131****2015 剛剛成功領取
        張同學 133****4652 剛剛成功領取
        李同學 135****8607 剛剛成功領取
        楊同學 132****5667 剛剛成功領取
        岳同學 134****6652 剛剛成功領取
        梁同學 157****2950 剛剛成功領取
        劉同學 189****1015 剛剛成功領取
        張同學 155****4678 剛剛成功領取
        鄒同學 139****2907 剛剛成功領取
        董同學 138****2867 剛剛成功領取
        周同學 136****3602 剛剛成功領取
        相關推薦HOT
        軟件開發(fā)管理流程中會出現(xiàn)哪些問題?

        一、需求不清需求不明確是導致項目失敗的主要原因之一。如果需求沒有清晰定義,開發(fā)人員可能會開發(fā)出不符合用戶期望的產(chǎn)品。二、通信不足溝通問...詳情>>

        2023-10-14 13:43:21
        軟件定制開發(fā)中的敏捷開發(fā)是什么?

        軟件定制開發(fā)中的敏捷開發(fā)是什么軟件定制開發(fā)中的敏捷開發(fā),從宏觀上看,是一個高度關注人員交互,持續(xù)開發(fā)與交付,接受需求變更并適應環(huán)境變化...詳情>>

        2023-10-14 13:24:57
        什么是PlatformIo?

        PlatformIO是什么PlatformIO是一個全面的物聯(lián)網(wǎng)開發(fā)平臺,它為眾多硬件平臺和開發(fā)環(huán)境提供了統(tǒng)一的工作流程,有效簡化了開發(fā)過程,并能兼容各種...詳情>>

        2023-10-14 12:55:06
        云快照與自動備份有什么區(qū)別?

        1、定義和目標不同云快照的主要目標是提供一種快速恢復數(shù)據(jù)的方法,它只記錄在快照時間點后的數(shù)據(jù)變化,而不是所有的數(shù)據(jù)。自動備份的主要目標...詳情>>

        2023-10-14 12:48:59
        服務器為什么要用Linux?

        服務器為什么要用Linux作為服務器操作系統(tǒng)的優(yōu)選,Linux在眾多選擇中脫穎而出。Linux作為服務器操作系統(tǒng)的優(yōu)選,有其獨特的優(yōu)勢和特點。包括其...詳情>>

        2023-10-14 12:34:11
        万山特区| 刚察县| 万宁市| 咸阳市| 余姚市| 山阴县| 石首市| 赫章县| 松原市| 南安市| 日照市| 夏邑县| 涟水县| 保定市| 望谟县| 湄潭县| 德江县| 衡东县| 秀山| 古丈县| 贵港市| 莒南县| 宾川县| 元氏县| 闸北区| 五大连池市| 东乌| 湖州市| 和林格尔县| 厦门市| 大埔县| 阜康市| 通渭县| 庆阳市| 类乌齐县| 甘南县| 锦州市| 建昌县| 晋州市| 米脂县| 衡东县|