From 8fc438af47258a01c674e0f4f5c89d0e28484785 Mon Sep 17 00:00:00 2001 From: w2016561536 Date: Sat, 5 Feb 2022 17:30:05 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DChrome=E6=B5=8F=E8=A7=88?= =?UTF-8?q?=E5=99=A8=E7=AD=89=E5=BA=94=E7=94=A8=E7=A8=8B=E5=BA=8F=E7=9A=84?= =?UTF-8?q?Session=E9=85=8D=E7=BD=AE=E9=94=99=E8=AF=AF=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20=E4=BF=AE=E6=94=B9=E6=8E=A7=E5=88=B6=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E9=80=BB=E8=BE=91=20=E4=BF=AE=E6=94=B9README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix session configuration error of Chrome browser and other applications Modify control file logic Modify Readme --- README.md | 14 +- README_en.md | 15 +- README_tc.md | 16 +- app/build.gradle | 4 +- app/release/app-release.apk | Bin 70944 -> 73060 bytes app/release/output-metadata.json | 4 +- .../main/java/com/example/vcam/HookMain.java | 166 +++++++++++------- .../java/com/example/vcam/MainActivity.java | 60 ++++++- app/src/main/res/layout/activity_main.xml | 35 +++- app/src/main/res/values-en/strings.xml | 2 + app/src/main/res/values-zh-rCN/strings.xml | 2 + app/src/main/res/values-zh-rHK/strings.xml | 2 + app/src/main/res/values-zh-rMO/strings.xml | 2 + app/src/main/res/values-zh-rSG/strings.xml | 2 + app/src/main/res/values-zh-rTW/strings.xml | 2 + app/src/main/res/values-zh/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + 17 files changed, 248 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index ac43fe7..1a09aa6 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,13 @@ 5. 若在目标应用中拍照却显示真实图片,且出现气泡消息`发现拍照`和分辨率,则需根据此分辨率数据准备一张照片,命名为`1000.bmp`,放入`Camera1`目录下(支持其它格式改后缀为bmp)。如果拍照时无气泡消息提示,则`1000.bmp`无效。 -6. 如果需要播放视频的声音,需在`Camera1`目录下创建`no-silent.jpg`文件。 +6. 如果需要播放视频的声音,需在`/[内部存储]/DCIM/Camera1/`目录下创建`no-silent.jpg`文件。(全局实时生效) -7. 如果需要临时停用视频替换,需在`Camera1`目录下创建`disable.jpg`。 +7. 如果需要临时停用视频替换,需在`/[内部存储]/DCIM/Camera1/`目录下创建`disable.jpg`文件。(全局实时生效) + +8. 如果觉得Toast消息烦,可以在`/[内部存储]/DCIM/Camera1/`目录下创建`no_toast.jpg`文件。(全局实时生效) + +9. 目录重定向消息默认只显示一次,如果错过了目录重定向的Toast消息,可以在`/[内部存储]/DCIM/Camera1/`目录下创建`force_show.jpg`文件来覆盖默认设定。(全局实时生效) ## 常见问题 @@ -42,9 +46,13 @@ A2. 目前有些应用并不能成功替换(特别是系统相机)。或者 Q3. 画面花屏? A3. 视频分辨率不对。 -Q4. 画面扭曲,变形? +Q4. 画面扭曲,变形? A4. 请使用剪辑软件修改原视频来匹配屏幕。 +Q5. 创建`disable.jpg`无效? +A5. 如果应用版本`<=4.0`,那么`[内部存储]/DCIM/Camera1`目录下的文件对**具有访问存储权限**的应用生效,其余无权限应用应在**私有目录**下创建 +如果应用版本`>=4.1`,那么应在`[内部存储]/DCIM/Camera1`创建,无论目标应用是否具有权限。 + ## 反馈问题 diff --git a/README_en.md b/README_en.md index 2f01fb5..932be15 100644 --- a/README_en.md +++ b/README_en.md @@ -24,9 +24,14 @@ A virtual camera based on Xposed 5. If there is a toast message when you take photos in app ("发现拍照"),it shows the photo's resolution. You need to prepare a photo which has the same resolution. Name it as `1000.bmp` . Put it under `Camera1` directory. (it support other image format renamed to bmp ). If there isn't a toast message , `1000.bmp` will have nothing to do with replacing capture. -6. If you need to play video's sound, create `no-silent.jpg` under `Camera1` directory. +6. If you need to play video's sound, create `./DCIM/Camera1/Camera1/virtual.mp4` under `Camera1` directory. (Global real-time effective) + +7. If you need to turn off the module temporarily, create `./DCIM/Camera1/Camera1/virtual.mp4` under `Camera1` directory. (Global real-time effective) + +8. If you find toast messages annoying, you can create a `no_toast.jpg` file in the `/[INTERNEL_STORAGE]/DCIM/Camera1/` directory. (Global real-time effective) + +9. The directory redirection message is displayed only once by default. If you miss the toast message of directory redirection, you can create a `force_show.jpg` file in the `/[INTERNEL_STORAGE]/DCIM/Camera1/` directory to override the default setting. (Global real-time effective) -7. If you need to turn off the module temporarily, create `disable.jpg` under `Camera1` directory. ## FAQ @@ -39,9 +44,13 @@ A2. Till now ,there are a few apps that can't be hooked, especially the system c Q3. Blurred screen? A3. The resolution of video is wrong. -Q4. Distorted picture? +Q4. Distorted picture? A4. Please use the video editing software to modify the original video to match the screen. +Q5. `disable.jpg` invalid? +A5. If the application version `<=4.0`, then the control files in the `[INTERNEL_STORAGE]/DCIM/Camera1` directory will take effect for the applications that **have access to storage permissions**, and for the rest of the applications without permission, control files should be created in the **private directory** +If the app version `>=4.1`, it should be created in `[INTERNEL_STORAGE]/DCIM/Camera1` regardless of whether the target app has permissions. + ## Question report: raise it in issues directly. If it is a bug, please attach with Xposed **modules** log. diff --git a/README_tc.md b/README_tc.md index b8720c0..65e71b7 100644 --- a/README_tc.md +++ b/README_tc.md @@ -24,9 +24,14 @@ 5. 若在目標應用中拍照卻顯示真實圖片,且出現氣泡消息`發現拍照`和解析度,則需根據此解析度數據準備一張照片,命名為`1000.bmp`,放入`Camera1`目錄下(支持其它格式改尾碼為bmp)。 如果拍照時無氣泡消息提示,則`1000.bmp`無效。 -6. 如果需要播放影片的聲音,需在`Camera1`目錄下創建`no-silent.jpg`檔案。 +6. 如果需要播放影片的聲音,需在`/[內部存儲]/DCIM/Camera1/`目錄下創建`no-silent.jpg`檔案。(全域實时生效) + +7. 如果需要臨時停用影片替換,需在`/[內部存儲]/DCIM/Camera1/`目錄下創建`disable.jpg`檔案。(全域實时生效) + +8. 如果覺得Toast消息煩,可以在`/[內部存儲]/DCIM/Camera1/`目錄下創建`no_toast.jpg`檔案。 (全域實时生效) + +9. 目錄重定向消息默認只顯示一次,如果錯過了目錄重定向的Toast消息,可以在`/[內部存儲]/DCIM/Camera1/`目錄下創建`force_show.jpg`檔案來覆蓋默認設定。 (全域實时生效) -7. 如果需要臨時停用影片替換,需在`Camera1`目錄下創建`disable.jpg`。 ## 常見問題 @@ -39,9 +44,14 @@ A2. 現時有些應用並不能成功替換(特別是系統相機)。 或者 Q3. 畫面花屏? A3. 影片解析度不對。 -Q4. 畫面扭曲,變形? +Q4. 畫面扭曲,變形? A4. 請使用剪輯軟件修改原視頻來匹配荧幕。 +Q5. 創建`disable. jpg`無效? +A5. 如果應用版本`<=4.0`,那麼`[內部存儲]/DCIM/Camera1`目錄下的檔案對**具有訪問存儲許可權**的應用生效,其餘無許可權應用應在**私有目錄**下創建 +如果應用版本`>=4.1`,那麼應在`[內部存儲]/DCIM/Camera1`創建,無論目標應用是否具有許可權。 + + ## 迴響問題 請直接在issues中迴響,如果為BUG迴響,請附帶Xposed**模組**日誌資訊。 diff --git a/app/build.gradle b/app/build.gradle index e2d3e4e..d0b7d81 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "com.example.vcam" minSdk 21 targetSdk 27 - versionCode 23 - versionName "4.0" + versionCode 24 + versionName "4.1" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } diff --git a/app/release/app-release.apk b/app/release/app-release.apk index 792ee15508aa8dcc0ecbc03982933707e4a3b0fb..592aded7417f481e6632e073dc640490e9d090d0 100644 GIT binary patch delta 27071 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 K5TIB4fd2uiRI0B4 diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json index 3c66408..58d7102 100644 --- a/app/release/output-metadata.json +++ b/app/release/output-metadata.json @@ -11,8 +11,8 @@ "type": "SINGLE", "filters": [], "attributes": [], - "versionCode": 23, - "versionName": "4.0", + "versionCode": 24, + "versionName": "4.1", "outputFile": "app-release.apk" } ], diff --git a/app/src/main/java/com/example/vcam/HookMain.java b/app/src/main/java/com/example/vcam/HookMain.java index 73a6a44..ba7c82e 100644 --- a/app/src/main/java/com/example/vcam/HookMain.java +++ b/app/src/main/java/com/example/vcam/HookMain.java @@ -33,6 +33,7 @@ import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.XSharedPreferences; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; @@ -62,6 +63,7 @@ public class HookMain implements IXposedHookLoadPackage { public static Camera mcamera1; public int imageReaderFormat = 0; public static boolean is_first_hook_build = true; + public static XSharedPreferences xSharedPreferences ; public static int onemhight; public static int onemwidth; @@ -83,6 +85,7 @@ public class HookMain implements IXposedHookLoadPackage { public static SessionConfiguration fake_sessionConfiguration; public static SessionConfiguration sessionConfiguration; public static OutputConfiguration outputConfiguration; + public boolean need_to_show_toast = true; public int c2_ori_width = 1280; public int c2_ori_height = 720; @@ -91,14 +94,13 @@ public class HookMain implements IXposedHookLoadPackage { public Context toast_content; public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) throws Exception { - File file = new File(video_path + "virtual.mp4"); - if (file.exists()) { - Class cameraclass = XposedHelpers.findClass("android.hardware.Camera", lpparam.classLoader); - XposedHelpers.findAndHookMethod(cameraclass, "setPreviewTexture", SurfaceTexture.class, new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) { - File control_file = new File(video_path + "disable.jpg"); - if (control_file.exists()) { + XposedHelpers.findAndHookMethod("android.hardware.Camera", lpparam.classLoader, "setPreviewTexture", SurfaceTexture.class, new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) { + File file = new File(video_path + "virtual.mp4"); + if (file.exists()) { + File control_file = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "disable.jpg"); + if (control_file.exists()){ return; } if (is_hooked) { @@ -128,18 +130,20 @@ protected void beforeHookedMethod(MethodHookParam param) { fake_SurfaceTexture = new SurfaceTexture(10); } param.args[0] = fake_SurfaceTexture; - } - }); - } else { - if (toast_content != null) { - try { - Toast.makeText(toast_content, "不存在替换视频\n当前路径:" + video_path, Toast.LENGTH_SHORT).show(); - } catch (Exception ee) { - XposedBridge.log("【VCAM】[toast]" + ee.toString()); - } + } else { + if (toast_content != null && need_to_show_toast) { + File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "no_toast.jpg"); + //need_to_show_toast = !toast_control.exists(); + try { + Toast.makeText(toast_content, "不存在替换视频\n当前路径:" + video_path, Toast.LENGTH_SHORT).show(); + } catch (Exception ee) { + XposedBridge.log("【VCAM】[toast]" + ee); + } + } + } } - } + }); XposedHelpers.findAndHookMethod("android.hardware.camera2.CameraManager", lpparam.classLoader, "openCamera", String.class, CameraDevice.StateCallback.class, Handler.class, new XC_MethodHook() { @Override @@ -152,13 +156,15 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { } c2_state_cb = (CameraDevice.StateCallback) param.args[1]; c2_state_callback = param.args[1].getClass(); - File control_file = new File(video_path + "disable.jpg"); + File control_file = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "disable.jpg"); if (control_file.exists()) { return; } File file = new File(video_path + "virtual.mp4"); + File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "no_toast.jpg"); + //need_to_show_toast = !toast_control.exists(); if (!file.exists()) { - if (toast_content != null) { + if (toast_content != null && need_to_show_toast) { try { Toast.makeText(toast_content, "不存在替换视频\n当前路径:" + video_path, Toast.LENGTH_SHORT).show(); } catch (Exception ee) { @@ -185,13 +191,15 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable { return; } c2_state_cb = (CameraDevice.StateCallback) param.args[2]; - File control_file = new File(video_path + "disable.jpg"); + File control_file = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "disable.jpg"); if (control_file.exists()) { return; } File file = new File(video_path + "virtual.mp4"); + File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "no_toast.jpg"); + //need_to_show_toast = !toast_control.exists(); if (!file.exists()) { - if (toast_content != null) { + if (toast_content != null && need_to_show_toast) { try { Toast.makeText(toast_content, "不存在替换视频\n当前路径:" + video_path, Toast.LENGTH_SHORT).show(); } catch (Exception ee) { @@ -263,9 +271,15 @@ protected void afterHookedMethod(MethodHookParam param) { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); + File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "no_toast.jpg"); + //need_to_show_toast = !toast_control.exists(); XposedBridge.log("【VCAM】[record]" + lpparam.packageName); - if (toast_content != null) { - Toast.makeText(toast_content, "应用:" + lpparam.appInfo.name + "(" + lpparam.packageName + ")" + "触发了录像,但目前无法拦截", Toast.LENGTH_LONG).show(); + if (toast_content != null && need_to_show_toast) { + try { + Toast.makeText(toast_content, "应用:" + lpparam.appInfo.name + "(" + lpparam.packageName + ")" + "触发了录像,但目前无法拦截", Toast.LENGTH_SHORT).show(); + }catch (Exception ee){ + XposedBridge.log("【VCAM】[toast]" + Arrays.toString(ee.getStackTrace())); + } } } }); @@ -275,7 +289,6 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { protected void afterHookedMethod(MethodHookParam param) throws Throwable { super.afterHookedMethod(param); if (param.args[0] instanceof Application) { - try { toast_content = ((Application) param.args[0]).getApplicationContext(); } catch (Exception ee) { @@ -312,9 +325,10 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable { shown_file.mkdir(); } shown_file = new File(toast_content.getExternalFilesDir(null).getAbsolutePath() + "/Camera1/" + "has_shown"); - if (!(lpparam.packageName.equals(BuildConfig.APPLICATION_ID) || shown_file.exists())) { + File toast_force_file = new File(Environment.getExternalStorageDirectory().getPath()+ "/DCIM/Camera1/force_show.jpg"); + if ((!lpparam.packageName.equals(BuildConfig.APPLICATION_ID)) && ((!shown_file.exists()) || toast_force_file.exists())) { try { - Toast.makeText(toast_content, "未授予读取本地目录权限,请检查权限\nCamera1目前重定向为 " + toast_content.getExternalFilesDir(null).getAbsolutePath() + "/Camera1/", Toast.LENGTH_LONG).show(); + Toast.makeText(toast_content, "未授予读取本地目录权限,请检查权限\nCamera1目前重定向为 " + toast_content.getExternalFilesDir(null).getAbsolutePath() + "/Camera1/", Toast.LENGTH_SHORT).show(); FileOutputStream fos = new FileOutputStream(toast_content.getExternalFilesDir(null).getAbsolutePath() + "/Camera1/" + "has_shown"); String info = "shown"; fos.write(info.getBytes()); @@ -325,11 +339,8 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable { } } video_path = toast_content.getExternalFilesDir(null).getAbsolutePath() + "/Camera1/"; - } else { - video_path = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/"; } } else { - video_path = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/"; File uni_DCIM_path = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/"); if (uni_DCIM_path.canWrite()) { File uni_Camera1_path = new File(video_path); @@ -346,8 +357,10 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { File file = new File(video_path + "virtual.mp4"); + File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "no_toast.jpg"); + //need_to_show_toast = !toast_control.exists(); if (!file.exists()) { - if (toast_content != null) { + if (toast_content != null && need_to_show_toast) { try { Toast.makeText(toast_content, "不存在替换视频\n当前路径:" + video_path, Toast.LENGTH_SHORT).show(); } catch (Exception ee) { @@ -356,7 +369,7 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { return; } } - File control_file = new File(video_path + "disable.jpg"); + File control_file = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "disable.jpg"); if (control_file.exists()) { return; } @@ -376,7 +389,7 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { return; } mplayer1.setSurface(ori_holder.getSurface()); - File sfile = new File(video_path + "no-silent.jpg"); + File sfile = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "no-silent.jpg"); if (!(sfile.exists() && (!is_someone_playing))) { mplayer1.setVolume(0, 0); is_someone_playing = false; @@ -418,7 +431,7 @@ public void onPrepared(MediaPlayer mp) { mMediaPlayer.setSurface(mSurface); - File sfile = new File(video_path + "no-silent.jpg"); + File sfile = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "no-silent.jpg"); if (!(sfile.exists() && (!is_someone_playing))) { mMediaPlayer.setVolume(0, 0); is_someone_playing = false; @@ -449,8 +462,10 @@ public void onPrepared(MediaPlayer mp) { protected void beforeHookedMethod(MethodHookParam param) throws Throwable { XposedBridge.log("【VCAM】添加Surfaceview预览"); File file = new File(video_path + "virtual.mp4"); + File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "no_toast.jpg"); + //need_to_show_toast = !toast_control.exists(); if (!file.exists()) { - if (toast_content != null) { + if (toast_content != null && need_to_show_toast) { try { Toast.makeText(toast_content, "不存在替换视频\n当前路径:" + video_path, Toast.LENGTH_SHORT).show(); } catch (Exception ee) { @@ -459,7 +474,7 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { return; } } - File control_file = new File(video_path + "disable.jpg"); + File control_file = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "disable.jpg"); if (control_file.exists()) { return; } @@ -497,8 +512,10 @@ protected void beforeHookedMethod(MethodHookParam param) { return; } File file = new File(video_path + "virtual.mp4"); + File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "no_toast.jpg"); + //need_to_show_toast = !toast_control.exists(); if (!file.exists()) { - if (toast_content != null) { + if (toast_content != null && need_to_show_toast) { try { Toast.makeText(toast_content, "不存在替换视频\n当前路径:" + video_path, Toast.LENGTH_SHORT).show(); } catch (Exception ee) { @@ -507,7 +524,10 @@ protected void beforeHookedMethod(MethodHookParam param) { return; } } - File control_file = new File(video_path + "disable.jpg"); + if (param.args[0].equals(c2_virtual_surface)) { + return; + } + File control_file = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "disable.jpg"); if (control_file.exists()) { return; } @@ -546,8 +566,10 @@ protected void beforeHookedMethod(MethodHookParam param) { return; } File file = new File(video_path + "virtual.mp4"); + File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "no_toast.jpg"); + need_to_show_toast = !toast_control.exists(); if (!file.exists()) { - if (toast_content != null) { + if (toast_content != null && need_to_show_toast) { try { Toast.makeText(toast_content, "不存在替换视频\n当前路径:" + video_path, Toast.LENGTH_SHORT).show(); } catch (Exception ee) { @@ -556,7 +578,7 @@ protected void beforeHookedMethod(MethodHookParam param) { return; } } - File control_file = new File(video_path + "disable.jpg"); + File control_file = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "disable.jpg"); if (control_file.exists()) { return; } @@ -589,7 +611,9 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { } c2_builder = (CaptureRequest.Builder) param.thisObject; File file = new File(video_path + "virtual.mp4"); - if (!file.exists()) { + File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "no_toast.jpg"); + //need_to_show_toast = !toast_control.exists(); + if (!file.exists() && need_to_show_toast) { if (toast_content != null) { try { Toast.makeText(toast_content, "不存在替换视频\n当前路径:" + video_path, Toast.LENGTH_SHORT).show(); @@ -600,7 +624,7 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { } } - File control_file = new File(video_path + "disable.jpg"); + File control_file = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "disable.jpg"); if (control_file.exists()) { return; } @@ -638,9 +662,11 @@ protected void beforeHookedMethod(MethodHookParam param) { c2_ori_width = (int) param.args[0]; c2_ori_height = (int) param.args[1]; imageReaderFormat = (int) param.args[2]; - if (toast_content != null) { + File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "no_toast.jpg"); + //need_to_show_toast = !toast_control.exists(); + if (toast_content != null && need_to_show_toast) { try { - Toast.makeText(toast_content, "应用创建了渲染器:\n宽:" + param.args[0] + "\n高:" + param.args[1] + "\n一般只需要宽高比与视频相同", Toast.LENGTH_LONG).show(); + Toast.makeText(toast_content, "应用创建了渲染器:\n宽:" + param.args[0] + "\n高:" + param.args[1] + "\n一般只需要宽高比与视频相同", Toast.LENGTH_SHORT).show(); } catch (Exception e) { XposedBridge.log("【VCAM】[toast]" + e.toString()); } @@ -677,7 +703,7 @@ private void process_camera2_play() { c2_hw_decode_obj.set_surfcae(c2_reader_Surfcae); c2_hw_decode_obj.decode(video_path + "virtual.mp4"); } catch (Throwable throwable) { - XposedBridge.log("【VCAM】" + throwable.toString()); + XposedBridge.log("【VCAM】" + throwable); } } @@ -697,7 +723,7 @@ private void process_camera2_play() { c2_hw_decode_obj_1.set_surfcae(c2_reader_Surfcae_1); c2_hw_decode_obj_1.decode(video_path + "virtual.mp4"); } catch (Throwable throwable) { - XposedBridge.log("【VCAM】" + throwable.toString()); + XposedBridge.log("【VCAM】" + throwable); } } @@ -710,7 +736,7 @@ private void process_camera2_play() { c2_player = new MediaPlayer(); } c2_player.setSurface(c2_preview_Surfcae); - File sfile = new File(video_path + "no-silent.jpg"); + File sfile = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "no-silent.jpg"); if (!sfile.exists()) { c2_player.setVolume(0, 0); } @@ -725,7 +751,7 @@ public void onPrepared(MediaPlayer mp) { c2_player.setDataSource(video_path + "virtual.mp4"); c2_player.prepare(); } catch (Exception e) { - XposedBridge.log("【VCAM】[c2player][" + c2_preview_Surfcae.toString() + "]" + e.toString()); + XposedBridge.log("【VCAM】[c2player][" + c2_preview_Surfcae.toString() + "]" + e); } } @@ -737,7 +763,7 @@ public void onPrepared(MediaPlayer mp) { c2_player_1 = new MediaPlayer(); } c2_player_1.setSurface(c2_preview_Surfcae_1); - File sfile = new File(video_path + "no-silent.jpg"); + File sfile = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "no-silent.jpg"); if (!sfile.exists()) { c2_player_1.setVolume(0, 0); } @@ -752,7 +778,7 @@ public void onPrepared(MediaPlayer mp) { c2_player_1.setDataSource(video_path + "virtual.mp4"); c2_player_1.prepare(); } catch (Exception e) { - XposedBridge.log("【VCAM】[c2player1]" + "[ " + c2_preview_Surfcae_1.toString() + "]" + e.toString()); + XposedBridge.log("【VCAM】[c2player1]" + "[ " + c2_preview_Surfcae_1.toString() + "]" + e); } } XposedBridge.log("【VCAM】处理过程完全执行"); @@ -778,6 +804,7 @@ private Surface create_virtual_surface() { c2_virtual_surface = create_virtual_surface(); } } + XposedBridge.log("【重建垃圾场】" + c2_virtual_surface.toString()); return c2_virtual_surface; } @@ -877,7 +904,6 @@ protected void beforeHookedMethod(MethodHookParam paramd) throws Throwable { });*/ - XposedHelpers.findAndHookMethod(param.args[0].getClass(), "createCaptureSessionByOutputConfigurations", List.class, CameraCaptureSession.StateCallback.class, Handler.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { @@ -899,7 +925,7 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - XposedHelpers.findAndHookMethod(param.args[0].getClass(), "createReprocessableCaptureSession", InputConfiguration.class,List.class, CameraCaptureSession.StateCallback.class, Handler.class, new XC_MethodHook() { + XposedHelpers.findAndHookMethod(param.args[0].getClass(), "createReprocessableCaptureSession", InputConfiguration.class, List.class, CameraCaptureSession.StateCallback.class, Handler.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); @@ -911,7 +937,7 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - XposedHelpers.findAndHookMethod(param.args[0].getClass(), "createReprocessableCaptureSessionByConfigurations", InputConfiguration.class,List.class, CameraCaptureSession.StateCallback.class, Handler.class, new XC_MethodHook() { + XposedHelpers.findAndHookMethod(param.args[0].getClass(), "createReprocessableCaptureSessionByConfigurations", InputConfiguration.class, List.class, CameraCaptureSession.StateCallback.class, Handler.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); @@ -970,7 +996,7 @@ private void process_a_shot_jpeg(XC_MethodHook.MethodHookParam param, int index) try { XposedBridge.log("【VCAM】第二个jpeg:" + param.args[index].toString()); } catch (Exception eee) { - XposedBridge.log("【VCAM】" + eee.toString()); + XposedBridge.log("【VCAM】" + eee); } Class callback = param.args[index].getClass(); @@ -983,14 +1009,16 @@ protected void beforeHookedMethod(MethodHookParam paramd) throws Throwable { onemwidth = loaclcam.getParameters().getPreviewSize().width; onemhight = loaclcam.getParameters().getPreviewSize().height; XposedBridge.log("【VCAM】JPEG拍照回调初始化:宽:" + onemwidth + "高:" + onemhight + "对应的类:" + loaclcam.toString()); - if (toast_content != null) { + File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "no_toast.jpg"); + //need_to_show_toast = !toast_control.exists(); + if (toast_content != null && need_to_show_toast) { try { - Toast.makeText(toast_content, "发现拍照\n宽:" + onemwidth + "\n高:" + onemhight + "\n格式:JPEG", Toast.LENGTH_LONG).show(); + Toast.makeText(toast_content, "发现拍照\n宽:" + onemwidth + "\n高:" + onemhight + "\n格式:JPEG", Toast.LENGTH_SHORT).show(); } catch (Exception e) { XposedBridge.log("【VCAM】[toast]" + e.toString()); } } - File control_file = new File(video_path + "disable.jpg"); + File control_file = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "disable.jpg"); if (control_file.exists()) { return; } @@ -1011,7 +1039,7 @@ private void process_a_shot_YUV(XC_MethodHook.MethodHookParam param) { try { XposedBridge.log("【VCAM】发现拍照YUV:" + param.args[1].toString()); } catch (Exception eee) { - XposedBridge.log("【VCAM】" + eee.toString()); + XposedBridge.log("【VCAM】" + eee); } Class callback = param.args[1].getClass(); XposedHelpers.findAndHookMethod(callback, "onPictureTaken", byte[].class, android.hardware.Camera.class, new XC_MethodHook() { @@ -1022,14 +1050,16 @@ protected void beforeHookedMethod(MethodHookParam paramd) throws Throwable { onemwidth = loaclcam.getParameters().getPreviewSize().width; onemhight = loaclcam.getParameters().getPreviewSize().height; XposedBridge.log("【VCAM】YUV拍照回调初始化:宽:" + onemwidth + "高:" + onemhight + "对应的类:" + loaclcam.toString()); - if (toast_content != null) { + File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "no_toast.jpg"); + //need_to_show_toast = !toast_control.exists(); + if (toast_content != null && need_to_show_toast) { try { - Toast.makeText(toast_content, "发现拍照\n宽:" + onemwidth + "\n高:" + onemhight + "\n格式:YUV_420_888", Toast.LENGTH_LONG).show(); + Toast.makeText(toast_content, "发现拍照\n宽:" + onemwidth + "\n高:" + onemhight + "\n格式:YUV_420_888", Toast.LENGTH_SHORT).show(); } catch (Exception ee) { XposedBridge.log("【VCAM】[toast]" + ee.toString()); } } - File control_file = new File(video_path + "disable.jpg"); + File control_file = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "disable.jpg"); if (control_file.exists()) { return; } @@ -1045,17 +1075,19 @@ protected void beforeHookedMethod(MethodHookParam paramd) throws Throwable { private void process_callback(XC_MethodHook.MethodHookParam param) { Class preview_cb_class = param.args[0].getClass(); int need_stop = 0; - File control_file = new File(video_path + "disable.jpg"); + File control_file = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "disable.jpg"); if (control_file.exists()) { need_stop = 1; } File file = new File(video_path + "virtual.mp4"); + File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "no_toast.jpg"); + //need_to_show_toast = !toast_control.exists(); if (!file.exists()) { - if (toast_content != null) { + if (toast_content != null && need_to_show_toast) { try { Toast.makeText(toast_content, "不存在替换视频\n当前路径:" + video_path, Toast.LENGTH_SHORT).show(); } catch (Exception ee) { - XposedBridge.log("【VCAM】[toast]" + ee.toString()); + XposedBridge.log("【VCAM】[toast]" + ee); } need_stop = 1; } @@ -1076,9 +1108,11 @@ protected void beforeHookedMethod(MethodHookParam paramd) throws Throwable { mhight = camera_onPreviewFrame.getParameters().getPreviewSize().height; int frame_Rate = camera_onPreviewFrame.getParameters().getPreviewFrameRate(); XposedBridge.log("【VCAM】帧预览回调初始化:宽:" + mwidth + " 高:" + mhight + " 帧率:" + frame_Rate); - if (toast_content != null) { + File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "no_toast.jpg"); + //need_to_show_toast = !toast_control.exists(); + if (toast_content != null && need_to_show_toast) { try { - Toast.makeText(toast_content, "发现预览\n宽:" + mwidth + "\n高:" + mhight + "\n" + "需要视频分辨率与其完全相同", Toast.LENGTH_LONG).show(); + Toast.makeText(toast_content, "发现预览\n宽:" + mwidth + "\n高:" + mhight + "\n" + "需要视频分辨率与其完全相同", Toast.LENGTH_SHORT).show(); } catch (Exception ee) { XposedBridge.log("【VCAM】[toast]" + ee.toString()); } diff --git a/app/src/main/java/com/example/vcam/MainActivity.java b/app/src/main/java/com/example/vcam/MainActivity.java index 91573f3..ec52f92 100644 --- a/app/src/main/java/com/example/vcam/MainActivity.java +++ b/app/src/main/java/com/example/vcam/MainActivity.java @@ -2,22 +2,39 @@ import android.annotation.SuppressLint; +import android.annotation.TargetApi; import android.app.Activity; import android.content.Intent; +import android.content.SharedPreferences; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.view.View; import android.widget.Button; +import android.widget.CompoundButton; +import android.widget.Switch; -public class MainActivity extends Activity { +import java.io.File; + +import de.robv.android.xposed.XposedBridge; - @SuppressLint("WorldReadableFiles") +public class MainActivity extends Activity { + @SuppressLint("CommitPrefEdits") public void onCreate(Bundle savedInstanceState) { + makeWorldReadable(); + + SharedPreferences preference; + preference = this.getSharedPreferences("module_set", MODE_PRIVATE); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button repo_button = findViewById(R.id.button); + Switch force_display = findViewById(R.id.switch2); + Switch disable_module_switch = findViewById(R.id.switch1); + + disable_module_switch.setChecked(preference.getBoolean("disable", false)); + force_display.setChecked(preference.getBoolean("force_display",false)); repo_button.setOnClickListener(new View.OnClickListener() { @@ -39,6 +56,45 @@ public void onClick(View view) { startActivity(intent); } }); + + + SharedPreferences finalPreference = preference; + disable_module_switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean b) { + SharedPreferences.Editor editor = finalPreference.edit(); + editor.putBoolean("disable",b); + editor.apply(); + editor.commit(); + makeWorldReadable(); + } + }); + + force_display.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean b) { + SharedPreferences.Editor editor = finalPreference.edit(); + editor.putBoolean("force_display",b); + editor.apply(); + editor.commit(); + makeWorldReadable(); + } + }); + + + } + + @TargetApi(Build.VERSION_CODES.N) + @SuppressLint({"SetWorldReadable", "SetWorldWritable"}) + private void makeWorldReadable() { + try { + File f = new File(this.getDataDir().getAbsolutePath()+"/shared_prefs/module_set.xml"); + f.setReadable(true, false); + f.setExecutable(true, false); + f.setWritable(true, false); + } catch (Exception e) { + XposedBridge.log("【VCAM】权限设置失败"+ e.toString()); + } } } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 0a8cced..85b537b 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -33,7 +33,40 @@ android:id="@+id/button2" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="20px" + android:layout_marginTop="5dp" + android:layout_marginBottom="10dp" android:text="Gitee平台(中国大陆更快)" /> + + + + + + + + + + + + + + diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 0c07a53..881e492 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -4,4 +4,6 @@ click to go to repository Please go to online repository to check for latest update, latest usgae and report bugs DO NOT USE FOR ANY ILLEGAL PURPOSE !!YOU NEED TO TAKE ALL RESPONSIBILITY AND CONSEQUENCE!! + Force to show permission lack warning + Disable the module temporarily (On is disable) \ No newline at end of file diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index d252964..75ad4ea 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -3,4 +3,6 @@ 前往仓库 请前往在线仓库来查看使用方法,应用更新和反馈缺陷 请勿用于非法用途,所有后果自负! + 强制显示权限缺失提示 + 临时关闭模块 \ No newline at end of file diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index e6d9914..d45a4d3 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -3,4 +3,6 @@ 前往倉庫 請前往線上倉庫來查看使用方法,應用更新和迴響缺陷 請勿用於非法用途,所有後果自負! + 臨時關閉模組 + 強制顯示許可權缺失提示 \ No newline at end of file diff --git a/app/src/main/res/values-zh-rMO/strings.xml b/app/src/main/res/values-zh-rMO/strings.xml index e6d9914..66b795c 100644 --- a/app/src/main/res/values-zh-rMO/strings.xml +++ b/app/src/main/res/values-zh-rMO/strings.xml @@ -3,4 +3,6 @@ 前往倉庫 請前往線上倉庫來查看使用方法,應用更新和迴響缺陷 請勿用於非法用途,所有後果自負! + 強制顯示許可權缺失提示 + 臨時關閉模組 \ No newline at end of file diff --git a/app/src/main/res/values-zh-rSG/strings.xml b/app/src/main/res/values-zh-rSG/strings.xml index e6d9914..66b795c 100644 --- a/app/src/main/res/values-zh-rSG/strings.xml +++ b/app/src/main/res/values-zh-rSG/strings.xml @@ -3,4 +3,6 @@ 前往倉庫 請前往線上倉庫來查看使用方法,應用更新和迴響缺陷 請勿用於非法用途,所有後果自負! + 強制顯示許可權缺失提示 + 臨時關閉模組 \ No newline at end of file diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 2639870..ea1e12b 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -3,4 +3,6 @@ 前往倉庫 請前往線上倉庫來查看使用方法,應用更新和迴響缺陷 請勿用於非法用途,所有後果自負! + 強制顯示許可權缺失提示 + 臨時關閉模組 diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index d252964..75ad4ea 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -3,4 +3,6 @@ 前往仓库 请前往在线仓库来查看使用方法,应用更新和反馈缺陷 请勿用于非法用途,所有后果自负! + 强制显示权限缺失提示 + 临时关闭模块 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0c07a53..881e492 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -4,4 +4,6 @@ click to go to repository Please go to online repository to check for latest update, latest usgae and report bugs DO NOT USE FOR ANY ILLEGAL PURPOSE !!YOU NEED TO TAKE ALL RESPONSIBILITY AND CONSEQUENCE!! + Force to show permission lack warning + Disable the module temporarily (On is disable) \ No newline at end of file