使用 XmlResourceParser 解析 AndroidManifest.xml 未按预期工作

Posted

技术标签:

【中文标题】使用 XmlResourceParser 解析 AndroidManifest.xml 未按预期工作【英文标题】:Parsing AndroidManifest.xml with XmlResourceParser not working as expected 【发布时间】:2018-08-22 05:13:01 【问题描述】:

我需要解析androidManifest.xml 以检索一些通过PackageManager 无法获得的附加信息。

我有以下代码:

try

    AssetManager assetManager = createPackageContext(getPackageName(), 0).getAssets();
    XmlResourceParser xml = assetManager.openXmlResourceParser("AndroidManifest.xml");
    int eventType = xml.getEventType();

    while (eventType != XmlPullParser.END_DOCUMENT)
    
        if(eventType == XmlPullParser.START_DOCUMENT) 
            Log.d(TAG, "START_DOCUMENT");
         else if(eventType == XmlPullParser.START_TAG) 
            Log.d(TAG, "START_TAG: " + xml.getName());
         else if(eventType == XmlPullParser.END_TAG) 
            Log.d(TAG, "END_TAG: " + xml.getName());
         else if(eventType == XmlPullParser.TEXT) 
            Log.d(TAG, "TEXT: " + xml.getText());
        
        eventType = xml.next();
    

    xml.close();

catch ( XmlPullParserException
      | PackageManager.NameNotFoundException
      | IOException ignore)  

我希望从 XML 文件中获取所有标签,但我得到的只是:

START_DOCUMENT
START_DOCUMENT
START_TAG: manifest
END_TAG: manifest

...这不是我所期望的。


我不知道为什么START_DOCUMENT 会出现两次,但最困扰我的是我在<manifests> 标签内没有任何标签。

我的解析有问题还是这些标签根本不可用?

【问题讨论】:

【参考方案1】:

Mohammed 的代码适用于非即时运行构建。

使用 Instant Run,设备上的 APK 与将要部署到生产环境的实际 APK 只是模糊地相似。一些核心 APK 可能是您真正的 APK 中的内容,但您的应用程序的其余部分作为某种形式的附加组件被推送,Instant Run 环境可以将它们混合在一起以创建一些运行方式有点像您的应用程序的东西。这样做的好处是这些附加组件可以快速推出,因为它们更小并且不需要完整的设备安装。

缺点是 Instant Run 应用程序不是您的 APK,因此在 APK 中窥视的内容在 Instant Run 构建中的工作方式可能与在常规构建中不同。 p>

我很惊讶清单是 Instant Run 环境可以基于这些附加组件动态合成的东西。话虽如此,将清单作为资源读取肯定是“不寻常的”,因此在这方面,回想起来 Instant Run 破坏了这段代码并不令人震惊。

因此,如果您确实需要这种读取清单 XML 功能,则需要为您的 IDE 禁用 Instant Run。或者,找到一些不需要读取清单 XML 的其他解决方案(例如,将所需的“哪些运行时权限是可选的?”信息保存在 Java static 字段中)。

【讨论】:

【参考方案2】:

您需要调用 xml.next() 而不是 xml.getEventType(),因为您正在处理 FILEnext() 方法始终以 zero 的值作为如果文件为空,则文件的起点和结束于 one 的值。

我希望这会有所帮助。

// for the sake of dealing with a file
int eventType = xml.next();

完整代码:

final String TAG = "cccc";

try

    AssetManager assetManager = createPackageContext(getPackageName(), 0).getAssets();
    XmlResourceParser xml = assetManager.openXmlResourceParser("AndroidManifest.xml");
    int eventType = xml.next();

    while (eventType != XmlPullParser.END_DOCUMENT)
    
        if (eventType == XmlPullParser.START_DOCUMENT) 
            Log.d(TAG, "START_DOCUMENT");
         else if(eventType == XmlPullParser.START_TAG) 
            Log.d(TAG, "START_TAG: " + xml.getName());
         else if(eventType == XmlPullParser.END_TAG) 
            Log.d(TAG, "END_TAG: " + xml.getName());
         else if(eventType == XmlPullParser.TEXT) 
            Log.d(TAG, "TEXT: " + xml.getText());
        
        eventType = xml.next();
    

    xml.close();

catch ( XmlPullParserException
      | PackageManager.NameNotFoundException
      | IOException ignore)  

在实际设备上运行的结果

 D/cccc: START_TAG:START_DOCUMENT
 D/cccc: START_TAG: manifest
 D/cccc: START_TAG: uses-sdk
 D/cccc: END_TAG: uses-sdk
 D/cccc: START_TAG: uses-permission
 D/cccc: END_TAG: uses-permission
 D/cccc: START_TAG: uses-permission
 D/cccc: END_TAG: uses-permission
.
.
.
 D/cccc: END_TAG: application
 D/cccc: END_TAG: manifest

我在使用模拟器运行代码时遇到了同样的问题。

参考this great post 代码将按预期工作。

【讨论】:

以上是关于使用 XmlResourceParser 解析 AndroidManifest.xml 未按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

XmlResourceParser出错解决

方便使用Android XmlResourceParser?

XmlResourceParser出错解决

Attempt to invoke virtual method ‘android.content.res.XmlResourceParser android.content.pm.ProviderI

android - 如何创建 xml 的 id?

Android本地化xml文件