天天看點

如何不通過反射來引用隐藏接口?

Internal接口和hide API

Android has two types of APIs that are not accessible via SDK.

1.  The first one is located in package com.android.internal.

2. The second API type is collection of classes and methods that are marked with @hide javadoc attribute.

The hidden methods can still be accessed via java reflection. The @hide attribute is just part of javadoc(droiddoc also), so the @hide just simply mean the method/class/field is excluded from the API docs.

For example, the checkUidPermission method in ActivityManager.java is @hide.

public static int checkUidPermission(String permission, int uid) {

    try {

        return AppGlobals.getPackageManager()

                .checkUidPermission(permission, uid);

    } catch (RemoteException e) {

        // Should never happen, but if it does... deny!

        Slog.e(TAG, "PackageManager is dead?!?", e);

    }

    return PackageManager.PERMISSION_DENIED;

}

http://www.cnblogs.com/xirihanlin/archive/2011/06/05/2073118.html

翻譯一下上面的:

Android有兩種類型的API是不能經由SDK通路的。

第一種是位于com.android.internal包中的API。我将稱之為internal API。第二種API類型是一系列被标記為@hide屬性的類和方法。第一種是不允許調用的,第二種是暫時設定為私有,但是未來可能調用的。

當你使用Android SDK進行開發的時候,你引用了一個非常重要的jar檔案——android.jar。它位于Android SDK平台的檔案夾中(SDK_DIR/platforms/platform-X/android.jar,其中,X表示API等級)。這個android.jar移掉了com.android.internal包中所有的類,也移掉了所有标記有@hide的類,枚舉,字段和方法。

一般對Hide接口的通路可以通過反射:,比如:

Class c;

c = Class.forName("android.app.ActivityManager");

Method m = c.getMethod("checkUidPermission", new Class[] {String.class, int.class}); Object o = m.invoke(null, new Object[]{"android.permission.READ_CONTACTS", 10010});

但也可以不使用反射,那就是把hide接口暴露出來,這需要使用framework.jar ,簡單來說,它和android.jar等同,但未移掉internal API和hidden API。

但是當我們去手機裡adb shell去擷取framework.jar時,發現它的大小是1k!why?因為L版本引入了Odex優化,

From Lollipop, due to ART, the framework files are in /system/framework/arm/boot.oat file.

Use 'java -jar oat2dex.jar boot boot.oat' and you will get a dex folder containing framework.dex and framework-classes2.dex.

那如何拿到framework.jar呢?

先記錄一下,https://github.com/liudongmiao/ForceStopGB/blob/master/aosp/readme-5.0-z... 裡的方法似乎是能用的,

但目前還沒有達到我原設的需求

1. 下載下傳 smali 和 baksmali,https://bitbucket.org/JesusFreke/smali/downloads 這個裡面的應該都能在 Java7 上運作。。。至少系統上為了編譯 framework 是安裝的 Java 7

2. 下載下傳 oat2dex,從 https://github.com/testwhat/SmaliEx/releases 下載下傳一個 oat2dex_java7.jar

3. 從 arm 目錄裡拿到 boot.oat 和 services.odex

4. 執行 java -jar oat2dex.jar boot boot.oat; 這會在 boot.oat 所在目錄下生成 dex odex 兩個子目錄

5. 執行 java -jar oat2dex.jar services.odex dex/ ; 生成 services.dex

6. 按照教程處理 services.odex 即可:java -jar baksmali.jar -a 22 -b -s services.dex -o services; ...; java -jar smali.jar -a 22 -j 1 -o classes.dex services; 7. 最後生成 services.jar:jar -cvf services.jar classes.dex; 覆寫,應該能重新開機成功