赞
踩
还是之前公司的那个需求,为满足客户需要,必须能够远程控制手下手机的相机和录音功能,之前能够使用设备管理器来禁用摄像头,但是毕竟需要手机使用者来手动点击确定激活的选项,这点就不是很美丽,虽然那个点击的操作可以使用自动化服务来实现,但是有点大题小做并且效果还是不理想,所以我使用的禁用android底层相机和录音的api,通过修改android底层代码实现 功能失效,而通过反编译手机自带的相机录音的apk虽然也能够实现失效的效果,但是毕竟这只是一个apk,人家在下载个其他的照相或录音的app,你还是拿人家没有办法,所有相关的应用都会使用Camera、AudioRecord或是MediaRecorder类实现的照相 和 录制语音的功能,让我们查询相关底层代码,修改部分代码就能够一举多得的让所有调用这三个类的所有app都失效啦~
话不多说直接上代码~ 关于xposed模块配置方面我就不介绍了...不会的同学可以看我的其他帖子或是去google一下,关于那三个类可以在AS上引出这三个包,然后ctri + 左键 点击进去查看源码,里面API介绍的很全面,对于是英文看不懂的同学可以再AS里面装一个自动翻译的插件,我可以推荐一个AS翻译的插件你们可以试试~无网络无法使用哦~网址如下所示点击就能进入(安装教程也讲解的很详细):
- private void hookCamera(XC_LoadPackage.LoadPackageParam loadPackageParam) {
- try {
- XposedHelpers.findAndHookMethod("android.hardware.Camera", loadPackageParam.classLoader, "open", new XC_MethodHook() {
- @Override
- protected void afterHookedMethod(MethodHookParam param) throws Throwable {
- super.afterHookedMethod(param);
- if (ModelHelper.getGZipModel("Audio.qwer.com","disable").equals("disable")){
- param.setResult(null);
- Log.e("pptppt", "试试吧");
- }
- }
- });
-
- XposedHelpers.findAndHookMethod("android.hardware.Camera", loadPackageParam.classLoader, "open",
- int.class, new XC_MethodHook() {
- @Override
- protected void afterHookedMethod(MethodHookParam param) throws Throwable {
- super.afterHookedMethod(param);
- if (ModelHelper.getGZipModel("Audio.qwer.com","disable").equals("disable")){
- param.setResult(null);
- Log.e("pptppt", "试试吧 啊哈哈");
- }
- }
- });
-
- } catch (Exception e) {
-
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
通过阅读Camera 的API 只要禁用掉open方法的返回值就能够实现无法开启摄像头操作,接下来是禁用语音录音功能:
- private void hookRecord(XC_LoadPackage.LoadPackageParam loadPackageParam) {
- try {
- Class<?> aClass = XposedHelpers.findClass("android.media.MediaRecorder", loadPackageParam.classLoader);
- XposedBridge.hookAllMethods(aClass, "setOutputFile", new XC_MethodHook() {
- @Override
- protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
- super.beforeHookedMethod(param);
- if (ModelHelper.getGZipModel("Audio.qwer.com","disable").equals("disable")){
- param.args[0] = null;
- Log.e("pptppt", "lalala1");
- }
- }
- });
- /*********************************************************************************/
- XposedHelpers.findAndHookMethod("android.media.AudioRecord", loadPackageParam.classLoader, "getState", new XC_MethodHook() {
- @Override
- protected void afterHookedMethod(MethodHookParam param) throws Throwable {
- super.afterHookedMethod(param);
- if (ModelHelper.getGZipModel("Audio.qwer.com","disable").equals("disable")){
- param.setResult(0);
- Log.e("pptppt", "getState");
- }
- }
- });
-
- }catch (Exception e){
-
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
不知道你们观察出来了没有,在修改参数或返回值的时候,我在外侧都会加一个if判断,读取一个压缩文件中的string字符串,不满足条件的时候在禁止,这样做是为了能够更灵活的实现禁用效果,当不需要禁用的时候就重新写入压缩文件中的内容就可以了~~ 如下是ModelHelper类的代码:
- import android.util.Log;
-
- import java.io.BufferedReader;
- import java.io.BufferedWriter;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.InputStreamReader;
- import java.io.OutputStreamWriter;
- import java.io.Reader;
- import java.util.zip.GZIPInputStream;
- import java.util.zip.GZIPOutputStream;
-
-
- public final class ModelHelper {
- public static final String DIR = "/sdcard/";
-
- /**
- * by kevin 07-03
- * 解压文件 获得string数据
- * @param modelName 文件名
- * @param value 取不到或解压出错时 用来替代的默认数据
- * @return 返回数据 成功为modelName文件的内容 失败为value默认内容
- */
- public static String getGZipModel(String modelName, String value) {
- try {
- File file = new File(DIR + modelName);
- if (!file.isFile() || !file.exists()) {
- return value;
- }
- byte [] buffer = new byte[10240];
- GZIPInputStream gis = new GZIPInputStream(new FileInputStream(file));
- int cnt = gis.read(buffer);
- gis.close();
- return new String(buffer, 0, cnt, "utf-8");
- } catch (Exception e) {
- e.printStackTrace();
- return value;
- }
- }
-
- /**
- * by kevin 07-03
- * set cloud.sv 设置数据内容
- * @param fileName 压缩文件名字
- * @param value 写入的内容
- */
- public static void setGZipModel(String fileName,String value){
- try {
- FileOutputStream fos = new FileOutputStream(DIR + fileName);
- GZIPOutputStream gos = new GZIPOutputStream(fos);
- gos.write(value.getBytes());
- gos.flush();
- gos.finish();
- }catch (Exception e){
- Log.e("qswx", "写入文件内容出错或不存在");
- }
- }
-
-
- /**
- * by kevin 06-20
- * 读文件的方法
- * @param modelName 文件名
- * @param value 没有这个文件或这不是文件的时候 返回的String类型信息
- * @return 返回的是文件中的数据信息 为String类型
- */
- public static String getModel(String modelName, String value) {
- try {
- File file = new File(DIR + modelName);
- if (!file.isFile() || !file.exists()) {
- return value;
- }
- Reader inputStreamReader = new InputStreamReader(new FileInputStream(file), "UTF-8");
- String str3 = new BufferedReader(inputStreamReader).readLine();
- inputStreamReader.close();
- return str3;
- } catch (Exception e) {
- e.printStackTrace();
- return value;
- }
- }
-
- /**
- * by kevin 06-20
- * 写入String字符串 写入到指定文件中
- * @param modelName 指定文件的文件名字
- * @param value 写入到文件的String字符串
- *
- * BufferedWriter 写入到缓存区
- * .flush()清空提交 不要忘记写
- */
- public static void setModel(String modelName, String value) {
- BufferedWriter bufferedWriter = null;
- try {
- bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(DIR + modelName), false), "UTF-8"));
- bufferedWriter.write(value);
- bufferedWriter.flush();
- bufferedWriter.close();
- } catch (Exception e3) {
- e3.printStackTrace();
- try {
- if(bufferedWriter != null) {
- bufferedWriter.close();
- }
- } catch (Exception e5) {
-
- }
- }
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。