簡體   English   中英

如果擴展文件版本與 apk 版本代碼不同,使用 URI(使用 Google Zip 擴展庫)訪問 APK 擴展文件會導致崩潰

[英]Accessing APK expansion file with URI (with Google Zip Expansion Library) causes a crash if expansion file version is different from apk versioncode

我的 apk 版本代碼是版本 3。我正在使用加載了 apk 版本代碼 1 的主擴展文件(文件名類似於 main.1.ex.etc.eg.obb)。 擴展文件可以在設備上正常下載。

擴展文件有媒體文件,所以我使用 Google APEZProvider擴展庫中的 APEZProvider 與VideoView一起播放。

調用VideoView.start()會導致 Nullpointer 異常。

到目前為止我發現了什么:在APEZProvider.initIfNecessary()中返回主擴展文件版本 3 而不是 1。因此嘗試打開ZipResourceFile (mAPKExtensionFile) 返回APEZProvider.openAssetFile()導致NullPointerException因為mAPKExtensionFilenull

谷歌Zip擴展庫中APEZProvider class的相關代碼:

  private boolean initIfNecessary() {
    if ( !mInit ) {
        Context ctx = getContext();
        PackageManager pm = ctx.getPackageManager();
        ProviderInfo pi = pm.resolveContentProvider(getAuthority(), PackageManager.GET_META_DATA);
        PackageInfo packInfo;
        try {
            packInfo = pm.getPackageInfo(ctx.getPackageName(), 0);
        } catch (NameNotFoundException e1) {
            e1.printStackTrace();
            return false;
        }
        int patchFileVersion;
        int mainFileVersion;
        int appVersionCode = packInfo.versionCode;
        if ( null != pi.metaData ) {
            mainFileVersion = pi.metaData.getInt("mainVersion", appVersionCode);
            patchFileVersion = pi.metaData.getInt("patchVersion", appVersionCode);          
        } else {
            mainFileVersion = patchFileVersion = appVersionCode;
        }
        try {
            mAPKExtensionFile = APKExpansionSupport.getAPKExpansionZipFile(ctx, mainFileVersion, patchFileVersion);
            return true;
        } catch (IOException e) {
            e.printStackTrace();                
        }
    }
    return false;       
}



@Override
public AssetFileDescriptor openAssetFile(Uri uri, String mode)
        throws FileNotFoundException {
    initIfNecessary();
    String path = uri.getEncodedPath();
    if ( path.startsWith("/") ) {
        path = path.substring(1);
    }
    return mAPKExtensionFile.getAssetFileDescriptor(path);      
}

我不確定上面的這一行代碼: ProviderInfo pi = pm.resolveContentProvider(getAuthority(), PackageManager.GET_META_DATA); 這個對嗎?

來自 Android 對 PackageManager.resolveContentProvider() 的參考。

公共抽象 ProviderInfo resolveContentProvider(字符串名稱,int 標志)

自:API 級別 1 通過其基本路徑名查找單個內容提供者。 參數

name:要查找的提供程序的名稱。

標志:附加選項標志。 當前應始終為 0。

有人可以確認我做錯了什么還是錯誤。

編輯:當我第一次上傳我的應用程序時,一切都按預期工作 - 只有當我更新導致不同版本代碼的 apk 時才會出現此問題。

Zip 文件提供程序 class 包含您可以在 AndroidManifest.zip 文件中放置的元數據,如果 APK 擴展文件的版本號與您的 APK 版本號不匹配。

<provider android:name=".APEZProvider"
              android:authorities="my.application.authority"
              android:exported="false"
              android:multiprocess="true"
    >
   <meta-data android:name="mainVersion"
              android:value="1"></meta-data>
   <meta-data android:name="patchVersion"
              android:value="2"></meta-data>
</provider>

您必須創建自己的提供者並在清單中聲明它

 <provider android:authorities="com.myCompany.myAppName.provider.ZipFileContentProvider" android:name=".ZipFileContentProvider"></provider>

取自:

SampleZipfileProvider class 在哪里?

正如您所說,擴展文件版本號可以與應用程序版本不同。 那么問題來了,我怎么知道擴展文件的版本號呢?

這是多個可能的答案之一:

來自APK 擴展文件指南

您可以通過多種方式確定擴展文件版本號。 一種簡單的方法是在下載開始時將版本保存在SharedPreferences文件中,方法是使用 APKExpansionPolicy 類的 getExpansionFileName(int index) 方法查詢擴展文件名。 當你想訪問擴展文件時,你可以通過讀取SharedPreferences文件來獲取版本代碼。

有關從共享存儲讀取的更多信息,請參閱數據存儲文檔。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM