diff options
| author | Lena <lena@omega> | 2026-01-01 00:00:00 +0000 |
|---|---|---|
| committer | Lena <lena@omega> | 2026-06-24 22:14:50 +0300 |
| commit | eb0c8951196c637e44daf3c0617b131b997d5d2c (patch) | |
| tree | 2f83b6a41cee745467e53fc401942b82cea286ea /vendor/libadb-android/README.md | |
| download | scrcpy-android-0.1.tar.gz | |
scrcpy-android: mirror an Android device over wireless ADB0.1
Native Java app for Android 12+ that mirrors another Android
device over wireless ADB, forwarding video, audio, touch input,
and clipboard. Bundles a pinned scrcpy-server.jar and the
vendored libadb-android stack. Supports h264/h265/av1 video and
raw/opus audio with in-app codec selection. No NDK, no Kotlin.
Includes JVM unit tests and a Docker-based emulator e2e rig.
Diffstat (limited to 'vendor/libadb-android/README.md')
| -rw-r--r-- | vendor/libadb-android/README.md | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/vendor/libadb-android/README.md b/vendor/libadb-android/README.md new file mode 100644 index 0000000..815cf46 --- /dev/null +++ b/vendor/libadb-android/README.md @@ -0,0 +1,199 @@ +# LibADB Android + +ADB library for Android. It enables an app to connect to the ADB daemon (`adbd` process) belonging to the same or a +different device and execute arbitrary services or commands (via `shell:` service). + +**Disclaimer:** This library has never gone through a security audit. Please, proceed with caution if security is +crucial for your app. Avoid using the APIs for reasons other than connecting or using ADB. For the safety of your app +and its users, open a remote service instead of using ADB and ask the user to disconnect Wireless debugging. + +## Getting Started +### Adding Dependencies +LibADB Android is available via JitPack. + +```groovy +// Top level build file +repositories { + mavenCentral() + maven { url "https://jitpack.io" } +} + +// Add to dependencies section +dependencies { + // Add this library + implementation 'com.github.MuntashirAkon:libadb-android:3.1.1' + + // Library to generate X509Certificate. You can also use BouncyCastle for + // this. See example for use-case. + // implementation 'com.github.MuntashirAkon:sun-security-android:1.1' + + // Bypass hidden API if you want to use the Android default Conscrypt in + // Android 9 (Pie) or later. It also requires additional steps. See + // https://github.com/LSPosed/AndroidHiddenApiBypass to find out more about + // this. + // implementation 'org.lsposed.hiddenapibypass:hiddenapibypass:6.1' + + // Use custom Conscrypt library. If you want to connect to a remote ADB + // daemon instead of the device the app is currently running or do not want + // to bypass hidden API, this is the recommended choice. + implementation 'org.conscrypt:conscrypt-android:2.5.3' +} +``` + +If you're using the custom Conscrypt library in order to connect to a remote ADB daemon and the app targets Android +version below 4.4, you have to extend `android.app.Application` to apply fixes for the random number generation: +```java +public class MyAwesomeApp extends Application { + @Override + public void onCreate() { + super.onCreate(); + // Fix random number generation in Android versions below 4.4. + PRNGFixes.apply(); + } + + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(base); + // Uncomment the following line if you want to bypass hidden API as + // described above. + // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + // HiddenApiBypass.addHiddenApiExemptions("L"); + // } + } +} +``` + +**Notice:** Conscrypt supports only API 9 (Gingerbread) or later, meaning you cannot use ADB pairing or any TLSv1.3 +features in API less than 9. The corresponding methods are already annotated properly. So, you don't have to worry about +compatibility issues that may arise when your app's minimum SDK is set to one of the unsupported versions. + +### Configuring ADB +Instead of doing everything manually, you can create a concrete implementation of the `AbsAdbConnectionManager` class. +Example: + +```java +public class AdbConnectionManager extends AbsAdbConnectionManager { + private static AbsAdbConnectionManager INSTANCE; + + public static AbsAdbConnectionManager getInstance() throws Exception { + if (INSTANCE == null) { + INSTANCE = new AdbConnectionManager(); + } + return INSTANCE; + } + + private PrivateKey mPrivateKey; + private Certificate mCertificate; + + private AdbConnectionManager() throws Exception { + // Set the API version whose `adbd` is running + setApi(Build.VERSION.SDK_INT); + // TODO: Load private key and certificate (along with public key) from + // some place such as KeyStore or file system. + mPrivateKey = ...; + mCertificate = ...; + if (mPrivateKey == null) { + // Generate a new key pair + int keySize = 2048; + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + keyPairGenerator.initialize(keySize, SecureRandom.getInstance("SHA1PRNG")); + KeyPair generateKeyPair = keyPairGenerator.generateKeyPair(); + PublicKey publicKey = generateKeyPair.getPublic(); + mPrivateKey = generateKeyPair.getPrivate(); + // Generate a certificate + // On Android, it requires sun.security-android library as mentioned + // above. + String subject = "CN=My Awesome App"; + String algorithmName = "SHA512withRSA"; + long expiryDate = System.currentTimeMillis() + 86400000; + CertificateExtensions certificateExtensions = new CertificateExtensions(); + certificateExtensions.set("SubjectKeyIdentifier", new SubjectKeyIdentifierExtension( + new KeyIdentifier(publicKey).getIdentifier())); + X500Name x500Name = new X500Name(subject); + Date notBefore = new Date(); + Date notAfter = new Date(expiryDate); + certificateExtensions.set("PrivateKeyUsage", new PrivateKeyUsageExtension(notBefore, notAfter)); + CertificateValidity certificateValidity = new CertificateValidity(notBefore, notAfter); + X509CertInfo x509CertInfo = new X509CertInfo(); + x509CertInfo.set("version", new CertificateVersion(2)); + x509CertInfo.set("serialNumber", new CertificateSerialNumber(new Random().nextInt() & Integer.MAX_VALUE)); + x509CertInfo.set("algorithmID", new CertificateAlgorithmId(AlgorithmId.get(algorithmName))); + x509CertInfo.set("subject", new CertificateSubjectName(x500Name)); + x509CertInfo.set("key", new CertificateX509Key(publicKey)); + x509CertInfo.set("validity", certificateValidity); + x509CertInfo.set("issuer", new CertificateIssuerName(x500Name)); + x509CertInfo.set("extensions", certificateExtensions); + X509CertImpl x509CertImpl = new X509CertImpl(x509CertInfo); + x509CertImpl.sign(mPrivateKey, algorithmName); + mCertificate = x509CertImpl; + // TODO: Store the key pair to some place else. + } + } + + @NonNull + @Override + protected PrivateKey getPrivateKey() { + return mPrivateKey; + } + + @NonNull + @Override + protected Certificate getCertificate() { + return mCertificate; + } + + @NonNull + @Override + protected String getDeviceName() { + return "MyAwesomeApp"; + } +} +``` + +### Connecting to ADB + +You can connect to ADB in several ways from the `AbsAdbConnectionManager`: + +| Method | Description | +|---------------------------------|---------------------------------------------------------------------------------------------------------------| +| `connect(host, port)` | Connect using a host address and a port number | +| `connect(port)` | Connect using a host address set by `setHostAddress()` and a port number | +| `connectTcp(Context, timeout)` | (SDK 16+) Discover host address and port number automatically for ADB over TCP and connect to it | +| `connectTls(Context, timeout)` | (SDK 16+) Discover host address and port number automatically for TLS (from Android 9) and connect to it | +| `autoConnect(Context, timeout)` | (SDK 16+) Discover host address and port number automatically for both ADB over TCP and TLS and connect to it | + +### Wireless Debugging +Internally, ADB over TCP and Wireless Debugging are very similar except Wireless Debugging requires an extra step of +_pairing_ the device. In order to pair a new device, you can simply invoke `AdbConnectionManager.getInstance().pair(host, port, pairingCode)`. +After the pairing, you can connect to ADB via the usual `connect()` methods without any additional steps. + +### Opening ADB Shell for Executing Arbitrary Commands +Simply use `AdbConnectionManager.getInstance().openStream("shell:")`. This will return an `AdbStream` which can be used +to read/write to the ADB shell via `AdbStream#openInputStream()` and `AdbStream#openOutputStream()` methods +respectively like a normal Java `Process`. While it is possible to read/write in the same thread (first write and then +read), this is not recommended because the shell might be stuck indefinitely for commands such as `top`. + +**NOTE:** If you want to create a full-featured terminal emulator, this approach isn't recommended. Instead, you should +create a remote service via `app_process` or start an SSH server and connect to it. + +### Other services +You can also use other services via the `AdbConnectionManager#openStream()` methods. See [SERVICES.md](./SERVICES.md) +for more information. + +## For Java (non-Android) Projects +It is possible to modify this library to work on non-Android project. But it isn't supported because Spake2-Java only +provides stable releases for Android. However, you can incorporate this library in your project by manually compiling +Spake2 library for your platforms. + +## Contributing +By contributing to this project, you permit your work to be released under the terms of GNU General Public License, +Version 3 or later **or** Apache License, Version 2.0. + +## License +Copyright 2021 © Muntashir Al-Islam + +Dual licensed under the terms of [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html) or +[Apache-2.0 license](https://www.apache.org/licenses/LICENSE-2.0.html). Use whatever license you need for your project. + +_Note regarding the Apache-2.0 license, this library has an LGPL dependency which may go against the policy of some +organizations such as ASF._ |