Android 调用系统隐藏的类和方法 | 您所在的位置:网站首页 › 删除系统默认输入法 › Android 调用系统隐藏的类和方法 |
1.Android系统隐藏的类和方法 阅读Android源码时,会发现很多被@UnsupportedAppUsage注解的方法,这些方法不能被外部应用访问。 比如Android中的PackageParser类,这个类是在android.content.pm包下面: 可以看到这个类是隐藏的(@hide),不对外提供sdk的调用,所以不能直接去实例化。 这个类里面有一个parsePackageLite静态方法: 这个方法有@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(); } }
②声明系统的类,空实现,抛异常 在查看类的时候,经常可以看到下面的代码,这个是编译通过,在最终调用的时候,会去找最终的系统实现类。 于是就参照系统的写法来试试 要保证创建的类和系统的包名一样,里面需要引用的其他类也要声明,写上。 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(); } } 结果: 看到结果是正确的,可以获得信息。 |
CopyRight 2018-2019 实验室设备网 版权所有 |