feat(settings): 优化截屏方案并优先使用SurfaceControl

This commit is contained in:
2026-07-27 02:22:18 +08:00
parent 951cedb8b1
commit b54015504e
2 changed files with 52 additions and 7 deletions

View File

@@ -150,13 +150,8 @@ public class SettingsUtilsActivity extends BaseMvvmActivity<SettingsUtilsViewMod
}
public void screenshotSnap(View view) {
// Bitmap bitmap = SystemUtils.takeFullScreenshot(SettingsUtilsActivity.this);
// Bitmap bitmap = SystemUtils.takeScreenshotHighVersion();
// if (bitmap != null) {
// mViewDataBinding.ivSnap.setImageBitmap(bitmap);
// }
String filepath = getExternalCacheDir().getAbsolutePath() + File.separator + "screenshot_" + System.currentTimeMillis() + ".png";
SystemUtils.screenshotCmd(filepath, new BlockingBaseObserver<Integer>() {
SystemUtils.screenshotSnap(SettingsUtilsActivity.this, filepath, new BlockingBaseObserver<Integer>() {
@Override
public void onNext(@NonNull Integer integer) {
if (integer == 0) {
@@ -167,7 +162,7 @@ public class SettingsUtilsActivity extends BaseMvvmActivity<SettingsUtilsViewMod
@Override
public void onError(@NonNull Throwable e) {
Logger.e(TAG, "screenshotSnap onError: " + e.getMessage());
}
});
}

View File

@@ -38,6 +38,7 @@ import android.view.WindowManager;
import com.ttstd.dialer.BuildConfig;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
@@ -62,6 +63,8 @@ import io.reactivex.rxjava3.core.Observer;
import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
import androidx.annotation.RequiresApi;
public class SystemUtils {
private static final String TAG = "SystemUtils";
@@ -667,6 +670,7 @@ public class SystemUtils {
}
}
@RequiresApi(api = Build.VERSION_CODES.Q)
public static Bitmap takeScreenshotHighVersion() {
try {
// 1. 获取主屏幕的 Token (Internal Display)
@@ -735,6 +739,52 @@ public class SystemUtils {
}
}
/**
* 智能截屏:根据系统版本选择最佳方案
* 1. 优先使用 SurfaceControl 反射 (速度快,且避开 Android 10+ 的 "Bad system call")
* 2. 失败则回退到 screencap 命令行
*
* @param context 上下文
* @param filepath 保存路径
* @param observer 结果回调 (0 为成功)
*/
public static void screenshotSnap(Context context, String filepath, Observer<Integer> observer) {
Observable.fromCallable(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
Bitmap bitmap = null;
// 1. 对于 Android 9.0 及以上,优先尝试反射 SurfaceControl
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
bitmap = takeScreenshotHighVersion();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
bitmap = takeFullScreenshot(context);
}
if (bitmap != null) {
try (FileOutputStream fos = new FileOutputStream(filepath)) {
boolean success = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
if (success) {
Logger.i(TAG, "screenshotSnap: SurfaceControl 截屏成功");
return 0;
}
}
}
} catch (Exception e) {
Logger.e(TAG, "SurfaceControl 截屏异常: " + e.getMessage());
}
// 2. Fallback: 使用命令行 (适用于旧版本或已 Root 设备)
Logger.w(TAG, "screenshotSnap: 尝试使用命令行回退");
CmdUtil.Result result = CmdUtil.execute("screencap -p " + filepath);
if (result.code != 0) {
Logger.e(TAG, "screenshotSnap 命令行失败: " + result.error);
}
return result.code;
}
}).subscribe(observer);
}
public static void screenshotCmd(String filepath, Observer<Integer> observer) {
Observable.fromCallable(new Callable<Integer>() {
@Override