Skip to content

Commit 97ce5b6

Browse files
author
Ven
committed
feat: 步骤器改版
1 parent 4b57b68 commit 97ce5b6

30 files changed

+582
-564
lines changed

assists/build.gradle

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,12 @@ android {
3131
}
3232

3333
dependencies {
34-
implementation 'androidx.core:core-ktx:1.13.0'
34+
implementation 'androidx.core:core-ktx:1.13.1'
35+
implementation 'androidx.activity:activity-ktx:1.9.0'
36+
implementation 'androidx.appcompat:appcompat:1.6.1'
3537
implementation platform('org.jetbrains.kotlin:kotlin-bom:1.8.22')
3638
api 'com.blankj:utilcodex:1.31.1'
39+
implementation project(':opencv-sdk')
3740
}
3841

3942
apply from: rootProject.file("gradle/maven-publish.gradle")
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,21 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
33

4+
<application>
5+
<provider
6+
android:name="com.ven.assists.AssistsFileProvider"
7+
android:authorities="${applicationId}.assists.fileprovider"
8+
android:exported="false"
9+
android:grantUriPermissions="true">
10+
<meta-data
11+
android:name="android.support.FILE_PROVIDER_PATHS"
12+
android:resource="@xml/assists_provider_paths" />
13+
</provider>
14+
<service
15+
android:name="com.ven.assists.ScreenService"
16+
android:enabled="true"
17+
android:exported="false"
18+
android:foregroundServiceType="mediaProjection" />
19+
20+
</application>
421
</manifest>

assists/src/main/java/com/ven/assists/Assists.kt

Lines changed: 97 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,55 @@ package com.ven.assists
22

33
import android.accessibilityservice.AccessibilityService
44
import android.accessibilityservice.GestureDescription
5+
import android.app.Activity
6+
import android.app.Application
57
import android.content.ClipData
68
import android.content.ClipboardManager
79
import android.content.Context
810
import android.content.Intent
911
import android.graphics.Path
1012
import android.graphics.Rect
13+
import android.media.projection.MediaProjectionManager
14+
import android.os.Bundle
1115
import android.provider.Settings
1216
import android.text.TextUtils
1317
import android.util.Log
1418
import android.view.accessibility.AccessibilityNodeInfo
19+
import androidx.activity.ComponentActivity
20+
import androidx.activity.result.ActivityResultLauncher
21+
import androidx.activity.result.contract.ActivityResultContracts
22+
import androidx.appcompat.app.AppCompatActivity
1523
import com.blankj.utilcode.util.ActivityUtils
1624
import com.blankj.utilcode.util.LogUtils
1725
import com.blankj.utilcode.util.ScreenUtils
1826
import com.blankj.utilcode.util.ThreadUtils
27+
import com.ven.assists.stepper.StepManager
28+
import kotlinx.coroutines.CoroutineScope
29+
import kotlinx.coroutines.Dispatchers
30+
import kotlinx.coroutines.Job
1931

2032
object Assists {
2133

2234
//日志TAG
2335
var LOG_TAG = "assists_log"
2436

37+
//手势执行延迟回调
38+
var gestureBeginDelay = 0L
39+
40+
val screenRequestLaunchers: HashMap<Activity, ActivityResultLauncher<Intent>> = hashMapOf()
41+
42+
private var job = Job()
43+
var coroutine: CoroutineScope = CoroutineScope(job + Dispatchers.IO)
44+
private set
45+
get() {
46+
if (job.isCancelled || !job.isActive) {
47+
job = Job()
48+
field = CoroutineScope(job + Dispatchers.IO)
49+
}
50+
return field
51+
}
52+
53+
2554
/**
2655
* 无障碍服务,未开启前为null,使用注意判空
2756
*/
@@ -33,11 +62,76 @@ object Assists {
3362
//手势监听
3463
val gestureListeners: ArrayList<GestureListener> = arrayListOf()
3564

36-
//手势执行延迟回调
37-
var gestureBeginDelay = 0L
3865

39-
fun init() {
66+
var screenCaptureService: ScreenCaptureService? = null
67+
set(value) {
68+
if (value != null) {
69+
serviceListeners.forEach { it.screenCaptureEnable() }
70+
}
71+
field = value
72+
}
73+
74+
private val activityLifecycleCallbacks = object : Application.ActivityLifecycleCallbacks {
75+
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
76+
if (activity is ComponentActivity) {
77+
val screenRequestLauncher = activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
78+
if (result.resultCode == Activity.RESULT_OK) {
79+
val service = Intent(activity, ScreenCaptureService::class.java)
80+
service.putExtra("rCode", result.resultCode)
81+
service.putExtra("rData", result.data)
82+
activity.startService(service)
83+
}
84+
}
85+
screenRequestLaunchers[activity] = screenRequestLauncher
86+
}
87+
}
88+
89+
override fun onActivityStarted(activity: Activity) {
90+
}
91+
92+
override fun onActivityResumed(activity: Activity) {
93+
}
94+
95+
override fun onActivityPaused(activity: Activity) {
96+
}
97+
98+
override fun onActivityStopped(activity: Activity) {
99+
}
100+
101+
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
102+
}
103+
104+
override fun onActivityDestroyed(activity: Activity) {
105+
screenRequestLaunchers.remove(activity)
106+
}
107+
}
108+
109+
/**
110+
* 请求录屏权限
111+
* @param isAutoEnable 是否自动通过,如果设置自动通过前提需要先开启无障碍服务(当前仅测试小米系统通过,其他机型系统未测试)
112+
*/
113+
fun requestScreenCapture(isAutoEnable: Boolean) {
114+
screenCaptureService ?: let {
115+
screenRequestLaunchers[ActivityUtils.getTopActivity()]?.launch(
116+
(ActivityUtils.getTopActivity().getSystemService(AppCompatActivity.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager)
117+
.createScreenCaptureIntent()
118+
)
119+
if (isAutoEnable && service != null) {
120+
}
121+
}
122+
}
123+
124+
/**
125+
* 是否拥有录屏权限
126+
*/
127+
fun isOwnScreenCapture(): Boolean {
128+
return screenCaptureService == null
129+
}
130+
131+
fun init(application: Application) {
132+
application.registerActivityLifecycleCallbacks(activityLifecycleCallbacks)
40133
LogUtils.getConfig().globalTag = LOG_TAG
134+
OpencvWrapper.init()
41135
}
42136

43137
/**
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.ven.assists
2+
3+
import android.app.Activity
4+
import android.app.Activity.RESULT_OK
5+
import android.app.Application
6+
import android.content.Intent
7+
import android.os.Bundle
8+
import androidx.activity.ComponentActivity
9+
import androidx.activity.result.ActivityResultLauncher
10+
import androidx.activity.result.contract.ActivityResultContracts
11+
import androidx.core.content.FileProvider
12+
import com.blankj.utilcode.util.LogUtils
13+
14+
class AssistsFileProvider : FileProvider() {
15+
override fun onCreate(): Boolean {
16+
val applicationContext = context?.applicationContext
17+
if (applicationContext is Application) {
18+
Assists.init(applicationContext)
19+
}
20+
return super.onCreate()
21+
}
22+
}

assists/src/main/java/com/ven/assists/AssistsService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ package com.ven.assists
33
import android.accessibilityservice.AccessibilityService
44
import android.content.Intent
55
import android.view.accessibility.AccessibilityEvent
6+
import com.blankj.utilcode.util.ActivityUtils
67
import com.blankj.utilcode.util.LogUtils
78

89
class AssistsService : AccessibilityService() {
910

1011
override fun onCreate() {
1112
super.onCreate()
1213
Assists.service = this
13-
Assists.init()
1414
}
1515

1616
override fun onServiceConnected() {

assists/src/main/java/com/ven/assists/AssistsServiceListener.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,11 @@ interface AssistsServiceListener {
1818
* 服务关闭后的回调,即[AssistsService.onUnbind]回调
1919
*/
2020
fun onUnbind() {}
21+
22+
/**
23+
* 录屏权限开启
24+
*/
25+
fun screenCaptureEnable() {
26+
27+
}
2128
}

assists/src/main/java/com/ven/assists/AssistsWindowManager.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ object AssistsWindowManager {
7575
viewList.add(ViewWrapper(view, view.layoutParams))
7676
}
7777

78+
fun pop() {
79+
viewList.lastOrNull()?.let {
80+
removeView(it.view)
81+
}
82+
}
83+
7884
fun removeView(view: View?) {
7985
view ?: return
8086
windowManager.removeView(view)
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package com.ven.assists
2+
3+
import android.graphics.Bitmap
4+
import android.graphics.BitmapFactory
5+
import com.blankj.utilcode.util.ActivityUtils
6+
import com.blankj.utilcode.util.LogUtils
7+
import kotlinx.coroutines.Dispatchers
8+
import kotlinx.coroutines.GlobalScope
9+
import kotlinx.coroutines.launch
10+
import kotlinx.coroutines.withContext
11+
import org.opencv.android.OpenCVLoader
12+
import org.opencv.android.Utils
13+
import org.opencv.core.Core
14+
import org.opencv.core.Mat
15+
import org.opencv.core.Point
16+
import org.opencv.imgproc.Imgproc
17+
import java.io.IOException
18+
import java.io.InputStream
19+
20+
object OpencvWrapper {
21+
22+
fun init() {
23+
Assists.coroutine.launch {
24+
if (OpenCVLoader.initLocal()) {
25+
LogUtils.d("OpenCV loaded successfully")
26+
} else {
27+
LogUtils.d("OpenCV initialization failed!")
28+
}
29+
}
30+
}
31+
32+
fun matchTemplateFromScreen(image: Mat, template: Mat): Point {
33+
val result = Mat()
34+
val method = Imgproc.TM_CCOEFF_NORMED
35+
Imgproc.matchTemplate(image, template, result, method)
36+
val minMaxLocResult = Core.minMaxLoc(result)
37+
return minMaxLocResult.maxLoc
38+
}
39+
40+
fun getScreen() {
41+
val screenBitmap = Assists.screenCaptureService?.toBitmap()
42+
val screenMat = Mat()
43+
Utils.bitmapToMat(screenBitmap, screenMat)
44+
Imgproc.cvtColor(screenMat, screenMat, Imgproc.COLOR_RGBA2BGR)
45+
}
46+
47+
fun getTemplateFromAsset(assetPath: String): Mat? {
48+
val bitmap = getBitmapFromAsset(assetPath)
49+
bitmap ?: return null
50+
val mat = Mat()
51+
Utils.bitmapToMat(bitmap, mat)
52+
Imgproc.cvtColor(mat, mat, Imgproc.COLOR_RGBA2BGR)
53+
return mat
54+
}
55+
56+
private fun getBitmapFromAsset(filePath: String): Bitmap? {
57+
val assetManager = ActivityUtils.getTopActivity().assets
58+
var inputStream: InputStream? = null
59+
return try {
60+
inputStream = assetManager.open(filePath)
61+
BitmapFactory.decodeStream(inputStream)
62+
} catch (e: IOException) {
63+
e.printStackTrace()
64+
null
65+
} finally {
66+
if (inputStream != null) {
67+
try {
68+
inputStream.close()
69+
} catch (e: IOException) {
70+
e.printStackTrace()
71+
}
72+
}
73+
}
74+
}
75+
76+
77+
}

simple/src/main/java/com/ven/assists/simple/ScreenCaptureService.kt renamed to assists/src/main/java/com/ven/assists/ScreenCaptureService.kt

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
package com.ven.assists.simple
1+
package com.ven.assists
22

33
import android.app.Notification
44
import android.app.NotificationChannel
55
import android.app.NotificationManager
66
import android.app.Service
7-
import android.content.Context
87
import android.content.Intent
98
import android.graphics.Bitmap
10-
import android.graphics.BitmapFactory
119
import android.graphics.Color
1210
import android.graphics.PixelFormat
1311
import android.hardware.display.DisplayManager
@@ -17,26 +15,21 @@ import android.media.projection.MediaProjection
1715
import android.media.projection.MediaProjectionManager
1816
import android.os.Build
1917
import android.os.IBinder
20-
import android.util.DisplayMetrics
21-
import android.view.WindowManager
2218
import androidx.annotation.RequiresApi
2319
import androidx.core.app.NotificationCompat
2420
import com.blankj.utilcode.util.PathUtils
2521
import com.blankj.utilcode.util.ScreenUtils
22+
import com.ven.assists.base.R
2623
import java.io.File
2724
import java.io.FileOutputStream
2825
import java.nio.ByteBuffer
2926

3027

3128
/**
32-
* 录制视频服务
29+
* 屏幕录制服务
3330
*/
3431
class ScreenCaptureService : Service() {
3532

36-
companion object {
37-
var instance: ScreenCaptureService? = null
38-
}
39-
4033
private var mMediaProjectionManager: MediaProjectionManager? = null
4134
private var imageReader: ImageReader? = null
4235
override fun onCreate() {
@@ -46,9 +39,13 @@ class ScreenCaptureService : Service() {
4639

4740
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
4841
val rCode = intent.getIntExtra("rCode", -1)
49-
val rData = intent.getParcelableExtra<Intent>("rData")
42+
val rData = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
43+
intent.getParcelableExtra("rData", Intent::class.java)
44+
} else {
45+
intent.getParcelableExtra<Intent>("rData")
46+
}
5047
startPushProjection(rCode, rData)
51-
instance = this
48+
Assists.screenCaptureService = this
5249
return super.onStartCommand(intent, flags, startId)
5350
}
5451

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.ven.assists.stepper
2+
3+
class Step private constructor(val tag: Int) {
4+
companion object {
5+
val none = Step(-1)
6+
val repeat = Step(-2)
7+
8+
fun get(tag: Int): Step {
9+
return Step(tag)
10+
}
11+
}
12+
13+
var stepImpl: StepImpl? = null
14+
}

0 commit comments

Comments
 (0)