Skip to content

Commit 01449ae

Browse files
committed
feat(documents): 更新文档并添加新功能说明
- 更新 AssistsWindowManager 相关文档 - 新增 MPManager 和 OpencvWrapper 的详细说明 - 添加使用示例和注意事项
1 parent 294c022 commit 01449ae

File tree

4 files changed

+276
-141
lines changed

4 files changed

+276
-141
lines changed

assists-mp/src/main/java/com/ven/assists_mp/MPManager.kt

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,25 +34,38 @@ import kotlinx.coroutines.Job
3434
import kotlinx.coroutines.delay
3535
import java.io.File
3636

37+
/**
38+
* 屏幕录制管理器
39+
* 负责处理屏幕录制相关的功能,包括权限请求、截图和图像处理
40+
*/
3741
object MPManager {
42+
/** 媒体投影请求码 */
3843
const val REQUEST_CODE = "request_code_media_projection"
44+
/** 媒体投影请求数据 */
3945
const val REQUEST_DATA = "request_data_media_projection"
4046

47+
/** 存储Activity和其对应的结果启动器映射 */
4148
private var requestLaunchers = hashMapOf<Activity, ActivityResultLauncher<Intent>>()
4249

50+
/** 服务启用回调 */
4351
var onEnable: ((service: MPService, intent: Intent, flags: Int, startId: Int) -> Unit)? = null
52+
/** 异步等待服务启用的Deferred对象 */
4453
private var completableDeferredEnable: CompletableDeferred<Boolean>? = null
54+
/** 自动允许权限的协程Job */
4555
private var autoAllowJob: Job? = null
4656

57+
/** 图像读取器实例 */
4758
private var imageReader: ImageReader? = null
4859

60+
/** 屏幕录制是否已启用 */
4961
var isEnable = false
5062
private set
5163
get() {
5264
field = imageReader?.let { return@let true } ?: false
5365
return field
5466
}
5567

68+
/** Activity生命周期回调,用于管理结果启动器 */
5669
private val activityLifecycleCallbacks = object : Application.ActivityLifecycleCallbacks {
5770
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
5871
if (activity is ComponentActivity && requestLaunchers[activity] == null) {
@@ -82,13 +95,24 @@ object MPManager {
8295
}
8396
}
8497

98+
/**
99+
* 处理服务启动命令
100+
* @param service MPService实例
101+
* @param intent 启动意图
102+
* @param flags 启动标志
103+
* @param startId 启动ID
104+
*/
85105
private fun onStartCommand(service: MPService, intent: Intent, flags: Int, startId: Int) {
86106
onCreateImageReader(service, intent, flags, startId)
87107
onEnable?.invoke(service, intent, flags, startId)
88108
completableDeferredEnable?.complete(true)
89109
completableDeferredEnable = null
90110
}
91111

112+
/**
113+
* 处理权限请求结果
114+
* @param result 活动结果
115+
*/
92116
private fun onResult(result: ActivityResult) {
93117
if (result.resultCode == Activity.RESULT_OK) {
94118
MPService.onStartCommand = ::onStartCommand
@@ -100,6 +124,13 @@ object MPManager {
100124
}
101125
}
102126

127+
/**
128+
* 创建并初始化图像读取器
129+
* @param service MPService实例
130+
* @param intent 启动意图
131+
* @param flags 启动标志
132+
* @param startId 启动ID
133+
*/
103134
private fun onCreateImageReader(service: MPService, intent: Intent, flags: Int, startId: Int) {
104135
imageReader?.close()
105136
val mediaProjectionManager = service.getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
@@ -127,12 +158,22 @@ object MPManager {
127158
}
128159
}
129160

161+
/**
162+
* 初始化管理器
163+
* @param application Application实例
164+
*/
130165
fun init(application: Application) {
131166
requestLaunchers.clear()
132167
application.unregisterActivityLifecycleCallbacks(activityLifecycleCallbacks)
133168
application.registerActivityLifecycleCallbacks(activityLifecycleCallbacks)
134169
}
135170

171+
/**
172+
* 请求屏幕录制权限
173+
* @param autoAllow 是否自动允许权限弹窗,默认为true
174+
* @param timeOut 超时时间,默认5000毫秒
175+
* @return 权限是否获取成功
176+
*/
136177
suspend fun request(autoAllow: Boolean = true, timeOut: Long = 5000): Boolean {
137178
var projectionManager: MediaProjectionManager? = null
138179
AssistsService.instance?.let {
@@ -179,6 +220,10 @@ object MPManager {
179220
return completableDeferredEnable?.await() ?: false
180221
}
181222

223+
/**
224+
* 获取当前屏幕截图
225+
* @return 屏幕截图位图,如果失败返回null
226+
*/
182227
fun takeScreenshot2Bitmap(): Bitmap? {
183228
imageReader?.let {
184229
val image: Image = it.acquireLatestImage()
@@ -193,6 +238,11 @@ object MPManager {
193238
} ?: let { throw RuntimeException("Please request permission for screen recording first") }
194239
}
195240

241+
/**
242+
* 获取指定元素的截图
243+
* @param screenshot 完整的屏幕截图
244+
* @return 元素区域的位图,如果失败返回null
245+
*/
196246
fun AccessibilityNodeInfo.getBitmap(screenshot: Bitmap): Bitmap? {
197247
runCatching {
198248
getBoundsInScreen().let {
@@ -205,6 +255,12 @@ object MPManager {
205255
return null
206256
}
207257

258+
/**
259+
* 将指定元素的截图保存到文件
260+
* @param screenshot 完整的屏幕截图
261+
* @param file 保存的目标文件,默认保存到应用内部文件目录
262+
* @return 保存成功返回文件对象,失败返回null
263+
*/
208264
fun AccessibilityNodeInfo.takeScreenshot2File(
209265
screenshot: Bitmap,
210266
file: File = File(
@@ -220,6 +276,11 @@ object MPManager {
220276
return null
221277
}
222278

279+
/**
280+
* 将当前屏幕截图保存到文件
281+
* @param file 保存的目标文件,默认保存到应用内部文件目录
282+
* @return 保存成功返回文件对象,失败返回null
283+
*/
223284
fun takeScreenshot2File(
224285
file: File = File(
225286
PathUtils.getInternalAppFilesPath(),
@@ -234,6 +295,11 @@ object MPManager {
234295
return null
235296
}
236297

298+
/**
299+
* 将Image对象转换为Bitmap
300+
* @param image 要转换的Image对象
301+
* @return 转换后的Bitmap对象
302+
*/
237303
private fun imageToBitmap(image: Image): Bitmap {
238304
val planes = image.planes
239305
val buffer = planes[0].buffer
@@ -249,5 +315,4 @@ object MPManager {
249315
bitmap.copyPixelsFromBuffer(buffer)
250316
return bitmap
251317
}
252-
253318
}

assists-mp/src/main/java/com/ven/assists_mp/MPService.kt

Lines changed: 23 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,12 @@ import androidx.annotation.RequiresApi
1313
import androidx.core.app.NotificationCompat
1414
import com.ven.assists.base.R
1515

16-
17-
/**
18-
* 屏幕录制服务
19-
*/
2016
class MPService : Service() {
2117

2218
companion object {
23-
var onStartCommand: ((service: MPService, intent: Intent, flags: Int, startId: Int) -> Unit)? = null
19+
var onStartCommand:
20+
((service: MPService, intent: Intent, flags: Int, startId: Int) -> Unit)? =
21+
null
2422
}
2523

2624
override fun onCreate() {
@@ -32,105 +30,33 @@ class MPService : Service() {
3230
return super.onStartCommand(intent, flags, startId)
3331
}
3432

35-
private fun captureScreen(mediaProjection: MediaProjection) {
36-
37-
// val screenWidth = ScreenUtils.getScreenWidth()
38-
// val screenHeight = ScreenUtils.getScreenHeight()
39-
// val screenDensityDpi = ScreenUtils.getScreenDensityDpi()
40-
//
41-
// imageReader = ImageReader.newInstance(screenWidth, screenHeight, PixelFormat.RGBA_8888, 2)
42-
//
43-
// mediaProjection.createVirtualDisplay(
44-
// "ScreenCapture",
45-
// screenWidth,
46-
// screenHeight,
47-
// screenDensityDpi,
48-
// DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
49-
// imageReader?.surface,
50-
// null,
51-
// null
52-
// )
53-
}
54-
55-
56-
// fun saveBitmap(): File? {
57-
// val image: Image? = imageReader?.acquireLatestImage()
58-
//
59-
// try {
60-
// val width = ScreenUtils.getScreenWidth()
61-
// val height = ScreenUtils.getScreenHeight()
62-
// val planes: Array<Image.Plane> = image?.planes ?: return null
63-
// val buffer: ByteBuffer = planes[0].buffer
64-
// val pixelStride: Int = planes[0].pixelStride
65-
// val rowStride: Int = planes[0].rowStride
66-
// val rowPadding = rowStride - pixelStride * width
67-
// val bitmap = Bitmap.createBitmap(
68-
// width + rowPadding / pixelStride,
69-
// height,
70-
// Bitmap.Config.ARGB_8888
71-
// )
72-
// bitmap.copyPixelsFromBuffer(buffer)
73-
// val file = File(PathUtils.getInternalAppCachePath(), "${System.currentTimeMillis()}.png")
74-
// val fileOutputStream = FileOutputStream(file)
75-
// bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream)
76-
// fileOutputStream.flush()
77-
// fileOutputStream.close()
78-
// image.close()
79-
// return file
80-
// } catch (e: Throwable) {
81-
// return null
82-
// } finally {
83-
// image?.close()
84-
// }
85-
// }
86-
87-
// fun toBitmap(): Bitmap? {
88-
// val image: Image? = imageReader?.acquireLatestImage()
89-
//
90-
// return try {
91-
// val width = ScreenUtils.getScreenWidth()
92-
// val height = ScreenUtils.getScreenHeight()
93-
// val planes: Array<Image.Plane> = image?.planes ?: return null
94-
// val buffer: ByteBuffer = planes[0].buffer
95-
// val pixelStride: Int = planes[0].pixelStride
96-
// val rowStride: Int = planes[0].rowStride
97-
// val rowPadding = rowStride - pixelStride * width
98-
// val bitmap = Bitmap.createBitmap(
99-
// width + rowPadding / pixelStride,
100-
// height,
101-
// Bitmap.Config.ARGB_8888
102-
// )
103-
// bitmap.copyPixelsFromBuffer(buffer)
104-
// return bitmap
105-
// } catch (e: Throwable) {
106-
// null
107-
// } finally {
108-
// image?.close()
109-
// }
110-
// }
111-
11233
private fun initNotificationChannel() {
113-
val channelId = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
114-
createNotificationChannel()
115-
} else {
116-
""
117-
}
34+
val channelId =
35+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
36+
createNotificationChannel()
37+
} else {
38+
""
39+
}
11840
val builder = NotificationCompat.Builder(this, channelId)
119-
val notification = builder.setOngoing(true)
120-
.setSmallIcon(R.mipmap.ic_launcher)
121-
.setPriority(NotificationCompat.PRIORITY_MIN)
122-
.setCategory(Notification.CATEGORY_SERVICE)
123-
.build()
41+
val notification =
42+
builder.setOngoing(true)
43+
.setSmallIcon(R.mipmap.ic_launcher)
44+
.setPriority(NotificationCompat.PRIORITY_MIN)
45+
.setCategory(Notification.CATEGORY_SERVICE)
46+
.build()
12447
startForeground(1, notification)
12548
}
12649

127-
/**
128-
* 创建通知通道
129-
*/
50+
/** 创建通知通道 */
13051
@RequiresApi(Build.VERSION_CODES.O)
13152
private fun createNotificationChannel(): String {
13253
val channelId = "mirror.hsl"
133-
val chan = NotificationChannel(channelId, "ForegroundService", NotificationManager.IMPORTANCE_NONE)
54+
val chan =
55+
NotificationChannel(
56+
channelId,
57+
"ForegroundService",
58+
NotificationManager.IMPORTANCE_NONE
59+
)
13460
chan.lightColor = Color.BLUE
13561
chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
13662
val service = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
@@ -145,4 +71,4 @@ class MPService : Service() {
14571
override fun onDestroy() {
14672
super.onDestroy()
14773
}
148-
}
74+
}

0 commit comments

Comments
 (0)