Skip to content

Commit

Permalink
更新V12.0
Browse files Browse the repository at this point in the history
大:
支持设置默认设备
支持修改悬浮球大小
重写adb库,提高响应速度,减少占用
完善专注模式
修改软件配色
完善设置功能
小:
修复退出后仍然高占用的bug
使用同步解码,修复高占用bug
加快启动速度
修复某些设备游戏空间无法更新画面问题(可能)
修复导出密钥问题
完善配置导出导入
  • Loading branch information
mingzhixian committed Jul 8, 2023
1 parent 4e027a2 commit 5de2481
Show file tree
Hide file tree
Showing 33 changed files with 756 additions and 593 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ scrcpy_android/app/debug
scrcpy_android/captures
scrcpy_android/.externalNativeBuild
scrcpy_android/.cxx
scrcpy_android/app/.cxx
scrcpy_android/local.properties
scrcpy_android/app/src/main/assets/scrcpy-server.jar
scrcpy_android/app/src/main/res/raw/scrcpy-server.jar
Expand All @@ -34,4 +35,5 @@ scrcpy_back/app/debug
scrcpy_back/captures
scrcpy_back/.externalNativeBuild
scrcpy_back/.cxx
scrcpy_back/app/.cxx
scrcpy_back/local.properties
2 changes: 1 addition & 1 deletion HOW_TO_USE.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ adb tcpip 5555
- 设备全屏控制后使用悬浮导航球导航,单击为返回、双击为桌面、长按为更多,悬浮球可拖动。
4. 小窗模式使用
- 可通过拖动横条移动小窗。
- 双击横条可进入全屏控制(进入全屏后只能断开连接,无法再恢复小窗模式)
- 点击左上角全屏按钮可进入全屏状态
- 点击右上角红点可关闭投屏。
- 拖动右下角白点可等比更改小窗大小。
5. 小小窗模式使用
Expand Down
13 changes: 1 addition & 12 deletions scrcpy_android/.idea/deploymentTargetDropDown.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion scrcpy_android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ android {

defaultConfig {
applicationId "top.saymzx.scrcpy.android"
minSdk 24
minSdk 23
targetSdk 33
versionCode 120
versionName "12.0"
Expand All @@ -19,6 +19,9 @@ android {
abiFilters "arm64-v8a" , "x86"
}
}
viewBinding {
enabled = true
}
buildTypes {
release {
ndk {
Expand Down
124 changes: 78 additions & 46 deletions scrcpy_android/app/src/main/java/top/saymzx/scrcpy/adb/Adb.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package top.saymzx.scrcpy.adb

import okhttp3.internal.notifyAll
import okhttp3.internal.wait
import okio.Buffer
import okio.sink
import okio.source
import java.io.IOException
import java.io.InputStream
import java.net.Socket
import java.nio.charset.StandardCharsets
import java.util.Random

class Adb(host: String, port: Int, keyPair: AdbKeyPair) {
Expand All @@ -12,9 +17,8 @@ class Adb(host: String, port: Int, keyPair: AdbKeyPair) {
private val adbWriter: AdbWriter
private val adbReader: AdbReader
private val random = Random()
private val maxPayloadSize: Int
private val connectionStreams = HashMap<Int, AdbStream>()
private val connectionStatus = HashMap<Int, Int>() // 0为断开,1为等待回复中,2为读写中
private var defaultShellStream: AdbStream? = null

init {
// 连接socket
Expand All @@ -37,79 +41,103 @@ class Adb(host: String, port: Int, keyPair: AdbKeyPair) {
// 认证失败
if (message.command != Constants.CMD_CNXN) throw IOException("Connection failed: $message")
// 最大承载长度
maxPayloadSize = message.arg1
adbWriter.maxPayloadSize = message.arg1
// 开始读写线程
Thread { readAdb() }.start()
}

// 打开一个连接流
fun open(destination: String): AdbStream {
fun open(destination: String, isNeedSource: Boolean): AdbStream {
val localId = random.nextInt()
adbWriter.writeOpen(localId, destination)
connectionStatus[localId] = 1
val stream = AdbStream(maxPayloadSize, adbWriter)
stream.localId = localId
val stream = AdbStream(localId, adbWriter, isNeedSource)
connectionStreams[localId] = stream
// 等待2秒
for (i in 0..200) {
when (connectionStatus[localId]) {
2 -> {
return stream
}

else -> {
Thread.sleep(10)
}
}
synchronized(stream) {
stream.wait()
}
throw IOException("连接错误")
if (stream.status == -1) throw IOException("连接错误")
else return stream
}

fun runAdbCmd(cmd: String): String {
val stream = open("shell:$cmd")
// 等待4秒
for (i in 0..200) {
if (connectionStatus[stream.localId] == 0) {
return stream.source.readUtf8()
} else {
Thread.sleep(20)
}
fun pushFile(file: InputStream, remotePath: String) {
val pushStream = open("sync:", true)
val remote = "$remotePath,${33206}"
pushStream.write(writePacket("SEND", remote.length))
pushStream.write(remote.toByteArray())
val byteArray = ByteArray(adbWriter.maxPayloadSize - 512)
while (true) {
val len = file.read(byteArray, 0, byteArray.size)
if (len == -1) break
pushStream.write(writePacket("DATA", len))
pushStream.write(byteArray.sliceArray(0..len))
}
return ""
pushStream.write(writePacket("DONE", (System.currentTimeMillis() / 1000).toInt()))
pushStream.readByte()
pushStream.write(writePacket("QUIT", 0))
}

private fun writePacket(id: String, arg: Int): ByteArray {
val tmpBuffer = Buffer()
tmpBuffer.clear()
tmpBuffer.writeString(id, StandardCharsets.UTF_8)
tmpBuffer.writeIntLe(arg)
return tmpBuffer.readByteArray()
}

fun tcpForward(port: Int): AdbStream {
val stream = open("tcp:$port")
// 等待4秒
for (i in 0..200) {
if (connectionStatus[stream.localId] == 2) {
return stream
} else {
Thread.sleep(20)
fun runAdbCmd(cmd: String, isNeedOutput: Boolean): String {
if (!isNeedOutput) {
if (defaultShellStream == null) defaultShellStream = open("shell:", false)
defaultShellStream!!.write((cmd + "\n").toByteArray())
return ""
} else {
val stream = open("shell:$cmd", true)
// 等待8秒
for (i in 0..200) {
if (stream.status == -1) {
return stream.source.readUtf8()
} else {
Thread.sleep(40)
}
}
return "命令运行超过8秒,未获取命令输出"
}
throw IOException("连接错误")
}

fun tcpForward(port: Int, isNeedSource: Boolean): AdbStream = open("tcp:$port", isNeedSource)

// 读取线程
private fun readAdb() {
try {
while (true) {
val message = adbReader.readMessage()
val stream = connectionStreams[message.arg1]!!
when (message.command) {
Constants.CMD_OKAY -> {
if (connectionStreams[message.arg1]!!.remoteId == 0)
connectionStreams[message.arg1]!!.remoteId = message.arg0
connectionStreams[message.arg1]?.push(message.payload)
connectionStatus[message.arg1] = 2
stream.status = 2
// 连接成功
if (stream.remoteId == 0) {
stream.remoteId = message.arg0
synchronized(stream) {
stream.notifyAll()
}
}
// 可读写
synchronized(stream.canWrite) {
stream.canWrite.notify()
}
}

Constants.CMD_WRTE -> {
adbWriter.writeOkay(message.arg1, message.arg0)
connectionStreams[message.arg1]?.push(message.payload)
stream.pushToSource(message.payload)
}

Constants.CMD_CLSE -> {
// 连接断开
stream.status = -1
synchronized(stream) {
stream.notifyAll()
}
}
}
}
Expand All @@ -119,8 +147,12 @@ class Adb(host: String, port: Int, keyPair: AdbKeyPair) {
}

fun close() {
adbReader.close()
adbWriter.close()
socket.close()
try {
defaultShellStream?.close()
adbReader.close()
adbWriter.close()
socket.close()
} catch (_: Exception) {
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@

package top.saymzx.scrcpy.adb

import okio.Buffer
import okio.BufferedSource
import java.nio.charset.StandardCharsets

internal class AdbMessage(
val command: Int,
val arg0: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

package top.saymzx.scrcpy.adb

import android.util.Log
import okio.Source
import okio.buffer

Expand Down
80 changes: 51 additions & 29 deletions scrcpy_android/app/src/main/java/top/saymzx/scrcpy/adb/AdbStream.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,51 +17,73 @@

package top.saymzx.scrcpy.adb

import okhttp3.internal.notify
import okhttp3.internal.wait
import okio.Buffer
import okio.Sink
import okio.Source
import okio.Timeout
import okio.buffer

class AdbStream(
private val localId: Int,
private val maxPayloadSize: Int,
private val adbWriter: AdbWriter
private val adbWriter: AdbWriter,
private val isNeedSource: Boolean
) {

var remoteId = 0

private var sourceBuffer = Buffer()
// -1为已关闭,0为连接中,1为等待恢复,2为可读写
var status = 0

fun push(byteArray: ByteArray) {
sourceBuffer.write(byteArray)
}
// 可写
val canWrite = Object()

val source = object : Source {
val source = Buffer()

override fun read(sink: Buffer, byteCount: Long): Long {
val tmp = ByteArray(byteCount.toInt())
val len = sourceBuffer.read(tmp, 0, byteCount.toInt())
sink.write(tmp, 0, maxOf(len, 0))
return len.toLong()
fun pushToSource(byteArray: ByteArray) {
if (isNeedSource) {
source.write(byteArray)
synchronized(source) {
source.notify()
}
}
}

override fun close() {}
fun write(byteArray: ByteArray) {
if (status == -1) return
else if (status != 2) synchronized(canWrite) {
canWrite.wait()
}
status = 1
adbWriter.writeWrite(localId, remoteId, byteArray, 0, byteArray.size)
}

override fun timeout() = Timeout.NONE
}.buffer()
fun close() {
status = -1
adbWriter.writeClose(localId, remoteId)
}

val sink = object : Sink {
fun readInt(): Int {
require(4)
return source.readInt()
}

override fun write(source: Buffer, byteCount: Long) {
adbWriter.writeWrite()
sinkBuffer.write(source, byteCount)
}
fun readByte(): Byte {
require(1)
return source.readByte()
}

override fun close() {}
fun readByteArray(size: Int): ByteArray {
require(size.toLong())
return source.readByteArray(size.toLong())
}

override fun flush() {}
fun readLong(): Long {
require(8)
return source.readLong()
}

override fun timeout() = Timeout.NONE
}.buffer()
private fun require(byteCount: Long) {
while (true) {
if (!source.request(byteCount)) synchronized(source) {
source.wait()
} else break
}
}
}
Loading

0 comments on commit 5de2481

Please sign in to comment.