Accessing android:installLocation manifest attribu

2019-02-09 20:43发布

I'm trying to write an Android 2.2 app that will find installed apps that can be moved to the SD card. The permission to do this is encoded in the AndroidManifest.xml file as the root-level attribute "android:installLocation". PackageInfo seems to have an interface to everything but this attribute. I can open the installed apk and extract the AndroidManifest.xml file, but it seems to be in some binary encoding format, which some random internet people have written a decoder for, but that seems like an awful lot of work.

Is there an interface that I'm missing?

4条回答
别忘想泡老子
2楼-- · 2019-02-09 21:12

As it turns out, while there's no direct API call to get installLocation, neither do I have to parse the binary XML manually, as the provided XmlResourceParser works on it.

// Experimentally determined
private static final int auto = 0;
private static final int internalOnly = 1;
private static final int preferExternal = 2;

AssetManager am = createPackageContext(packageName, 0).getAssets();
XmlResourceParser xml = am.openXmlResourceParser("AndroidManifest.xml");
int eventType = xml.getEventType();
xmlloop:
while (eventType != XmlPullParser.END_DOCUMENT) {
    switch (eventType) {
        case XmlPullParser.START_TAG:
            if (! xml.getName().matches("manifest")) {
                break xmlloop;
            } else {
                attrloop:
                for (int j = 0; j < xml.getAttributeCount(); j++) {
                    if (xml.getAttributeName(j).matches("installLocation")) {
                        switch (Integer.parseInt(xml.getAttributeValue(j))) {
                            case auto:
                                // Do stuff
                                break;
                            case internalOnly:
                                // Do stuff
                                break;
                            case preferExternal:
                                // Do stuff
                                break;
                            default:
                                // Shouldn't happen
                                // Do stuff
                                break;
                        }
                        break attrloop;
                    }
                }
            }
            break;
        }
        eventType = xml.nextToken();
    }

Uh, I guess there's a switch in there with one case that should probably just be an if. Oh well. You get the point.

查看更多
乱世女痞
3楼-- · 2019-02-09 21:12

Considering all other direct attributes of the manifest tag are available from PackageInfo, I think you're right to look for it there.

I know it's not in the doc, but did you try anyway? Something like

PackageInfo pkg = ...;
String loc = pkg.installLocation();

I know this is probably very naive considering the doc may even be generated automatically - and I wouldn't dare suggest it if I could try it myself (stuck on API 7 at the moment due to retarded OS not supported anymore in 8)

If it doesn't work, I'm afraid they just overlooked that - I can't imagine they would put it elsewhere all of a sudden. In that case, you'll probably be stuck parsing the manifests by yourself indeed.

查看更多
聊天终结者
4楼-- · 2019-02-09 21:15

In the older API's from 2007, there was public fields in the PackageInfo class that gave all information on the internalLocation and other relevant information. For security reasons I am guessing they got rid of those convenient fields.

查看更多
Evening l夕情丶
5楼-- · 2019-02-09 21:23

You may access this attribute by next example:

PackageInfo packageInfo = context.getPackageManager().getPackageInfo(mPackageName, 0);
if (packageInfo.installLocation != PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
    .....
}

http://developer.android.com/reference/android/content/pm/PackageInfo.html#installLocation
was introduced in API 21

But this field exists even in Android 2.3 http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3_r1/android/content/pm/PackageInfo.java/

查看更多
登录 后发表回答