如果扩展文件版本与apk版本代码不同,访问带有URI的APK扩展文件会导致崩溃

问题描述:

我的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导致发生此问题的不同版本代码时。

如果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

你必须创建自己的供应商,并在您的清单

<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

正如你说的,扩展文件的版本号可以是不同的应用程序版本。所以问题是,我怎么知道扩展文件的版本号?

这里的多种可能的答案之一:

APK Expansion Files guide

有很多,你可以决定扩展文件版本 号的方式。一种简单的方法是在下载开始时通过使用APKExpansionPolicy类的getExpansionFileName(int index) 方法查询扩展文件名 来将版本保存在SharedPreferences 文件中。当您想要访问扩展文件时,您可以通过读取 SharedPreferences文件来获取版本代码。

有关从共享存储中读取的更多信息,请参阅 Data Storage文档。