Android calls the hidden classes and methods of the system

1. Android system hidden classes and methods

When reading the Android source code, you will find many methods annotated by @UnsupportedAppUsage, which cannot be accessed by external applications.

For example, the PackageParser class in Android, this class is under the android.content.pm package:

0d41f917553b4ea0a837b6e1cb012067.png

You can see that this class is hidden (@hide), and does not provide external calls to the sdk, so it cannot be instantiated directly.

There is a parsePackageLite static method in this class:

c70522b8cf094f05ba6f791955c9e2e6.png

This method is annotated with @UnsupportedAppUsage, indicating that the method does not support the user app to call.

 

2. Call the hidden classes and methods of the system

① by reflection

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();

    }

}

0993a440524a4d09a276a919e9f49905.pngIt can be seen from the log that this method can be obtained.

② Declare the class of the system, empty implementation, throw an exception

When looking at the class, you can often see the following code. This is compiled and passed. When it is finally called, it will find the final system implementation class.

cf5bc56f0de0432abb53999ac4e26678.png

So try to refer to the writing method of the system

c6523821ba18476baec4d7b23346b893.png

To ensure that the created class has the same package name as the system, other classes that need to be referenced in it must also be declared and written.

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;

       ...all attributes are directly copied over

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

            this.packageName = baseApk.packageName;

           ...all attribute assignments are directly copied over

        }

        public List<String> getAllCodePaths() {

          throw new RuntimeException("Stub!");

        }

    }

    public static class ApkLite {

        public final String codePath;

       ... all attributes are copied over

        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!");

        }

    }

}

As you can see, the implementation part is replaced by throw new RuntimeException("Stub!");

Note: All attributes should be written (if there is UnsupportedAppUsage annotation, delete the annotation), you can copy the source code, and then replace the implementation with 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<VerifierInfo> CREATOR = new Parcelable.Creator<VerifierInfo>() {

        public VerifierInfo createFromParcel( Parcel source) {

         throw new RuntimeException("Stub!");

        }

        public VerifierInfo[] newArray(int size) {

         throw new RuntimeException("Stub!");

        }

    };

}

Then you can call the hidden method in the 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();

    }

}

result:

9eb01c4a2e68489eaada4bf516c5953e.png

Seeing that the result is correct gives information.

Guess you like

Origin blog.csdn.net/zenmela2011/article/details/131010937