Android 调用系统隐藏的类和方法

1.Android系统隐藏的类和方法

阅读Android源码时,会发现很多被@UnsupportedAppUsage注解的方法,这些方法不能被外部应用访问。

比如Android中的PackageParser类,这个类是在android.content.pm包下面:

Android 调用系统隐藏的类和方法_第1张图片

可以看到这个类是隐藏的(@hide),不对外提供sdk的调用,所以不能直接去实例化。

这个类里面有一个parsePackageLite静态方法:

Android 调用系统隐藏的类和方法_第2张图片

这个方法有@UnsupportedAppUsage注解,表示该方法不支持用户app去调用。

 

2.调用系统隐藏的类和方法

①通过反射

private void testReflect() {

    try {

        Class cls=Class.forName( "android.content.pm.PackageParser");

        Method[] methods=cls.getMethods();

        for (int i = 0; i < methods.length; i++) {

            Log.i("RR",methods[i].getName());

        }

    } catch (ClassNotFoundException e) {

        e.printStackTrace();

    }

}

Android 调用系统隐藏的类和方法_第3张图片通过log可以看到,是可以获得到这个方法的。

②声明系统的类,空实现,抛异常

在查看类的时候,经常可以看到下面的代码,这个是编译通过,在最终调用的时候,会去找最终的系统实现类。

Android 调用系统隐藏的类和方法_第4张图片

于是就参照系统的写法来试试

Android 调用系统隐藏的类和方法_第5张图片

要保证创建的类和系统的包名一样,里面需要引用的其他类也要声明,写上。

PackageParser.java:

package android.content.pm;

import java.io.File;

import java.security.cert.Certificate;

import java.util.List;

public class PackageParser {

    public static PackageLite parsePackageLite(File packageFile, int flags) throws PackageParserException {

        throw new RuntimeException("Stub!");

    }

    public static class PackageLite {

        public final String packageName;

       ……所有属性直接拷过来

        public PackageLite(String codePath, ApkLite baseApk, String[] splitNames, String[] splitCodePaths, int[] splitRevisionCodes) {

            this.packageName = baseApk.packageName;

           ……所有属性赋值直接拷过来

        }

        public List getAllCodePaths() {

          throw new RuntimeException("Stub!");

        }

    }

    public static class ApkLite {

        public final String codePath;

       ……所有属性拷过来

        public ApkLite(String codePath, String packageName, String splitName, int versionCode, int revisionCode, int installLocation, List verifiers, Signature[] signatures, Certificate[][] certificates, boolean coreApp, boolean multiArch, boolean use32bitAbi, boolean extractNativeLibs) {

         throw new RuntimeException("Stub!");

        }

    }

    public static class PackageParserException extends Exception {

        public final int error;

        public PackageParserException(int error, String detailMessage) {

            super(detailMessage);

         throw new RuntimeException("Stub!");

        }

        public PackageParserException(int error, String detailMessage, Throwable throwable) {

            super(detailMessage, throwable);

         throw new RuntimeException("Stub!");

        }

    }

}

可以看到,实现的部分都用throw new RuntimeException(“Stub!”); 这个代替了。

注意:属性要全部写上(有UnsupportedAppUsage注解的,把注解删掉),可以把源码拷贝过来,然后把实现替代为throw new RuntimeException(“Stub!”);

VerifierInfo.java:

package android.content.pm;

import android.os.Parcel;

import android.os.Parcelable;

import java.security.PublicKey;

public class VerifierInfo implements Parcelable {

    public final String packageName;

    public final PublicKey publicKey;

    public VerifierInfo(String packageName, PublicKey publicKey) {

        throw new RuntimeException("Stub!");

    }

    private VerifierInfo(Parcel source) {

        throw new RuntimeException("Stub!");

    }

    @Override

    public int describeContents() {

        throw new RuntimeException("Stub!");

    }

    @Override

    public void writeToParcel(Parcel dest, int flags) {

        throw new RuntimeException("Stub!");

    }

    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {

        public VerifierInfo createFromParcel( Parcel source) {

         throw new RuntimeException("Stub!");

        }

        public VerifierInfo[] newArray(int size) {

         throw new RuntimeException("Stub!");

        }

    };

}

接下来就可以在app中调用该隐藏方法了:

private void testRuntimeExp() {

    File file=new File( Environment.getExternalStorageDirectory().getPath()+"/mm/app-debug.apk");

    if (!file.exists()) {

        Toast.makeText(this, "file is not exist", Toast.LENGTH_SHORT).show();

        return;

    }

    try {

       PackageParser.PackageLite packageLite= PackageParser.parsePackageLite(file,0);

       Log.i("RR","packageName:" + packageLite.packageName);

       Log.i("RR","versionCode:" + packageLite.versionCode);

       Log.i("RR","installLocation:" + packageLite.installLocation);

       Log.i("RR","codePath:" + packageLite.codePath);

       Log.i("RR","baseCodePath:" + packageLite.baseCodePath);

       Log.i("RR","coreApp:" + packageLite.coreApp);

        String s="";

    } catch (PackageParser.PackageParserExc eption e) {

        e.printStackTrace();

    }

}

结果:

Android 调用系统隐藏的类和方法_第6张图片

看到结果是正确的,可以获得信息。

你可能感兴趣的:(android)