update now can connect adb but scrcpy still bug

This commit is contained in:
Kenta420 2024-01-22 12:50:07 +07:00
parent 45851422f7
commit a95c350844
10 changed files with 116 additions and 132 deletions

View file

@ -28,5 +28,6 @@ module.exports = {
{ allowConstantExport: true }, { allowConstantExport: true },
], ],
"@typescript-eslint/consistent-type-imports": "error", "@typescript-eslint/consistent-type-imports": "error",
"react-hooks/exhaustive-deps": "off",
}, },
} }

View file

@ -5,5 +5,6 @@
"bracketSpacing": true, "bracketSpacing": true,
"arrowParens": "avoid", "arrowParens": "avoid",
"endOfLine": "lf", "endOfLine": "lf",
"tabWidth": 2 "tabWidth": 2,
"proseWrap": "preserve"
} }

View file

@ -1,19 +0,0 @@
// import type { AdbDaemonWebUsbDevice } from '@yume-chan/adb-daemon-webusb'
// import { AdbDaemonWebUsbDeviceManager } from '@yume-chan/adb-daemon-webusb'
import { webusb } from 'usb'
// const WebUsb: WebUSB = new WebUSB({ allowAllDevices: true })
// const Manager: AdbDaemonWebUsbDeviceManager = new AdbDaemonWebUsbDeviceManager(
// WebUsb
// )
export function getDevices() {
// const devices: AdbDaemonWebUsbDevice[] = await Manager.getDevices()
// if (!devices.length) {
// alert('No device connected')
// }
webusb.requestDevice({ filters: [] }).then(device => {
console.log(device)
})
}

View file

@ -1,6 +1,6 @@
const Header: React.FC = () => { const Header: React.FC = () => {
return ( return (
<header className="fixed bg-black w-full z-0 px-4 shadow-sm shadow-slate-500/40 pl-[20rem]"> <header className="fixed bg-black w-full z-40 px-4 shadow-sm shadow-slate-500/40 pl-[20rem]">
<h2>Header</h2> <h2>Header</h2>
</header> </header>
) )

View file

@ -1,3 +1,4 @@
import { type Adb } from '@yume-chan/adb'
import { import {
type AdbDaemonWebUsbDevice, type AdbDaemonWebUsbDevice,
AdbDaemonWebUsbDeviceManager AdbDaemonWebUsbDeviceManager
@ -5,14 +6,18 @@ import {
import { create } from 'zustand' import { create } from 'zustand'
interface ADB { interface ADB {
adb: Adb | undefined
manager: AdbDaemonWebUsbDeviceManager | undefined manager: AdbDaemonWebUsbDeviceManager | undefined
device: AdbDaemonWebUsbDevice | undefined device: AdbDaemonWebUsbDevice | undefined
setAdb: (adb: Adb | undefined) => void
setDevice: (device: AdbDaemonWebUsbDevice | undefined) => void setDevice: (device: AdbDaemonWebUsbDevice | undefined) => void
} }
const useAdb = create<ADB>(set => ({ const useAdb = create<ADB>(set => ({
adb: undefined,
manager: AdbDaemonWebUsbDeviceManager.BROWSER, manager: AdbDaemonWebUsbDeviceManager.BROWSER,
device: undefined, device: undefined,
setAdb: adb => set({ adb }),
setDevice: device => set({ device }) setDevice: device => set({ device })
})) }))

View file

@ -33,7 +33,7 @@ const MainLayout = () => {
<div> <div>
<Sidebar /> <Sidebar />
<Header /> <Header />
<main className="fixed pt-14 px-4 pl-[21rem]"> <main className="fixed pt-[5rem] pl-[21rem]">
<Outlet /> <Outlet />
</main> </main>
</div> </div>

View file

@ -2,176 +2,172 @@ import { useShallow } from 'zustand/react/shallow'
import { ADB_DEFAULT_DEVICE_FILTER } from '@yume-chan/adb-daemon-webusb' import { ADB_DEFAULT_DEVICE_FILTER } from '@yume-chan/adb-daemon-webusb'
import AdbWebCredentialStore from '@yume-chan/adb-credential-web' import AdbWebCredentialStore from '@yume-chan/adb-credential-web'
import { Adb, AdbDaemonTransport } from '@yume-chan/adb' import { Adb, AdbDaemonTransport } from '@yume-chan/adb'
import useAdb from '../hooks/adb' import useAdb from '../hooks/useAdb'
import type { AdbScrcpyVideoStream } from '@yume-chan/adb-scrcpy' import type { AdbScrcpyVideoStream } from '@yume-chan/adb-scrcpy'
import { AdbScrcpyClient, AdbScrcpyOptions2_1 } from '@yume-chan/adb-scrcpy' import { AdbScrcpyClient, AdbScrcpyOptions2_1 } from '@yume-chan/adb-scrcpy'
import { WebCodecsDecoder } from '@yume-chan/scrcpy-decoder-webcodecs' import { WebCodecsDecoder } from '@yume-chan/scrcpy-decoder-webcodecs'
import { import {
ScrcpyLogLevel1_18, ScrcpyLogLevel1_18,
ScrcpyOptions2_1, ScrcpyOptions2_2,
ScrcpyVideoCodecId ScrcpyVideoCodecId
} from '@yume-chan/scrcpy' } from '@yume-chan/scrcpy'
import { useState } from 'react' import { useCallback, useRef, useState } from 'react'
import {
const ScreenStream: React.FC<{ child: HTMLCanvasElement }> = ({ ReadableStream,
child WritableStream,
}: { Consumable,
child: HTMLCanvasElement DecodeUtf8Stream
}) => { } from '@yume-chan/stream-extra'
return <div ref={ref => ref?.appendChild(child)}></div> import { useBeforeUnload } from 'react-router-dom'
}
const AndroidPage: React.FC = () => { const AndroidPage: React.FC = () => {
const { manager, device, setDevice } = useAdb( const { adb, manager, device, setAdb, setDevice } = useAdb(
useShallow(state => ({ useShallow(state => ({
adb: state.adb,
manager: state.manager, manager: state.manager,
device: state.device, device: state.device,
setAdb: state.setAdb,
setDevice: state.setDevice setDevice: state.setDevice
})) }))
) )
const [decoder, setDecoder] = useState<WebCodecsDecoder | undefined>() async function createNewConnection() {
const [client, setClient] = useState<AdbScrcpyClient | undefined>()
const [adbClient, setAdbClient] = useState<Adb | undefined>(undefined)
function attachDevice() {
manager
?.requestDevice({
filters: [
{
...ADB_DEFAULT_DEVICE_FILTER,
vendorId: 1478
}
]
})
.then(selectedDevice => {
if (!selectedDevice) {
return
} else {
setDevice(selectedDevice)
}
})
}
function disConnectDevice() {
device?.raw.forget() device?.raw.forget()
setDevice(undefined) setDevice(undefined)
} const selectedDevice = await manager?.requestDevice({
filters: [
{
...ADB_DEFAULT_DEVICE_FILTER,
serialNumber: 'd'
}
]
})
// function reboot() { if (!selectedDevice) {
// device?.connect().then(connection => { return
// const credentialStore: AdbWebCredentialStore = new AdbWebCredentialStore() } else {
setDevice(selectedDevice)
}
// AdbDaemonTransport.authenticate({ const connection = await selectedDevice.connect()
// serial: device?.serial,
// connection,
// credentialStore: credentialStore
// }).then(transport => {
// const adb: Adb = new Adb(transport)
// adb.power.reboot().then(() => {
// console.log('reboot success')
// })
// })
// })
// }
async function scrcpyConnect() {
// const url = new URL('../bin/scrcpy-server.bin', import.meta.url)
// const server: ArrayBuffer = await fetch(url).then(res => res.arrayBuffer())
const connection = await device?.connect()
const credentialStore: AdbWebCredentialStore = new AdbWebCredentialStore() const credentialStore: AdbWebCredentialStore = new AdbWebCredentialStore()
const transport = await AdbDaemonTransport.authenticate({ const transport = await AdbDaemonTransport.authenticate({
serial: device!.serial, serial: selectedDevice.serial,
connection: connection!, connection: connection,
credentialStore: credentialStore credentialStore: credentialStore
}) })
const adb: Adb = new Adb(transport) const adb: Adb = new Adb(transport)
setAdbClient(adb) setAdb(adb)
// await AdbScrcpyClient.pushServer( }
// adb,
// new ReadableStream({
// start(controller) {
// controller.enqueue(new Consumable(new Uint8Array(server)))
// controller.close()
// }
// })
// )
await adb.subprocess.spawn( const [client, setClient] = useState<AdbScrcpyClient | undefined>()
'CLASSPATH=/data/local/tmp/scrcpy-server.jar app_process / com.genymobile.scrcpy.Server 2.1' const [decoder, setDecoder] = useState<WebCodecsDecoder | undefined>()
const screenRef = useRef<HTMLDivElement>(null)
// when user close or refresh the page, close the adb connection
useBeforeUnload(
useCallback(() => {
client?.close()
adb?.close()
device?.raw.forget()
}, [])
)
async function scrcpyConnect() {
const server: ArrayBuffer = await fetch(
new URL('../scrcpy/scrcpy_server_v2.2', import.meta.url)
).then(res => res.arrayBuffer())
await AdbScrcpyClient.pushServer(
adb!,
new ReadableStream({
start(controller) {
controller.enqueue(new Consumable(new Uint8Array(server)))
controller.close()
}
})
) )
const scrcpyOption = new ScrcpyOptions2_1({ const res = await adb!.subprocess.spawn(
'CLASSPATH=/data/local/tmp/scrcpy-server.jar app_process / com.genymobile.scrcpy.Server 2.2'
)
res.stdout.pipeThrough(new DecodeUtf8Stream()).pipeTo(
new WritableStream({
write(chunk) {
console.log(chunk)
}
})
)
const scrcpyOption = new ScrcpyOptions2_2({
audio: false, audio: false,
maxFps: 60, maxFps: 60,
control: false, control: false,
video: true, video: true,
logLevel: ScrcpyLogLevel1_18.Debug, logLevel: ScrcpyLogLevel1_18.Debug,
videoCodec: 'h264',
stayAwake: true, stayAwake: true,
cleanup: true cleanup: true
}) })
const _client = await AdbScrcpyClient.start( const _client = await AdbScrcpyClient.start(
adb, adb!,
'/data/local/tmp/scrcpy-server.jar', '/data/local/tmp/scrcpy-server.jar',
'2.1', '2.2',
new AdbScrcpyOptions2_1(scrcpyOption) new AdbScrcpyOptions2_1(scrcpyOption)
) )
const videoStream: AdbScrcpyVideoStream | undefined =
await _client?.videoStream
const _decoder = new WebCodecsDecoder(ScrcpyVideoCodecId.H264)
screenRef.current?.appendChild(_decoder.renderer)
videoStream?.stream.pipeTo(_decoder.writable)
setDecoder(_decoder)
setClient(_client) setClient(_client)
} }
async function scrcpyStream() { function disconnectAdb() {
const videoStream: AdbScrcpyVideoStream | undefined = client?.close()
await client?.videoStream adb?.close()
const _decoder = new WebCodecsDecoder(ScrcpyVideoCodecId.H264) setClient(undefined)
videoStream?.stream.pipeTo(_decoder.writable) setAdb(undefined)
setDecoder(_decoder)
} }
function scrcpyDisconnect() { function scrcpyDisconnect() {
decoder?.dispose()
client?.close() client?.close()
setClient(undefined) setClient(undefined)
setDecoder(undefined) setDecoder(undefined)
} }
function rebootDevice() { function rebootDevice() {
adbClient?.power.reboot() adb?.power.reboot()
} }
return ( return (
<div> <>
<h1>This is Android Page!!!!!!!</h1> <div className="grid grid-cols-2 gap-4">
{device ? <h2>Device: {device.name}</h2> : <h2>No Device</h2>} <div className="flex flex-col">
<div className="flex flex-row"> <button
<button className="btn btn-primary" onClick={attachDevice}> className="btn btn-primary"
Attach Device onClick={adb ? disconnectAdb : createNewConnection}
</button> >
<button className="btn btn-primary" onClick={disConnectDevice}> {adb ? 'Disconnect' : 'Connect'}
Disconnect Device </button>
</button> <button
<button className="btn btn-primary" onClick={rebootDevice}> className="btn btn-primary"
Reboot Device onClick={adb && !client ? scrcpyConnect : scrcpyDisconnect}
</button> >
{client ? 'Disconnect' : 'Connect'}
</button>
{adb ? <button onClick={rebootDevice}>Reboot</button> : ''}
</div>
<div className="bg-white">{adb && device ? device.name : ''}</div>
</div> </div>
<div className="flex flex-row"> <div ref={screenRef}></div>
<button className="btn btn-primary" onClick={scrcpyConnect}> </>
Scrcpy Connect
</button>
<button className="btn btn-primary" onClick={scrcpyStream}>
Scrcpy Stream
</button>
<button className="btn btn-primary" onClick={scrcpyDisconnect}>
Scrcpy Disconnect
</button>
</div>
{decoder ? <ScreenStream child={decoder.renderer} /> : ''}
</div>
) )
} }

Binary file not shown.

Binary file not shown.