diff --git a/android/app/build.gradle b/android/app/build.gradle
index 9aa6a16d0..24d927b25 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -33,7 +33,7 @@ apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 30
- // ndkVersion '22.1.7171670' // * 仅个人使用 存在多版本NDK无法自动选择 需要使用此配置指定NDK版本 [CSF]
+ ndkVersion '22.1.7171670' // * 仅个人使用 存在多版本NDK无法自动选择 需要使用此配置指定NDK版本 [CSF]
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index e096196e9..c83ccf780 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -1,51 +1,76 @@
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/carriez/flutter_hbb/InputService.kt b/android/app/src/main/kotlin/com/carriez/flutter_hbb/InputService.kt
new file mode 100644
index 000000000..6b23eaddd
--- /dev/null
+++ b/android/app/src/main/kotlin/com/carriez/flutter_hbb/InputService.kt
@@ -0,0 +1,106 @@
+package com.carriez.flutter_hbb
+
+import android.accessibilityservice.AccessibilityService
+import android.accessibilityservice.GestureDescription
+import android.content.Context
+import android.graphics.Path
+import android.os.Build
+import android.util.Log
+import android.view.accessibility.AccessibilityEvent
+import androidx.annotation.RequiresApi
+import kotlin.concurrent.thread
+
+class InputService : AccessibilityService() {
+// companion object {
+// var inputService:InputService? = null
+// }
+ private val logTag = "input service"
+ private var leftIsDown = false
+ private var mPath = Path()
+ private var mLastGestureStartTime = 0L
+ private var mouseX = 0
+ private var mouseY = 0
+
+ @RequiresApi(Build.VERSION_CODES.N)
+ fun mouseInput(mask: Int, _x: Int, _y: Int) {
+ Log.w(logTag, "got mouse input:x:$_x ,y:$_y ,mask:$mask ")
+
+ // TODO 临时倍数
+ // TODO 按键抬起按下时候 x y 都是0
+ if ( !(mask == 9 || mask == 10) ) {
+ mouseX = _x * 2
+ mouseY = _y * 2
+ }
+
+ // left button down ,was up
+ if (mask == 9){
+ leftIsDown = true
+ startGesture(mouseX,mouseY)
+ }
+
+ // left down ,was down
+ if (mask == 9){
+ continueGesture(mouseX,mouseY)
+ }
+
+ // left up ,was down
+ if (mask == 10){
+ leftIsDown = false
+ endGesture(mouseX, mouseY)
+ }
+ }
+
+ private fun startGesture(x: Int, y: Int) {
+ mPath = Path()
+ mPath.moveTo(x.toFloat(), y.toFloat())
+ mLastGestureStartTime = System.currentTimeMillis()
+ }
+
+ private fun continueGesture(x: Int, y: Int) {
+ mPath.lineTo(x.toFloat(), y.toFloat())
+ }
+ @RequiresApi(Build.VERSION_CODES.N)
+ private fun endGesture(x: Int, y: Int) {
+ mPath.lineTo(x.toFloat(), y.toFloat())
+ val stroke = GestureDescription.StrokeDescription(
+ mPath,
+ 0,
+ System.currentTimeMillis() - mLastGestureStartTime
+ )
+ val builder = GestureDescription.Builder()
+ builder.addStroke(stroke)
+ Log.d(logTag, "end gesture $x $y")
+ dispatchGesture(builder.build(), object : GestureResultCallback() {
+ override fun onCompleted(gestureDescription: GestureDescription) {
+ super.onCompleted(gestureDescription)
+ Log.d(logTag, "滑动成功")
+ }
+
+ override fun onCancelled(gestureDescription: GestureDescription) {
+ super.onCancelled(gestureDescription)
+ Log.d(logTag, "滑动失败 ")
+ }
+ }, null)
+ }
+
+ external fun init(ctx: Context)
+
+ init {
+ System.loadLibrary("rustdesk")
+ }
+
+ private val LOG_TAG = "INPUT_LOG"
+ @RequiresApi(Build.VERSION_CODES.O)
+ override fun onServiceConnected() {
+ super.onServiceConnected()
+ Log.d(LOG_TAG,"onServiceConnected!")
+ init(this)
+ }
+ override fun onAccessibilityEvent(event: AccessibilityEvent?) {
+// TODO("Not yet implemented")
+ }
+
+ override fun onInterrupt() {
+// TODO("Not yet implemented")
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt b/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt
index 393e96a98..372bd3cfe 100644
--- a/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt
+++ b/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainActivity.kt
@@ -1,12 +1,14 @@
package com.carriez.flutter_hbb
import android.app.Activity
+import android.app.AlertDialog
import android.content.Context
import android.content.Intent
import android.media.projection.MediaProjectionManager
import android.os.Build
import android.os.Bundle
import android.os.PersistableBundle
+import android.provider.Settings
import android.util.Log
import androidx.annotation.RequiresApi
import io.flutter.embedding.android.FlutterActivity
@@ -50,6 +52,10 @@ class MainActivity : FlutterActivity() {
mStopService()
result.success(true)
}
+ "checkInput" ->{
+ checkInput()
+ result.success(true)
+ }
else -> {}
}
}
@@ -96,6 +102,25 @@ class MainActivity : FlutterActivity() {
}
}
+ private fun checkInput() {
+ AlertDialog.Builder(this)
+ .setCancelable(false)
+ .setTitle("检查Input服务")
+ .setMessage("请开启相关服务")
+ .setPositiveButton("Yes") { dialog, which ->
+ val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)
+ if (intent.resolveActivity(packageManager) != null) startActivityForResult(
+ intent,
+ 11
+ ) else AlertDialog.Builder(this)
+ .setTitle("错误")
+ .setMessage("无法启动服务")
+ .show()
+ }
+ .setNegativeButton("No") { dialog, which -> }
+ .show()
+ }
+
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK && data != null) {
diff --git a/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt b/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt
index 77b2f9c9e..1c6fba716 100644
--- a/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt
+++ b/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt
@@ -34,11 +34,11 @@ const val M_KEY_FRAME_RATE = 30
class MainService : Service() {
- fun rustGetRaw():ByteArray{
+ fun rustGetRaw(): ByteArray {
return rawByteArray!!
}
- external fun init(ctx:Context)
+ external fun init(ctx: Context)
init {
System.loadLibrary("rustdesk")
@@ -49,7 +49,7 @@ class MainService : Service() {
private var surface: Surface? = null
private val singleThread = Executors.newSingleThreadExecutor()
private var mEncoder: MediaCodec? = null
- private var rawByteArray :ByteArray? = null
+ private var rawByteArray: ByteArray? = null
override fun onBind(intent: Intent): IBinder? {
return null
@@ -90,7 +90,8 @@ class MainService : Service() {
return super.onStartCommand(intent, flags, startId)
}
- lateinit var mImageReader:ImageReader // * 注意 这里要成为成员变量,防止被回收 https://www.cnblogs.com/yongdaimi/p/11004560.html
+ lateinit var mImageReader: ImageReader // * 注意 这里要成为成员变量,防止被回收 https://www.cnblogs.com/yongdaimi/p/11004560.html
+
@SuppressLint("WrongConstant")
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
private fun startRecorder() {
@@ -100,23 +101,23 @@ class MainService : Service() {
mImageReader =
ImageReader.newInstance(FIXED_WIDTH, FIXED_HEIGHT, PixelFormat.RGBA_8888, 2) // 至少是2
mImageReader.setOnImageAvailableListener({ imageReader: ImageReader ->
- Log.d(logTag, "on image")
- try {
- imageReader.acquireLatestImage().use { image ->
- if (image == null) return@setOnImageAvailableListener
- val planes = image.planes
- val buffer = planes[0].buffer
- buffer.rewind()
- // 这里注意 处理不当会引发OOM
- if (rawByteArray == null){
- rawByteArray = ByteArray(buffer.capacity())
- buffer.get(rawByteArray!!)
- }else{
- buffer.get(rawByteArray!!)
- }
+// Log.d(logTag, "on image")
+ try {
+ imageReader.acquireLatestImage().use { image ->
+ if (image == null) return@setOnImageAvailableListener
+ val planes = image.planes
+ val buffer = planes[0].buffer
+ buffer.rewind()
+ // 这里注意 处理不当会引发OOM
+ if (rawByteArray == null) {
+ rawByteArray = ByteArray(buffer.capacity())
+ buffer.get(rawByteArray!!)
+ } else {
+ buffer.get(rawByteArray!!)
}
- } catch (ignored: java.lang.Exception) {
}
+ } catch (ignored: java.lang.Exception) {
+ }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
imageReader.discardFreeBuffers()
}
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
new file mode 100644
index 000000000..9acb4104b
--- /dev/null
+++ b/android/app/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+ RustDesk
+ 测试服务 输入服务
+
\ No newline at end of file
diff --git a/android/app/src/main/res/xml/accessibility_service_config.xml b/android/app/src/main/res/xml/accessibility_service_config.xml
new file mode 100644
index 000000000..fa9407128
--- /dev/null
+++ b/android/app/src/main/res/xml/accessibility_service_config.xml
@@ -0,0 +1,6 @@
+
diff --git a/android/build.gradle b/android/build.gradle
index 110174e8d..18592b640 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -7,7 +7,7 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:4.1.0'
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10"
classpath 'com.google.gms:google-services:4.3.3'
}
}
diff --git a/lib/home_page.dart b/lib/home_page.dart
index 70f444703..8d5cde352 100644
--- a/lib/home_page.dart
+++ b/lib/home_page.dart
@@ -100,7 +100,8 @@ class _HomePageState extends State {
getPeers(),
ElevatedButton(onPressed:_toAndroidGetPer, child: Text("获取权限事件")),
ElevatedButton(onPressed:_toAndroidStartSer, child: Text("开启录屏服务")),
- ElevatedButton(onPressed:_toAndroidStopSer, child: Text("停止录屏服务"))
+ ElevatedButton(onPressed:_toAndroidStopSer, child: Text("停止录屏服务")),
+ ElevatedButton(onPressed:_toAndroidCheckInput, child: Text("检查输入权限")),
]),
));
}
@@ -116,6 +117,10 @@ class _HomePageState extends State {
bool res = await toAndroidChannel.invokeMethod("stopSer");
debugPrint("_toAndroidStopSer:$res");
}
+ Future _toAndroidCheckInput() async{
+ bool res = await toAndroidChannel.invokeMethod("checkInput");
+ debugPrint("_toAndroidStopSer:$res");
+}
void onConnect() {
var id = _idController.text.trim();