如果扩展文件版本与apk版本代码不同,则使用URI(使用Google Zip扩展库)访问APK扩展文件会导致崩溃

时间:2012-04-07 02:23:41

标签: android

我的apk版本代码是版本3.使用它我使用的主扩展文件加载了apk版本代码1(文件名类似于main.1.ex.etc.eg.obb)。扩展文件在设备上下载得很好。

扩展文件包含媒体文件,因此我使用Google Zip扩展库中的APEZProviderVideoView一起播放。

调用VideoView.start()会导致Nullpointer异常。

到目前为止我发现了什么: 在APEZProvider.initIfNecessary()中,将主扩展文件版本返回为3而不是1.因此,尝试打开ZipResourceFile(mAPKExtensionFile)将返回null。 APEZProvider.openAssetFile()导致NullPointerException mAPKExtensionFilenull

Google Zip扩展库中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参考。

public abstract ProviderInfo resolveContentProvider(String name,int flags)

自:API级别1 按基本路径名查找单个内容提供程序。  参数

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

flags:附加选项标志。目前应始终为0。

有人可以确认我是做错了还是错误。

编辑:当我第一次上传我的应用程序时,一切都按预期工作 - 仅当我更新apk时导致出现此问题的不同版本代码。

3 个答案:

答案 0 :(得分:14)

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

答案 1 :(得分:2)

您必须创建自己的提供者并在清单中声明它

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

取自:

Where is the SampleZipfileProvider class?

答案 2 :(得分:0)

正如您所说,扩展文件版本号可以与应用版本不同。所以问题是,我如何知道扩展文件的版本号?

以下是多个可能的答案之一:

来自APK Expansion Files guide

  

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

     

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