通过反射来获取Intent中的Key

在项目中遇到一种情况,我想通过了解某个Intent里面到底存了哪些数据来解决这个问题。但是我们知道,Intent里面的数据需要知道key才能调用相应的函数取出来,所以如何才能找出这些key呢?

通过对Intent代码里面对存数据的观察,我们可以看到,通过putExtra()存的数据,都放在一个叫做mExtrasBundle中。而Bundle继承自BaseBundle,并且其中申明了一个变量叫做ArrayMap<String, Object> mMap = null;

1
2
3
4
5
6
7
8
9
10
11
12
13
// Intent.java
public @NonNull Intent putExtra(String name, String value) {
if (mExtras == null) {
mExtras = new Bundle();
}
mExtras.putString(name, value);
return this;
}
// BaseBundle.java
public void putString(@Nullable String key, @Nullable String value) {
unparcel();
mMap.put(key, value);
}

也不难理解它将数据以Object的方式存放在一个Map中,然后通过相应的get,将Object强转成相应的数据类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Intent.java
public String getStringExtra(String name) {
return mExtras == null ? null : mExtras.getString(name);
}

// BaseBundle.java
public String getString(@Nullable String key) {
unparcel();
final Object o = mMap.get(key);
try {
return (String) o;//强转成String
} catch (ClassCastException e) {
typeWarning(key, o, "String", e);
return null;
}
}

所以我们只需要获取到这个mMap,就可以获取到所有的key和数据。如何才能获取到它呢?Intent以及Bundle中都没有相应的获取方法,然后在BaseBundle中,mMap的申明和获取都是默认包访问权限。所以通过常规方法是无法获取到的。

1
2
3
4
5
6
7
8
9
// BaseBundle.java

ArrayMap<String, Object> mMap = null;//默认包访问权限

/** @hide */
ArrayMap<String, Object> getMap() {//默认包访问权限
unparcel();
return mMap;
}

听说反射可以做一些比较牛逼的事情,包括可以调用被@hide修饰的方法以及所有的方法、变量。在这里我们可以通过调用上面的那个get方法,也可以直接获取它的变量。在这里,我通过反射,来获取这个get方法,然后执行相应Bundle的该方法,成功获取到了mMap,并打印出其中的key

这个代码运行在一个普通的Android应用中,没有需要其他的权限。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void showBundleContent(){
try {
Class<BaseBundle> c = BaseBundle.class;
Method method = c.getDeclaredMethod("getMap");
method.setAccessible(true);
Object obj = method.invoke(getIntent().getExtras());
obj = (ArrayMap<String, Object>) obj;
Iterator it = ((ArrayMap<String, Object>) obj).keySet().iterator();
while (it.hasNext()){
Log.e("TAG", "set : "+(String)it.next());
}
} catch (Exception e) {
e.printStackTrace();
}
}

通过反射来获取Intent中的Key

https://eucham.me/2018/03/27/4a74bf2e6eac.html

作者

遇寻

发布于

2018-03-27

更新于

2022-04-21

许可协议

评论