2012-04-07 50 views
2

我的apk版本代碼是版本3.使用它我使用的主擴展文件已加載apk版本代碼1(文件名與main.1.ex.etc.eg.obb類似)。擴展文件在設備上正常下載。如果擴展文件版本與apk版本代碼不同,訪問帶有URI的APK擴展文件會導致崩潰

擴展文件包含媒體文件,因此我使用Google Zip擴展庫中的APEZProviderVideoView一起播放。

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

我迄今發現: 在APEZProvider.initIfNecessary()返回主擴展文件版本3,而不是1。因此試圖打開ZipResourceFile(mAPKExtensionFile)返回null。 APEZProvider.openAssetFile()導致NullPointerExceptionmAPKExtensionFilenull

APEZProvider類在谷歌郵編擴展庫

相關代碼:

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);這是正確的嗎?

從PackageManager.resolveContentProvider()的Android參考。

公共抽象ProviderInfo resolveContentProvider(字符串名稱,INT標誌)

自:API等級1 查找其基本路徑名的單個內容提供商。 參數

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

flags:其他選項標誌。目前應該始終爲0.

有人可以確認如果我做錯了什麼或它是一個錯誤。

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

回答

13

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

<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> 
+0

作品!謝謝。這不應該更清楚地記錄或我錯過了明顯的東西?同樣對於pm.resolveContentProvider(),文檔說標誌應該是零,但是在APEZProvider類中不是這樣。對此有何澄清? – user1318455 2012-06-10 11:30:31

2

你必須創建自己的供應商,並在您的清單

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

聲明它來自

Where is the SampleZipfileProvider class?

+0

我的問題與鏈接的不一樣。提供者已經被聲明。只要apk版本代碼和擴展文件版本相同,視​​頻就可以與VideoView.setVideoURI()一起正常工作。如果apk版本代碼與擴展文件版本不同,則不起作用。 – user1318455 2012-04-22 19:04:06

+0

因爲它不應該。您的版本代碼需要與擴展文件名稱匹配。 – Blundell 2012-04-22 19:20:02

+0

如果您上傳更新的apk,則可以使用上一個apk上傳的擴展文件。在這種情況下,文件擴展版本與apk版本代碼不同 - 除了通過URI訪問視頻外,其他所有功能都可以使用。對我來說,它看起來更像是一個APEZProvider問題。 – user1318455 2012-04-22 19:27:08

0

正如你說的,擴展文件的版本號可以是不同的應用程序版本。所以問題是,我怎麼知道擴展文件的版本號?

這裏的多種可能的答案之一:

APK Expansion Files guide

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

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