android-studio - Android 反射取得方法 ClassNotFoundException
PHP中文网
PHP中文网 2017-05-16 13:24:23
0
2
1199

我是想取得Bundle中持有的mMap集合.
bundle類別中,有getMap()方法可以取得,但是被標記為hide,所以我用反射去取.

        ArrayMap<String, Object> metaMap= null;
        try {
            Class ownerClass = Class.forName(Bundle.class.getName());
            Class superclass = ownerClass.getSuperclass();
            Method[] declaredMethods = superclass.getDeclaredMethods();
//            getMapMethod.setAccessible(true);
//            metaMap= (ArrayMap<String, Object>) getMapMethod.invoke(metaData);
            Log.e("test","superclass: "+superclass.getName());
            declaredMethods.toString();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

這是我測試的程式碼,之前是直接調方法,然後拋異常了.於是我就列印了所有的方法:

0 = {Method@4216} "public void android.os.BaseBundle.clear()"
1 = {Method@4217} "public boolean android.os.BaseBundle.containsKey(java.lang.String)"
2 = {Method@4218} "public java.lang.Object android.os.BaseBundle.get(java.lang.String)"
3 = {Method@4219} "public boolean android.os.BaseBundle.getBoolean(java.lang.String)"
4 = {Method@4220} "public boolean android.os.BaseBundle.getBoolean(java.lang.String,boolean)"
5 = {Method@4221} "public [Z android.os.BaseBundle.getBooleanArray(java.lang.String)"
6 = {Method@4222} "byte android.os.BaseBundle.getByte(java.lang.String)"
7 = {Method@4223} "java.lang.Byte android.os.BaseBundle.getByte(java.lang.String,byte)"
8 = {Method@4224} "[B android.os.BaseBundle.getByteArray(java.lang.String)"
9 = {Method@4225} "char android.os.BaseBundle.getChar(java.lang.String)"
10 = {Method@4226} "char android.os.BaseBundle.getChar(java.lang.String,char)"
11 = {Method@4227} "[C android.os.BaseBundle.getCharArray(java.lang.String)"
12 = {Method@4228} "java.lang.CharSequence android.os.BaseBundle.getCharSequence(java.lang.String)"
13 = {Method@4229} "java.lang.CharSequence android.os.BaseBundle.getCharSequence(java.lang.String,java.lang.CharSequence)"
14 = {Method@4230} "[Ljava.lang.CharSequence; android.os.BaseBundle.getCharSequenceArray(java.lang.String)"
15 = {Method@4231} "java.util.ArrayList android.os.BaseBundle.getCharSequenceArrayList(java.lang.String)"
16 = {Method@4232} "java.lang.ClassLoader android.os.BaseBundle.getClassLoader()"
17 = {Method@4233} "public double android.os.BaseBundle.getDouble(java.lang.String)"
18 = {Method@4234} "public double android.os.BaseBundle.getDouble(java.lang.String,double)"
19 = {Method@4235} "public [D android.os.BaseBundle.getDoubleArray(java.lang.String)"
20 = {Method@4236} "float android.os.BaseBundle.getFloat(java.lang.String)"
21 = {Method@4237} "float android.os.BaseBundle.getFloat(java.lang.String,float)"
22 = {Method@4238} "[F android.os.BaseBundle.getFloatArray(java.lang.String)"
23 = {Method@4239} "public int android.os.BaseBundle.getInt(java.lang.String)"
24 = {Method@4240} "public int android.os.BaseBundle.getInt(java.lang.String,int)"
25 = {Method@4241} "public [I android.os.BaseBundle.getIntArray(java.lang.String)"
26 = {Method@4242} "java.util.ArrayList android.os.BaseBundle.getIntegerArrayList(java.lang.String)"
27 = {Method@4243} "public long android.os.BaseBundle.getLong(java.lang.String)"
28 = {Method@4244} "public long android.os.BaseBundle.getLong(java.lang.String,long)"
29 = {Method@4245} "public [J android.os.BaseBundle.getLongArray(java.lang.String)"
30 = {Method@4246} "public java.lang.String android.os.BaseBundle.getPairValue()"
31 = {Method@4247} "java.io.Serializable android.os.BaseBundle.getSerializable(java.lang.String)"
32 = {Method@4248} "short android.os.BaseBundle.getShort(java.lang.String)"
33 = {Method@4249} "short android.os.BaseBundle.getShort(java.lang.String,short)"
34 = {Method@4250} "[S android.os.BaseBundle.getShortArray(java.lang.String)"
35 = {Method@4251} "public java.lang.String android.os.BaseBundle.getString(java.lang.String)"
36 = {Method@4252} "public java.lang.String android.os.BaseBundle.getString(java.lang.String,java.lang.String)"
37 = {Method@4253} "public [Ljava.lang.String; android.os.BaseBundle.getStringArray(java.lang.String)"
38 = {Method@4254} "java.util.ArrayList android.os.BaseBundle.getStringArrayList(java.lang.String)"
39 = {Method@4255} "public boolean android.os.BaseBundle.isEmpty()"
40 = {Method@4256} "public boolean android.os.BaseBundle.isParcelled()"
41 = {Method@4257} "public java.util.Set android.os.BaseBundle.keySet()"
42 = {Method@4258} "public void android.os.BaseBundle.putAll(android.os.PersistableBundle)"
43 = {Method@4259} "void android.os.BaseBundle.putAll(android.util.ArrayMap)"
44 = {Method@4260} "public void android.os.BaseBundle.putBoolean(java.lang.String,boolean)"
45 = {Method@4261} "public void android.os.BaseBundle.putBooleanArray(java.lang.String,boolean[])"
46 = {Method@4262} "void android.os.BaseBundle.putByte(java.lang.String,byte)"
47 = {Method@4263} "void android.os.BaseBundle.putByteArray(java.lang.String,byte[])"
48 = {Method@4264} "void android.os.BaseBundle.putChar(java.lang.String,char)"
49 = {Method@4265} "void android.os.BaseBundle.putCharArray(java.lang.String,char[])"
50 = {Method@4266} "void android.os.BaseBundle.putCharSequence(java.lang.String,java.lang.CharSequence)"
51 = {Method@4267} "void android.os.BaseBundle.putCharSequenceArray(java.lang.String,java.lang.CharSequence[])"
52 = {Method@4268} "void android.os.BaseBundle.putCharSequenceArrayList(java.lang.String,java.util.ArrayList)"
53 = {Method@4269} "public void android.os.BaseBundle.putDouble(java.lang.String,double)"
54 = {Method@4270} "public void android.os.BaseBundle.putDoubleArray(java.lang.String,double[])"
55 = {Method@4271} "void android.os.BaseBundle.putFloat(java.lang.String,float)"
56 = {Method@4272} "void android.os.BaseBundle.putFloatArray(java.lang.String,float[])"
57 = {Method@4273} "public void android.os.BaseBundle.putInt(java.lang.String,int)"
58 = {Method@4274} "public void android.os.BaseBundle.putIntArray(java.lang.String,int[])"
59 = {Method@4275} "void android.os.BaseBundle.putIntegerArrayList(java.lang.String,java.util.ArrayList)"
60 = {Method@4276} "public void android.os.BaseBundle.putLong(java.lang.String,long)"
61 = {Method@4277} "public void android.os.BaseBundle.putLongArray(java.lang.String,long[])"
62 = {Method@4278} "void android.os.BaseBundle.putSerializable(java.lang.String,java.io.Serializable)"
63 = {Method@4279} "void android.os.BaseBundle.putShort(java.lang.String,short)"
64 = {Method@4280} "void android.os.BaseBundle.putShortArray(java.lang.String,short[])"
65 = {Method@4281} "public void android.os.BaseBundle.putString(java.lang.String,java.lang.String)"
66 = {Method@4282} "public void android.os.BaseBundle.putStringArray(java.lang.String,java.lang.String[])"
67 = {Method@4283} "void android.os.BaseBundle.putStringArrayList(java.lang.String,java.util.ArrayList)"
68 = {Method@4284} "void android.os.BaseBundle.readFromParcelInner(android.os.Parcel)"
69 = {Method@4285} "public void android.os.BaseBundle.remove(java.lang.String)"
70 = {Method@4286} "void android.os.BaseBundle.setClassLoader(java.lang.ClassLoader)"
71 = {Method@4287} "public int android.os.BaseBundle.size()"
72 = {Method@4288} "void android.os.BaseBundle.typeWarning(java.lang.String,java.lang.Object,java.lang.String,java.lang.ClassCastException)"
73 = {Method@4289} "void android.os.BaseBundle.typeWarning(java.lang.String,java.lang.Object,java.lang.String,java.lang.Object,java.lang.ClassCastException)"
74 = {Method@4290} "synchronized void android.os.BaseBundle.unparcel()"
75 = {Method@4291} "void android.os.BaseBundle.writeToParcelInner(android.os.Parcel,int)"
76 = {Method@4292} "private void android.os.BaseBundle.readFromParcelInner(android.os.Parcel,int)"

我在原始碼中看到的方法如下:(只複製了方法名稱.)

BaseBundle
BaseBundle
BaseBundle
BaseBundle
BaseBundle
BaseBundle
BaseBundle
clear
containsKey
get
getBoolean
getBoolean
getBooleanArray
getByte
getByte
getByteArray
getChar
getChar
getCharArray
getCharSequence
getCharSequence
getCharSequenceArray
getCharSequenceArrayList
getClassLoader
getDouble
getDouble
getDoubleArray
getFloat
getFloat
getFloatArray
getInt
getInt
getIntArray
getIntegerArrayList
getLong
getLong
getLongArray
getMap
getPairValue
getSerializable
getShort
getShort
getShortArray
getString
getString
getStringArray
getStringArrayList
isEmpty
isEmptyParcel
isParcelled
keySet
putAll
putAll
putBoolean
putBooleanArray
putByte
putByteArray
putChar
putCharArray
putCharSequence
putCharSequenceArray
putCharSequenceArrayList
putDouble
putDoubleArray
putFloat
putFloatArray
putInt
putIntArray
putIntegerArrayList
putLong
putLongArray
putSerializable
putShort
putShortArray
putString
putStringArray
putStringArrayList
readFromParcelInner
readFromParcelInner
remove
setClassLoader
setShouldDefuse
size
typeWarning
typeWarning
unparcel
writeToParcelInner

其中,isParcelled(),getPairValue()也是被標記為hide,但是卻能取得到.想問是為什麼?

我猜是sdk版本原因,我的手機是sdk = 23,我編譯的版本為25,我猜測那幾個沒獲取到的方法是23之後添加的,不知有沒有什麼可以查看sdk版本差異測方法,或者是其他的原因.

PHP中文网
PHP中文网

认证高级PHP讲师

全部回覆(2)
巴扎黑

我對比了下Api23和Api25兩個的Bundle源碼,沒有關於getMap的明顯信息,
然後又對比了下Api16和Api25兩個的Bundle源碼,發現端倪,如下圖黃色塊標註:



🎜🎜🎜🎜🎜🎜🎜🎜🎜🎜我們可以看到Api25上,Bundle extends BaseBundle,而Api16卻沒有,兩邊所採用的資料結構也發生了變化。 🎜 🎜我們看下🎜Api25🎜上的BaseBundle,確實有getMap :🎜
/** @hide */
ArrayMap<String, Object> getMap() {
    unparcel();
    return mMap;
}
🎜然後我們在看下在Api23的BaseBundle裡面搜getMap,結果如下:🎜🎜🎜🎜🎜很明顯,🎜在Api23上,無論是Bundle,還是它的父類BaseBundle,都是不存在getMap方法的,所以反射也調不到。 🎜🎜
为情所困

@hide 屬於一個javadoc的標籤, Bundle源碼在編譯成jar包的時候會把@hide標記過的方法排除掉, 生成的jar包是給開發者使用的, 所以在IDE中我們是沒辦法直接通過bundle物件的引用去直接呼叫到bundle類別hide起來的方法的, 這個跟sdk編譯的版本是沒差別的。
等到後期你熟悉了android的整體後, 可以自己嘗試著編譯一下android源碼生成自己的android.jar包, 打個比方說, 這邊做camera開發比較多, 而camera不少方法都被hide了我們又不想每次都透過反射去調用hide方法, 於是乎, 我們自己編譯了一套完整的android.jar包, 在camera中被hide的方法就可以在ide中直接調用到了。

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板