您的位置:首页 > 移动开发 > Android开发

android 反射调用其他apk中的方法

2015-03-25 16:00 573 查看
最近在研究调用android原生界面进行拍照,尝试了很多方法均没有成功,刚开始想到了采用模拟按键的方式去实现,发现不可行,用Instrumentation 需要是system app,不能当做普通app,如果手机已被Root,采用Instrumentation 模拟KEYCODE_CAMERA按键的方式倒是可行的。在非Root设备上,是因为权限的问题而报错,想到采用JNI的方式,尝试发现还是不能绕开android系统的权限问题,也是不可行的,后面想到反射,尝试发现也是不可行的,因为有很多参数需要初始化,之前很少用到反射,现在记录下使用反射的过程。

1. 在使用反射的过程中,被第一个问题困扰,找不到com.android.camera这个包名,后面通过反编译发现这个包被打进了com.android.gallery3d这个包,也就是说,它把Camera和Gallery合成了一个apk,了解了这个问题以后就好办了。

2. 主要代码

Context mmsCtx = createPackageContext("com.android.gallery3d",
Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
Class<?> clazz = Class.forName("com.android.camera.manager.ShutterManager", true, mmsCtx.getClassLoader());
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
Constructor<?> constructor = null;
for (int i = 0; i < constructors.length; i++) {
constructor = constructors[i];
if (constructor.getGenericParameterTypes().length == 0)
break;
}
constructor.setAccessible(true);

Class<?> camera = Class.forName("com.android.camera.Camera", true, mmsCtx.getClassLoader());
Object cameraObject = camera.newInstance();

Object maObject = constructor.newInstance(cameraObject);
Method[] methods = clazz.getMethods();

Method[] methodss = clazz.getDeclaredMethods();
for(Method meth : methodss) {
Log.i(TAG,"name:" + meth.getName());
/*if(meth.getName().equals("getView")) {
meth.setAccessible(true);
meth.invoke(maObject);
}*/
}

for(Method meth : methods) {
//Log.i(TAG,"name:" + meth.getName());
if(meth.getName().equals("performPhotoShutter")) {
meth.setAccessible(true);
meth.invoke(maObject);
}
}


这里面主要要注意的地方就是:

1. 因为这个相机apk比较特殊,他不是在com.android.camera这个包里,首先要找到包名:createPackageContext(com.android.gallery3d), 然后在查找类的时候,就不需要

外面的这层包名,直接用它的包名和类名就可以了:com.android.camera.manager.ShutterManager,如果还是加上外面层的包名会出现找不到类的异常。

2. 实例化类,通过newInstance 可以实现,而且可以传递参数,如上面就是constructor.newInstance(cameraObject); 给 ShutterManager 传递了 Camera 这个参数

3. getDeclaredMethods() 和 getMethods() 获取到的函数数组还是不一样的。

最后通过log发现com.android.camera.manager.ShutterManager 里的 performPhotoShutter()确实被调用了,但是因为该方法里有数据没有初始化,所以还是不能拍照的。

反射机制确实很强大。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: