adb-dbg 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,28 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .pytest_cache/
6
+ .mypy_cache/
7
+ .ruff_cache/
8
+
9
+ # Virtual environments
10
+ .venv/
11
+ venv/
12
+
13
+ # Build artifacts
14
+ build/
15
+ dist/
16
+
17
+ # IDE
18
+ .idea/
19
+ .vscode/
20
+
21
+ # OS
22
+ .DS_Store
23
+ Thumbs.db
24
+
25
+ # Secrets
26
+ .env
27
+ .env.*
28
+ !.env.example
adb_dbg-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tirrou Oussama
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
adb_dbg-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,115 @@
1
+ Metadata-Version: 2.5
2
+ Name: adb-dbg
3
+ Version: 0.1.0
4
+ Summary: A lightweight Android process debugger with automatic PID reconnection.
5
+ Project-URL: Homepage, https://github.com/TirrouOussama/adb-dbg
6
+ Project-URL: Repository, https://github.com/TirrouOussama/adb-dbg
7
+ Project-URL: Issues, https://github.com/TirrouOussama/adb-dbg/issues
8
+ Author: Tirrou Oussama
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: adb,android,android-debugging,debugging,logcat
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Topic :: Software Development :: Debuggers
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+
22
+ # adb-dbg
23
+
24
+ A lightweight Android process debugger that automatically monitors an Android application's PID and reconnects Logcat whenever the process restarts.
25
+
26
+ ## Features
27
+
28
+ - Automatically detects connected Android devices.
29
+ - Selects the device automatically when only one is connected.
30
+ - Supports explicit device selection when multiple devices are connected.
31
+ - Monitors Android application processes.
32
+ - Supports secondary Android processes (`PACKAGE:SERVICE`).
33
+ - Automatically reconnects Logcat when a process terminates or restarts.
34
+ - Detects unexpected Logcat termination and reconnects.
35
+ - Clean shutdown with Ctrl+C.
36
+
37
+ ## Requirements
38
+
39
+ - Python 3.9+
40
+ - Android Debug Bridge (ADB)
41
+ - At least one authorized Android device connected through ADB.
42
+
43
+ ADB must be available in your system PATH.
44
+
45
+ ## Installation
46
+
47
+ Clone the repository:
48
+
49
+ ```bash
50
+ git clone https://github.com/TirrouOussama/adb-dbg.git
51
+ cd adb-dbg
52
+ ```
53
+
54
+ ## Usage
55
+
56
+ ### Automatic device selection
57
+
58
+ ```bash
59
+ adb-dbg PACKAGE
60
+ ```
61
+
62
+ Example:
63
+
64
+ ```bash
65
+ adb-dbg org.awfer.awferrides
66
+ ```
67
+
68
+ ### Secondary process
69
+
70
+ ```bash
71
+ adb-dbg PACKAGE SERVICE
72
+ ```
73
+
74
+ Example:
75
+
76
+ ```bash
77
+ adb-dbg org.awfer.awferdriver tripd
78
+ ```
79
+
80
+ ### Explicit device selection
81
+
82
+ ```bash
83
+ adb-dbg DEVICE PACKAGE [SERVICE]
84
+ ```
85
+
86
+ Example:
87
+
88
+ ```bash
89
+ adb-dbg RZCX31JLK1N org.awfer.awferdriver tripd
90
+ ```
91
+
92
+ ### Help
93
+
94
+ ```bash
95
+ adb-dbg --help
96
+ ```
97
+
98
+ ## How it works
99
+
100
+ 1. Detects authorized ADB devices.
101
+ 2. Selects the target device.
102
+ 3. Finds the Android process using `pidof`.
103
+ 4. Attaches Logcat to the process PID.
104
+ 5. Monitors the PID every 0.5 seconds.
105
+ 6. Detects process termination or restart.
106
+ 7. Reconnects Logcat using the new PID.
107
+ 8. If the process is not running, waits until it becomes available.
108
+
109
+ ## Controls
110
+
111
+ - `Ctrl+C`: Stop the debugger.
112
+
113
+ ## License
114
+
115
+ MIT License. See [LICENSE](LICENSE).
@@ -0,0 +1,94 @@
1
+ # adb-dbg
2
+
3
+ A lightweight Android process debugger that automatically monitors an Android application's PID and reconnects Logcat whenever the process restarts.
4
+
5
+ ## Features
6
+
7
+ - Automatically detects connected Android devices.
8
+ - Selects the device automatically when only one is connected.
9
+ - Supports explicit device selection when multiple devices are connected.
10
+ - Monitors Android application processes.
11
+ - Supports secondary Android processes (`PACKAGE:SERVICE`).
12
+ - Automatically reconnects Logcat when a process terminates or restarts.
13
+ - Detects unexpected Logcat termination and reconnects.
14
+ - Clean shutdown with Ctrl+C.
15
+
16
+ ## Requirements
17
+
18
+ - Python 3.9+
19
+ - Android Debug Bridge (ADB)
20
+ - At least one authorized Android device connected through ADB.
21
+
22
+ ADB must be available in your system PATH.
23
+
24
+ ## Installation
25
+
26
+ Clone the repository:
27
+
28
+ ```bash
29
+ git clone https://github.com/TirrouOussama/adb-dbg.git
30
+ cd adb-dbg
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ ### Automatic device selection
36
+
37
+ ```bash
38
+ adb-dbg PACKAGE
39
+ ```
40
+
41
+ Example:
42
+
43
+ ```bash
44
+ adb-dbg org.awfer.awferrides
45
+ ```
46
+
47
+ ### Secondary process
48
+
49
+ ```bash
50
+ adb-dbg PACKAGE SERVICE
51
+ ```
52
+
53
+ Example:
54
+
55
+ ```bash
56
+ adb-dbg org.awfer.awferdriver tripd
57
+ ```
58
+
59
+ ### Explicit device selection
60
+
61
+ ```bash
62
+ adb-dbg DEVICE PACKAGE [SERVICE]
63
+ ```
64
+
65
+ Example:
66
+
67
+ ```bash
68
+ adb-dbg RZCX31JLK1N org.awfer.awferdriver tripd
69
+ ```
70
+
71
+ ### Help
72
+
73
+ ```bash
74
+ adb-dbg --help
75
+ ```
76
+
77
+ ## How it works
78
+
79
+ 1. Detects authorized ADB devices.
80
+ 2. Selects the target device.
81
+ 3. Finds the Android process using `pidof`.
82
+ 4. Attaches Logcat to the process PID.
83
+ 5. Monitors the PID every 0.5 seconds.
84
+ 6. Detects process termination or restart.
85
+ 7. Reconnects Logcat using the new PID.
86
+ 8. If the process is not running, waits until it becomes available.
87
+
88
+ ## Controls
89
+
90
+ - `Ctrl+C`: Stop the debugger.
91
+
92
+ ## License
93
+
94
+ MIT License. See [LICENSE](LICENSE).
@@ -0,0 +1,41 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "adb-dbg"
7
+ version = "0.1.0"
8
+ description = "A lightweight Android process debugger with automatic PID reconnection."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "MIT"
12
+ authors = [
13
+ { name = "Tirrou Oussama" }
14
+ ]
15
+ keywords = [
16
+ "android",
17
+ "adb",
18
+ "debugging",
19
+ "logcat",
20
+ "android-debugging"
21
+ ]
22
+ classifiers = [
23
+ "Development Status :: 3 - Alpha",
24
+ "Environment :: Console",
25
+ "Intended Audience :: Developers",
26
+ "License :: OSI Approved :: MIT License",
27
+ "Operating System :: OS Independent",
28
+ "Programming Language :: Python :: 3",
29
+ "Topic :: Software Development :: Debuggers"
30
+ ]
31
+
32
+ [project.urls]
33
+ Homepage = "https://github.com/TirrouOussama/adb-dbg"
34
+ Repository = "https://github.com/TirrouOussama/adb-dbg"
35
+ Issues = "https://github.com/TirrouOussama/adb-dbg/issues"
36
+
37
+ [project.scripts]
38
+ adb-dbg = "adb_dbg.cli:main"
39
+
40
+ [tool.hatch.build.targets.wheel]
41
+ packages = ["src/adb_dbg"]
@@ -0,0 +1,3 @@
1
+ """ADB-Debugger: monitor Android processes and automatically reconnect logcat."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,263 @@
1
+
2
+ """Android process debugger with automatic PID reconnection."""
3
+
4
+ import argparse
5
+ import shutil
6
+ import subprocess
7
+ import sys
8
+ import time
9
+
10
+
11
+ def get_devices(adb):
12
+ """Return authorized ADB device serials."""
13
+
14
+ result = subprocess.run(
15
+ [adb, "devices"],
16
+ capture_output=True,
17
+ text=True,
18
+ )
19
+
20
+ if result.returncode != 0:
21
+ raise RuntimeError("Unable to retrieve ADB devices.")
22
+
23
+ devices = []
24
+
25
+ for line in result.stdout.splitlines()[1:]:
26
+ fields = line.split()
27
+
28
+ if len(fields) >= 2 and fields[1] == "device":
29
+ devices.append(fields[0])
30
+
31
+ return devices
32
+
33
+
34
+ def get_process_pid(adb, device, process):
35
+ """Return the first PID belonging to the Android process."""
36
+
37
+ result = subprocess.run(
38
+ [adb, "-s", device, "shell", "pidof", process],
39
+ capture_output=True,
40
+ text=True,
41
+ )
42
+
43
+ output = result.stdout.strip().replace("\r", "")
44
+
45
+ if not output:
46
+ return None
47
+
48
+ return output.split()[0]
49
+
50
+
51
+ def stop_logcat(logcat):
52
+ """Stop the current logcat subprocess."""
53
+
54
+ if logcat is None or logcat.poll() is not None:
55
+ return
56
+
57
+ logcat.terminate()
58
+
59
+ try:
60
+ logcat.wait(timeout=2)
61
+ except subprocess.TimeoutExpired:
62
+ logcat.kill()
63
+ logcat.wait()
64
+
65
+
66
+ def build_parser():
67
+ parser = argparse.ArgumentParser(
68
+ prog="adb-dbg",
69
+ description=(
70
+ "Monitor an Android process and automatically reconnect "
71
+ "logcat when its PID changes."
72
+ ),
73
+ usage=(
74
+ "adb-dbg [-h] PACKAGE [SERVICE]\n"
75
+ " adb-dbg [-h] DEVICE PACKAGE [SERVICE]"
76
+ ),
77
+ epilog=(
78
+ "Examples:\n"
79
+ " adb-dbg org.awfer.awferrides\n"
80
+ " adb-dbg org.awfer.awferdriver tripd\n"
81
+ " adb-dbg DEVICE_SERIAL com.example.anyapp\n"
82
+ " adb-dbg DEVICE_SERIAL com.example.anyapp service"
83
+ ),
84
+ formatter_class=argparse.RawDescriptionHelpFormatter,
85
+ )
86
+
87
+ parser.add_argument(
88
+ "arguments",
89
+ nargs="*",
90
+ metavar="ARG",
91
+ )
92
+
93
+ return parser
94
+
95
+
96
+ def main(argv=None):
97
+ parser = build_parser()
98
+ args = parser.parse_args(argv)
99
+ arguments = args.arguments
100
+
101
+ if not arguments:
102
+ parser.error("Missing application package.")
103
+
104
+ if len(arguments) > 3:
105
+ parser.error("Too many arguments.")
106
+
107
+ adb = shutil.which("adb")
108
+
109
+ if adb is None:
110
+ print(
111
+ "ERROR: ADB is not installed or not in PATH.",
112
+ file=sys.stderr,
113
+ )
114
+ return 1
115
+
116
+ try:
117
+ devices = get_devices(adb)
118
+ except (OSError, RuntimeError) as exc:
119
+ print(f"ERROR: {exc}", file=sys.stderr)
120
+ return 1
121
+
122
+ if not devices:
123
+ print(
124
+ "ERROR: No connected or authorized ADB devices.",
125
+ file=sys.stderr,
126
+ )
127
+ return 1
128
+
129
+ device = None
130
+ package = None
131
+ service = ""
132
+
133
+ # Explicit device selection.
134
+ if arguments[0] in devices:
135
+ if len(arguments) < 2:
136
+ parser.error("Missing application package after device serial.")
137
+
138
+ device = arguments[0]
139
+ package = arguments[1]
140
+ service = arguments[2] if len(arguments) == 3 else ""
141
+
142
+ else:
143
+ if len(devices) > 1:
144
+ print(
145
+ "ERROR: Multiple ADB devices connected.",
146
+ file=sys.stderr,
147
+ )
148
+ print("\nSpecify a device:", file=sys.stderr)
149
+
150
+ for serial in devices:
151
+ print(f" {serial}", file=sys.stderr)
152
+
153
+ print(
154
+ f"\nExample:\n adb-dbg {devices[0]} "
155
+ f"{arguments[0]}",
156
+ file=sys.stderr,
157
+ )
158
+ return 1
159
+
160
+ if len(arguments) == 3:
161
+ parser.error(
162
+ "Invalid device serial. "
163
+ "Use DEVICE PACKAGE [SERVICE]."
164
+ )
165
+
166
+ device = devices[0]
167
+ package = arguments[0]
168
+ service = arguments[1] if len(arguments) == 2 else ""
169
+
170
+ process = f"{package}:{service}" if service else package
171
+
172
+ print("======================================")
173
+ print(" ANDROID PROCESS DEBUGGER")
174
+ print("======================================")
175
+ print(f"Device: {device}")
176
+ print(f"Package: {package}")
177
+ print(f"Process: {process}")
178
+ print("======================================")
179
+
180
+ logcat = None
181
+
182
+ try:
183
+ while True:
184
+ try:
185
+ pid = get_process_pid(adb, device, process)
186
+ except OSError as exc:
187
+ print(f"ADB error: {exc}", file=sys.stderr)
188
+ time.sleep(1)
189
+ continue
190
+
191
+ if not pid:
192
+ print(
193
+ f"[{time.strftime('%H:%M:%S')}] "
194
+ f"Waiting for {process}...",
195
+ flush=True,
196
+ )
197
+ time.sleep(1)
198
+ continue
199
+
200
+ print()
201
+ print(f"[{time.strftime('%H:%M:%S')}] ATTACHED")
202
+ print(f"Process: {process}")
203
+ print(f"PID: {pid}")
204
+ print("--------------------------------------", flush=True)
205
+
206
+ try:
207
+ logcat = subprocess.Popen(
208
+ [
209
+ adb,
210
+ "-s",
211
+ device,
212
+ "logcat",
213
+ "-v",
214
+ "threadtime",
215
+ f"--pid={pid}",
216
+ ]
217
+ )
218
+ except OSError as exc:
219
+ print(f"ERROR: Unable to start logcat: {exc}")
220
+ time.sleep(1)
221
+ continue
222
+
223
+ while True:
224
+ time.sleep(0.5)
225
+
226
+ try:
227
+ current_pid = get_process_pid(
228
+ adb,
229
+ device,
230
+ process,
231
+ )
232
+ except OSError:
233
+ current_pid = None
234
+
235
+ if current_pid != pid:
236
+ print()
237
+ print(
238
+ f"[{time.strftime('%H:%M:%S')}] "
239
+ "PROCESS CHANGED"
240
+ )
241
+ print(f"Old PID: {pid}")
242
+ print(f"New PID: {current_pid or 'DEAD'}")
243
+ print("Reconnecting...")
244
+ break
245
+
246
+ if logcat.poll() is not None:
247
+ print("Logcat exited. Reconnecting...")
248
+ break
249
+
250
+ stop_logcat(logcat)
251
+ logcat = None
252
+
253
+ except KeyboardInterrupt:
254
+ print("\nDebugger stopped.")
255
+
256
+ finally:
257
+ stop_logcat(logcat)
258
+
259
+ return 0
260
+
261
+
262
+ if __name__ == "__main__":
263
+ sys.exit(main())
File without changes