搜索

首页  >  问答  >  正文

android-studio - Android 反射获取方法 ClassNotFoundException

我是想获取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中文网2753 天前1176

全部回复(2)我来回复

  • 巴扎黑

    巴扎黑2017-05-16 13:26:23

    我对比了下 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方法的,所以反射也调不到。

    回复
    0
  • 为情所困

    为情所困2017-05-16 13:26:23

    @hide 属于一个javadoc的标签, Bundle源码在编译成jar包的时候会把@hide标记过的方法 排除掉, 生成的jar包是给开发者使用的, 所以在IDE中我们是没办法直接通过bundle对象的引用去直接调用到bundle类hide起来的方法的, 这个跟sdk编译的版本是没差别的。
    等到后期你熟悉了android的整体后, 可以自己尝试着编译一下android源码生成自己的android.jar包, 打个比方说, 这边做camera开发比较多, 而camera不少方法都被hide了 我们又不想每次都通过反射去调用hide方法, 于是乎, 我们自己编译了一套完整的android.jar包, 在camera中被hide的方法就可以在 ide中直接调用到了。

    回复
    0
  • 取消回复