Files
sociology_app/uni_modules/yb-screen-capture/utssdk/app-android/index.uts

128 lines
4.0 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { UTSAndroid } from "io.dcloud.uts";
import PixelCopy from "android.view.PixelCopy";
import OnPixelCopyFinishedListener from "android.view.PixelCopy.OnPixelCopyFinishedListener";
import Bitmap from "android.graphics.Bitmap";
import Canvas from "android.graphics.Canvas";
import Handler from "android.os.Handler";
import Looper from "android.os.Looper";
import Build from "android.os.Build";
import ByteArrayOutputStream from "java.io.ByteArrayOutputStream";
import Base64 from "android.util.Base64";
import {
CaptureScreen,
CaptureScreenOptions,
CaptureScreenSuccess,
CaptureScreenFail
} from "../interface.uts";
/**
* 将 Bitmap 压缩为 JPEG 并编码为 data URL 形式的 base64
*/
function encodeBitmapToBase64(bitmap : Bitmap) : string {
const baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos);
const bytes = baos.toByteArray();
const base64 = Base64.encodeToString(bytes, Base64.NO_WRAP);
bitmap.recycle();
return "data:image/jpeg;base64," + base64;
}
/**
* PixelCopy 完成监听器
*/
class PixelCopyListener extends OnPixelCopyFinishedListener {
private bitmap : Bitmap;
private options : CaptureScreenOptions;
constructor(bitmap : Bitmap, options : CaptureScreenOptions) {
super();
this.bitmap = bitmap;
this.options = options;
}
override onPixelCopyFinished(copyResult : Int) : void {
if (copyResult == PixelCopy.SUCCESS) {
const base64 = encodeBitmapToBase64(this.bitmap);
const res : CaptureScreenSuccess = { base64: base64 };
this.options.success?.(res);
this.options.complete?.(res);
} else {
this.bitmap.recycle();
const res : CaptureScreenFail = {
errCode: 12010,
errMsg: "captureScreen:fail PixelCopy copyResult=" + copyResult
};
this.options.fail?.(res);
this.options.complete?.(res);
}
}
}
/**
* 在 UI 线程执行实际截图
*/
class CaptureRunnable extends Runnable {
private options : CaptureScreenOptions;
constructor(options : CaptureScreenOptions) {
super();
this.options = options;
}
override run() : void {
try {
const activity = UTSAndroid.getUniActivity();
if (activity == null) {
const res : CaptureScreenFail = { errCode: 12010, errMsg: "captureScreen:fail activity is null" };
this.options.fail?.(res);
this.options.complete?.(res);
return;
}
// 注意UTS 中 getWindow() 返回可空类型,必须用 ! 断言,否则编译失败
const window = activity!.getWindow()!;
const decorView = window.getDecorView()!;
const width = decorView.getWidth();
const height = decorView.getHeight();
if (width <= 0 || height <= 0) {
const res : CaptureScreenFail = { errCode: 12010, errMsg: "captureScreen:fail invalid window size" };
this.options.fail?.(res);
this.options.complete?.(res);
return;
}
const bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Android 8.0+:使用 PixelCopy 可以正确截取 SurfaceView/视频等硬件加速画面
const handler = new Handler(Looper.getMainLooper());
PixelCopy.request(window, bitmap, new PixelCopyListener(bitmap, this.options), handler);
} else {
// 低版本降级:仅能截取 View 层级内容,视频区域可能为黑屏
const canvas = new Canvas(bitmap);
decorView.draw(canvas);
const base64 = encodeBitmapToBase64(bitmap);
const res : CaptureScreenSuccess = { base64: base64 };
this.options.success?.(res);
this.options.complete?.(res);
}
} catch (e) {
const res : CaptureScreenFail = { errCode: 12010, errMsg: "captureScreen:fail " + e.toString() };
this.options.fail?.(res);
this.options.complete?.(res);
}
}
}
export const captureScreen : CaptureScreen = function (options : CaptureScreenOptions) {
const activity = UTSAndroid.getUniActivity();
if (activity == null) {
const res : CaptureScreenFail = { errCode: 12010, errMsg: "captureScreen:fail activity is null" };
options.fail?.(res);
options.complete?.(res);
return;
}
activity!.runOnUiThread(new CaptureRunnable(options));
}