Skip to content

Commit 8bda609

Browse files
authored
Merge branch 'tytydraco:main' into main
2 parents 0726809 + 44b564e commit 8bda609

25 files changed

+404
-270
lines changed

OWNERS

Lines changed: 0 additions & 2 deletions
This file was deleted.

README.md

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,44 @@
11
# LADB
2+
23
A local ADB shell for Android!
34

45
# How does it work?
5-
LADB bundles an ADB server within the app libraries. Normally, this server cannot connect to the local device because it requires an active USB connection. However, Android's Wireless ADB Debugging feature allows the server and the client to speak to each other locally.
6-
7-
# Initial Setup:
8-
1. About -> Build Number -> Click 7 times
9-
2. Developer Settings -> Wireless ADB Debugging -> On
10-
3. Developer Settings -> ADB Debugging -> On
11-
12-
# Troubleshooting:
13-
If you encounter "device unauthorized" or "multiple devices connected", try this:
14-
1. Enable Airplane Mode
15-
2. Disconnect any USB devices
16-
3. Kill and restart LADB
17-
18-
Still not working? Try this:
19-
1. Close LADB completely
20-
2. Developer Settings -> Wireless ADB Debugging -> Off
21-
3. Developer Settings -> ADB Debugging -> Off
22-
4. Developer Settings -> Revoke authorizations
23-
5. Reboot
24-
6. Developer Settings -> Wireless ADB Debugging -> On
25-
7. Developer Settings -> ADB Debugging -> On
26-
8. Enable Airplane Mode
27-
9. Open LADB
28-
29-
# Credit
30-
Thanks to Surge1223 for compiling ADB for the ARM/ARM64 architecture.
6+
7+
LADB bundles an ADB server within the app libraries. Normally, this server cannot connect to the local device because it
8+
requires an active USB connection. However, Android's Wireless ADB Debugging feature allows the server and the client to
9+
speak to each other locally.
10+
11+
# Initial Setup
12+
13+
Use split-screen more or a pop-out window with LADB and Settings at the same time. This is because Android will
14+
invalidate the pairing information if the dialog gets dismissed. Add a Wireless Debugging connection, and copy the
15+
pairing code and port into LADB. Keep both windows open until the Settings dialog dismisses itself.
16+
17+
Here is a nice tutorial from XDA on how to do it: [link](https://www.xda-developers.com/debloat-your-phone-run-adb-shell-commands-no-root-no-pc/).
18+
19+
Here is a video tutorial: [link](https://www.youtube.com/shorts/v7hT6rMYqh4).
20+
21+
# Issues
22+
23+
LADB is sadly incompatible with Shizuku at the current moment. That means that if you have Shiuzuku installed, LADB will
24+
usually fail to connect properly. You must uninstall it and reboot to use LADB.
25+
26+
# Troubleshooting
27+
28+
Most errors can be fixed by clearing the app data for LADB, removing all Wireless Debugging connections from Settings,
29+
and rebooting.
3130

3231
# License
33-
While this project is GPLv3 licensed, I would like to add an additional parameter: please do not publish unofficial (user) LADB builds to the Google Play Store.
3432

35-
Still confused? Email me at [email protected].
33+
While this project is GPLv3 licensed, I would like to add a parameter: please do not publish unofficial (user) LADB
34+
builds to the Google Play Store.
35+
36+
# Support
37+
38+
Still confused? Email me at [email protected].
39+
40+
We also have a Telegram server here: https://t.me/ladb_support.
41+
42+
# Privacy Policy
43+
44+
LADB does not send any device data outside of the app. Your data is not collected or processed.

app/build.gradle

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,19 @@ plugins {
44
id 'com.google.android.gms.oss-licenses-plugin'
55
}
66

7+
78
android {
8-
compileSdk 31
9+
compileSdk 33
910

1011
defaultConfig {
1112
applicationId "com.draco.ladb"
1213
minSdk 26
13-
targetSdk 31
14-
versionCode 38
15-
versionName "2.0"
14+
targetSdk 33
15+
versionCode 39
16+
versionName "2.1"
1617

1718
ndk {
18-
abiFilters 'arm64-v8a', 'armeabi-v7a'
19+
abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
1920
}
2021
}
2122

@@ -24,6 +25,12 @@ android {
2425
minifyEnabled true
2526
shrinkResources true
2627
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
28+
29+
buildConfigField 'Boolean', 'ANTI_PIRACY', RELEASE_ANTIPIRACY
30+
}
31+
32+
debug {
33+
buildConfigField 'Boolean', 'ANTI_PIRACY', DEBUG_ANTIPIRACY
2734
}
2835
}
2936
compileOptions {
@@ -43,19 +50,20 @@ android {
4350
buildFeatures {
4451
viewBinding true
4552
}
53+
namespace 'com.draco.ladb'
4654
}
4755

4856
dependencies {
4957
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
50-
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2'
58+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
5159

52-
implementation 'androidx.core:core-ktx:1.8.0'
53-
implementation 'androidx.appcompat:appcompat:1.4.2'
60+
implementation 'androidx.core:core-ktx:1.9.0'
61+
implementation 'androidx.appcompat:appcompat:1.5.1'
5462
implementation 'androidx.preference:preference-ktx:1.2.0'
55-
implementation 'androidx.fragment:fragment-ktx:1.5.0'
56-
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.0'
57-
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.0'
58-
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.0'
63+
implementation 'androidx.fragment:fragment-ktx:1.5.3'
64+
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
65+
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.1'
66+
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
5967

6068
implementation 'com.github.javiersantos:PiracyChecker:1.2.8'
6169

app/src/main/AndroidManifest.xml

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,61 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:tools="http://schemas.android.com/tools"
4-
package="com.draco.ladb"
54
android:installLocation="internalOnly">
65

7-
<uses-feature android:name="android.software.leanback" android:required="false" />
8-
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
6+
<uses-feature
7+
android:name="android.software.leanback"
8+
android:required="false" />
9+
<uses-feature
10+
android:name="android.hardware.touchscreen"
11+
android:required="false" />
912

1013
<uses-permission android:name="android.permission.INTERNET" />
11-
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"
14+
<uses-permission
15+
android:name="android.permission.WRITE_SECURE_SETTINGS"
1216
tools:ignore="ProtectedPermissions" />
1317

1418
<application
19+
android:banner="@drawable/banner"
20+
android:extractNativeLibs="true"
1521
android:icon="@mipmap/ic_launcher"
1622
android:label="@string/app_name"
1723
android:roundIcon="@mipmap/ic_launcher_round"
1824
android:supportsRtl="true"
19-
android:theme="@style/Theme.LADB"
20-
android:extractNativeLibs="true"
21-
android:banner="@drawable/banner">
22-
<activity android:name=".views.MainActivity"
25+
android:theme="@style/Theme.LADB">
26+
<activity
27+
android:name=".views.MainActivity"
2328
android:exported="true">
2429
<intent-filter>
2530
<action android:name="android.intent.action.MAIN" />
31+
2632
<category android:name="android.intent.category.LAUNCHER" />
2733
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
2834
</intent-filter>
2935
<intent-filter>
3036
<action android:name="android.intent.action.SEND" />
3137
<category android:name="android.intent.category.DEFAULT" />
38+
3239
<data android:mimeType="text/x-sh" />
3340
<data android:mimeType="text/plain" />
3441
</intent-filter>
3542
</activity>
36-
<activity android:name=".views.HelpActivity" android:label="@string/more" />
37-
<activity android:name=".views.BookmarksActivity" android:label="@string/bookmarks" />
43+
<activity
44+
android:name=".views.PairActivity"
45+
android:label="@string/pair" />
46+
<activity
47+
android:name=".views.HelpActivity"
48+
android:label="@string/more" />
49+
<activity
50+
android:name=".views.BookmarksActivity"
51+
android:label="@string/bookmarks" />
3852

39-
<service android:name=".services.QSTile"
40-
android:label="@string/app_name"
53+
<service
54+
android:name=".services.QSTile"
55+
android:exported="true"
4156
android:icon="@drawable/ic_baseline_adb_24"
42-
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
43-
android:exported="true">
57+
android:label="@string/app_name"
58+
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
4459
<intent-filter>
4560
<action android:name="android.service.quicksettings.action.QS_TILE" />
4661
</intent-filter>

app/src/main/java/com/draco/ladb/fragments/HelpPreferenceFragment.kt

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,11 @@ class HelpPreferenceFragment : PreferenceFragmentCompat() {
3535

3636
override fun onPreferenceTreeClick(preference: Preference): Boolean {
3737
when (preference.key) {
38-
getString(R.string.reset_key) -> {
38+
getString(R.string.unpair_key) -> {
3939
val context = requireContext()
4040
PreferenceManager.getDefaultSharedPreferences(context).edit(commit = true) {
41-
clear()
41+
putBoolean(context.getString(R.string.paired_key), false)
4242
}
43-
44-
context.filesDir.deleteRecursively()
45-
context.cacheDir.deleteRecursively()
46-
4743
restartApp()
4844
}
4945

app/src/main/java/com/draco/ladb/recyclers/BookmarksRecyclerAdapter.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import androidx.preference.PreferenceManager
1111
import androidx.recyclerview.widget.RecyclerView
1212
import com.draco.ladb.R
1313

14-
class BookmarksRecyclerAdapter(val context: Context): RecyclerView.Adapter<BookmarksRecyclerAdapter.ViewHolder>() {
14+
class BookmarksRecyclerAdapter(context: Context) : RecyclerView.Adapter<BookmarksRecyclerAdapter.ViewHolder>() {
1515
private val list = sortedSetOf<String>()
1616
private val prefs = PreferenceManager.getDefaultSharedPreferences(context)
1717

@@ -65,7 +65,7 @@ class BookmarksRecyclerAdapter(val context: Context): RecyclerView.Adapter<Bookm
6565
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
6666
updateList(false)
6767
val view = LayoutInflater.from(parent.context)
68-
.inflate(R.layout.recycler_item, parent, false)
68+
.inflate(R.layout.recycler_item, parent, false)
6969
return ViewHolder(view)
7070
}
7171

app/src/main/java/com/draco/ladb/utils/ADB.kt

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ class ADB(private val context: Context) {
2121
const val OUTPUT_BUFFER_DELAY_MS = 100L
2222

2323
@SuppressLint("StaticFieldLeak")
24-
@Volatile private var instance: ADB? = null
24+
@Volatile
25+
private var instance: ADB? = null
2526
fun getInstance(context: Context): ADB = instance ?: synchronized(this) {
2627
instance ?: ADB(context).also { instance = it }
2728
}
@@ -86,26 +87,44 @@ class ADB(private val context: Context) {
8687

8788
if (autoShell) {
8889
/* Only do wireless debugging steps on compatible versions */
89-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
90-
if (secureSettingsGranted && !isWirelessDebuggingEnabled()) {
90+
if (secureSettingsGranted) {
91+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !isWirelessDebuggingEnabled()) {
9192
debug("Enabling wireless debugging...")
9293
Settings.Global.putInt(
9394
context.contentResolver,
9495
"adb_wifi_enabled",
9596
1
9697
)
98+
99+
Thread.sleep(3_000)
100+
} else if (!isUSBDebuggingEnabled()) {
101+
debug("Enabling USB debugging...")
102+
Settings.Global.putInt(
103+
context.contentResolver,
104+
Settings.Global.ADB_ENABLED,
105+
1
106+
)
107+
97108
Thread.sleep(3_000)
98109
}
110+
}
99111

100-
/* Check again... */
101-
if (!isWirelessDebuggingEnabled()) {
102-
debug("Wireless debugging is not enabled!")
103-
debug("Settings -> Developer options -> Wireless debugging")
104-
debug("Waiting for wireless debugging...")
112+
/* Check again... */
113+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !isWirelessDebuggingEnabled()) {
114+
debug("Wireless debugging is not enabled!")
115+
debug("Settings -> Developer options -> Wireless debugging")
116+
debug("Waiting for wireless debugging...")
105117

106-
while (!isWirelessDebuggingEnabled()) {
107-
Thread.sleep(1_000)
108-
}
118+
while (!isWirelessDebuggingEnabled()) {
119+
Thread.sleep(1_000)
120+
}
121+
} else if (!isUSBDebuggingEnabled()) {
122+
debug("USB debugging is not enabled!")
123+
debug("Settings -> Developer options -> USB debugging")
124+
debug("Waiting for USB debugging...")
125+
126+
while (!isUSBDebuggingEnabled()) {
127+
Thread.sleep(1_000)
109128
}
110129
}
111130

@@ -116,10 +135,9 @@ class ADB(private val context: Context) {
116135
val waitProcess = adb(false, listOf("wait-for-device")).waitFor(2, TimeUnit.MINUTES)
117136
if (!waitProcess) {
118137
debug("Could not detect any devices")
119-
debug("Make sure pairing info is correct:")
120-
debug("More -> Factory reset")
121-
debug("To try again, restart the server:")
122-
debug("More -> Restart")
138+
debug("Fix 1) Toggle Wi-Fi or reboot")
139+
debug("Fix 2) Re-enter pairing information (More -> Factory Reset)")
140+
debug("To try again, restart the server (More -> Restart)")
123141

124142
tryingToPair = false
125143
return false
@@ -149,7 +167,8 @@ class ADB(private val context: Context) {
149167
else
150168
sendToShellProcess("echo 'Entered non-adb shell'")
151169

152-
val startupCommand = sharedPrefs.getString(context.getString(R.string.startup_command_key), "echo 'Success! ※\\(^o^)/※'")!!
170+
val startupCommand =
171+
sharedPrefs.getString(context.getString(R.string.startup_command_key), "echo 'Success! ※\\(^o^)/※'")!!
153172
if (startupCommand.isNotEmpty())
154173
sendToShellProcess(startupCommand)
155174

@@ -162,6 +181,9 @@ class ADB(private val context: Context) {
162181
private fun isWirelessDebuggingEnabled() =
163182
Settings.Global.getInt(context.contentResolver, "adb_wifi_enabled", 0) == 1
164183

184+
private fun isUSBDebuggingEnabled() =
185+
Settings.Global.getInt(context.contentResolver, Settings.Global.ADB_ENABLED, 0) == 1
186+
165187
/**
166188
* Wait restart the shell once it dies
167189
*/
@@ -193,7 +215,7 @@ class ADB(private val context: Context) {
193215

194216
/* Continue once finished pairing (or 10s elapses) */
195217
pairShell.waitFor(10, TimeUnit.SECONDS)
196-
pairShell.destroyForcibly()
218+
pairShell.destroyForcibly().waitFor()
197219
return pairShell.exitValue() == 0
198220
}
199221

0 commit comments

Comments
 (0)