如何调用android 系统隐藏类和方法

如何调用android 系统隐藏类和方法

我们在做有些特殊功能的开发,公开的android-sdk里的api不能满足要求,就需要调用android系统中的隐藏类和里面的隐藏方法,今天我们就用Android中的PackageParser类 调用里面的parsePackageLite静态方法为例子来实现

我们先来看看这个类

这个类是在android.content.pm 这个包下面

image

我们看到这个类是隐藏的,不对外提供sdk的调用,所以我们直接去实例化是不行的

image

上面这个就是我们要调用的方法,这里还是android7.1.2的源码

我们看下android 10以上是什么样子的

image

我们发现android10(包括10)这个方法都有@UnsupportedAppUsage 注解,这个注解就是不支持用户app去调用了,经过我测试,有了这个注解,通过反射的反射是获取不到这个方法的,系统底层的虚拟器会读取这个注解,然后过滤调它,接下来我们测试下

1、反射
 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();
        }

    }

我在iqoo5 上测试测,是android11的版本

结果

						28991-28991/com.lihua.txtest I/RR: collectCertificates
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: equals
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: generateActivityInfo
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: generateApplicationInfo
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: generateApplicationInfo
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: generateInstrumentationInfo
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: generatePackageInfo
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: generatePackageInfo
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: generatePermissionGroupInfo
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: generatePermissionInfo
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: generateProviderInfo
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: generateServiceInfo
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: getClass
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: hashCode
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: notify
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: notifyAll
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: parseMonolithicPackage
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: parsePackage
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: parsePackage
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: parsePackageLite
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: setCompatibilityModeEnabled
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: setSeparateProcesses
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: toString
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: wait
2021-12-06 10:21:49.381 28991-28991/com.lihua.txtest I/RR: wait

我们看到这些方法中并没有我们要调用的那个方法,parsePackageLite

我们来看下android10一下,就用api28来测试下,开个模拟器

image

结果是可以获得到这个方法的,我们最终是可以调用的里面的这个方法

那么我们就没有办法在android10 上调用这个方法了吗?

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

image

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

那么我们就参照系统的写法来试试

image

我们创建的类需要和系统的报名一样,里面需要引用的其他类,也要声明,写上

PackageParser:

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 final int versionCode;
        public final int installLocation;
        public final VerifierInfo[] verifiers;

        /** Names of any split APKs, ordered by parsed splitName */
        public final String[] splitNames;

        /**
         * Path where this package was found on disk. For monolithic packages
         * this is path to single base APK file; for cluster packages this is
         * path to the cluster directory.
         */
        public final String codePath;

        /** Path of base APK */
        public final String baseCodePath;
        /** Paths of any split APKs, ordered by parsed splitName */
        public final String[] splitCodePaths;

        /** Revision code of base APK */
        public final int baseRevisionCode;
        /** Revision codes of any split APKs, ordered by parsed splitName */
        public final int[] splitRevisionCodes;

        public final boolean coreApp;
        public final boolean multiArch;
        public final boolean use32bitAbi;
        public final boolean extractNativeLibs;

        public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
                           String[] splitCodePaths, int[] splitRevisionCodes) {
            this.packageName = baseApk.packageName;
            this.versionCode = baseApk.versionCode;
            this.installLocation = baseApk.installLocation;
            this.verifiers = baseApk.verifiers;
            this.splitNames = splitNames;
            this.codePath = codePath;
            this.baseCodePath = baseApk.codePath;
            this.splitCodePaths = splitCodePaths;
            this.baseRevisionCode = baseApk.revisionCode;
            this.splitRevisionCodes = splitRevisionCodes;
            this.coreApp = baseApk.coreApp;
            this.multiArch = baseApk.multiArch;
            this.use32bitAbi = baseApk.use32bitAbi;
            this.extractNativeLibs = baseApk.extractNativeLibs;
        }

        public List<String> getAllCodePaths() {
            throw new RuntimeException("Stub!");
        }
    }












    public static class ApkLite {
        public final String codePath;
        public final String packageName;
        public final String splitName;
        public final int versionCode;
        public final int revisionCode;
        public final int installLocation;
        public final VerifierInfo[] verifiers;
        public final Signature[] signatures;
        public final Certificate[][] certificates;
        public final boolean coreApp;
        public final boolean multiArch;
        public final boolean use32bitAbi;
        public final boolean extractNativeLibs;

        public ApkLite(String codePath, String packageName, String splitName, int versionCode,
                       int revisionCode, int installLocation, List<VerifierInfo> 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!”); 这个代替

属性都要全部写上,我都是自己把源码拷贝过来,然后把实现都throw new RuntimeException(“Stub!”);

VerifierInfo:

package android.content.pm;

import android.os.Parcel;
import android.os.Parcelable;

import java.security.PublicKey;



    public class VerifierInfo implements Parcelable {
        /** Package name of the verifier. */
        public final String packageName;

        /** Signatures used to sign the package verifier's package. */
        public final PublicKey publicKey;

        /**
         * Creates an object that represents a verifier info object.
         *
         * @param packageName the package name in Java-style. Must not be {@code
         *            null} or empty.
         * @param publicKey the public key for the signer encoded in Base64. Must
         *            not be {@code null} or empty.
         * @throws IllegalArgumentException if either argument is null or empty.
         */
        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<VerifierInfo> CREATOR
                = new Parcelable.Creator<VerifierInfo>() {
            public VerifierInfo createFromParcel(Parcel source) {
                throw new RuntimeException("Stub!");
            }

            public VerifierInfo[] newArray(int size) {
                throw new RuntimeException("Stub!");
            }
        };
    }




接下来我们来调用下试试看Demo

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.PackageParserException e) {
        e.printStackTrace();
    }

}

结果:

image

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

VirtualApk 这个框架就大量运用了这种技术,想了解更多详情的同学可以到GitHub上看下

image

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值