Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/184.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如果扩展文件版本与APK版本代码不同,则使用URI(使用Google Zip扩展库)访问APK扩展文件会导致崩溃_Android - Fatal编程技术网

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

Android 如果扩展文件版本与APK版本代码不同,则使用URI(使用Google Zip扩展库)访问APK扩展文件会导致崩溃,android,Android,我的apk版本代码是版本3。我使用的是主扩展文件,该文件加载了apk版本代码1(文件名类似于main.1.ex.etc.eg.obb)。扩展文件可以在设备上正常下载 扩展文件有媒体文件,因此我使用Google Zip扩展库中的APEZProvider来播放VideoView 调用VideoView.start()会导致空指针异常 到目前为止,我发现: 在APEZProvider.initifrequired()中,将主扩展文件版本返回为3,而不是1。因此,尝试打开ZipResourceFile(

我的apk版本代码是版本3。我使用的是主扩展文件,该文件加载了apk版本代码1(文件名类似于main.1.ex.etc.eg.obb)。扩展文件可以在设备上正常下载

扩展文件有媒体文件,因此我使用Google Zip扩展库中的
APEZProvider
来播放
VideoView

调用
VideoView.start()
会导致空指针异常

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

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参考

公共抽象ProviderInfo resolveContentProvider(字符串名称,int标志)

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

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

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

有人能确认我是否做错了什么,或者是一个bug吗


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

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

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

摘自:


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

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

从:

有许多方法可以确定扩展文件的版本 号码。一种简单的方法是将版本保存在 文件下载开始时,通过查询扩展文件名 使用ApkeExpansionPolicy类的getExpansionFileName(int索引) 方法。然后,您可以通过读取 当您想要访问扩展文件时

有关读取共享存储的更多信息,请参阅 文件


Zip文件提供程序类包含元数据,如果APK扩展文件的版本号与APK的版本号不匹配,则可以将元数据放置在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>


我的问题与链接的问题不同。提供程序已声明。只要apk版本代码和扩展文件版本相同,视频就可以与VideoView.setVideoURI()配合使用。如果apk版本代码与扩展文件版本不同,则不起作用。因为它不应该。您的版本代码需要与扩展文件名匹配。如果上载更新的apk,则可以使用与早期apk一起上载的扩展文件。在本例中,文件扩展版本与apk版本代码不同,除了通过URI访问视频之外,其他一切都正常工作。在我看来,这更像是APEZProvider的问题。从我阅读的文档来看,他们希望文件名与版本代码匹配。因此,每当我更新我的应用程序时,我都会使用一个新的补丁文件进行更新。在你的第一条评论中,你说setVideoUri有效,但在下一条评论中,你说它无效:-/来自文档:“在Google Play上使用扩展文件的最大好处之一是能够更新你的应用程序,而无需重新下载所有原始资产。”然后“现有用户只收到更新的APK和新的补丁扩展文件(保留以前的主扩展文件)。”主文件版本将保持不变。正如我所说的,即使使用不同的版本,一切都会正常工作,除了上面代码中提到的videoURI失败。(setVideoURI仅在应用程序和扩展文件的版本相同时才起作用)起作用!谢谢。这不是应该有更清晰的文档记录吗?或者我错过了一些明显的内容吗?同样适用于pm.resolveContentProvider(),文档中说标志应该为零,但在APEZProvider类中不是这样。对此有任何说明吗?@user1318455我在清单中设置提供程序时出错:java.lang.RuntimeException:无法获取提供程序com.dabbel.zipfile.APEZProvider:java.lang.InstanceException:java.lang.Class无法实例化