mirror of
https://github.com/Genymobile/scrcpy.git
synced 2025-08-03 06:39:39 +00:00
Add util function to get the APK path
Use "pm list package -f" to find where the APK is actually installed on the device.
This commit is contained in:
parent
88499cd101
commit
00766b8ab6
5 changed files with 118 additions and 0 deletions
|
@ -713,3 +713,48 @@ sc_adb_get_device_ip(struct sc_intr *intr, const char *serial, unsigned flags) {
|
||||||
|
|
||||||
return sc_adb_parse_device_ip(buf);
|
return sc_adb_parse_device_ip(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
sc_adb_get_installed_apk_path(struct sc_intr *intr, const char *serial,
|
||||||
|
unsigned flags) {
|
||||||
|
assert(serial);
|
||||||
|
const char *const argv[] =
|
||||||
|
SC_ADB_COMMAND("-s", serial, "shell", "pm", "list", "package", "-f",
|
||||||
|
SC_ANDROID_PACKAGE);
|
||||||
|
|
||||||
|
sc_pipe pout;
|
||||||
|
sc_pid pid = sc_adb_execute_p(argv, flags, &pout);
|
||||||
|
if (pid == SC_PROCESS_NONE) {
|
||||||
|
LOGD("Could not execute \"pm list packages\"");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "pm list packages -f <package>" output should contain only one line, so
|
||||||
|
// the output should be short
|
||||||
|
char buf[1024];
|
||||||
|
ssize_t r = sc_pipe_read_all_intr(intr, pid, pout, buf, sizeof(buf) - 1);
|
||||||
|
sc_pipe_close(pout);
|
||||||
|
|
||||||
|
bool ok = process_check_success_intr(intr, pid, "pm list packages", flags);
|
||||||
|
if (!ok) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r == -1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert((size_t) r < sizeof(buf));
|
||||||
|
if (r == sizeof(buf) - 1) {
|
||||||
|
// The implementation assumes that the output of "pm list packages"
|
||||||
|
// fits in the buffer in a single pass
|
||||||
|
LOGW("Result of \"pm list package\" does not fit in 1Kb. "
|
||||||
|
"Please report an issue.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is parsed as a NUL-terminated string
|
||||||
|
buf[r] = '\0';
|
||||||
|
|
||||||
|
return sc_adb_parse_installed_apk_path(buf);
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
#define SC_ADB_SILENT (SC_ADB_NO_STDOUT | SC_ADB_NO_STDERR | SC_ADB_NO_LOGERR)
|
#define SC_ADB_SILENT (SC_ADB_NO_STDOUT | SC_ADB_NO_STDERR | SC_ADB_NO_LOGERR)
|
||||||
|
|
||||||
|
#define SC_ANDROID_PACKAGE "com.genymobile.scrcpy"
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
sc_adb_get_executable(void);
|
sc_adb_get_executable(void);
|
||||||
|
|
||||||
|
@ -114,4 +116,11 @@ sc_adb_getprop(struct sc_intr *intr, const char *serial, const char *prop,
|
||||||
char *
|
char *
|
||||||
sc_adb_get_device_ip(struct sc_intr *intr, const char *serial, unsigned flags);
|
sc_adb_get_device_ip(struct sc_intr *intr, const char *serial, unsigned flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the path of the installed APK for com.genymobile.scrcpy (if any)
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
sc_adb_get_installed_apk_path(struct sc_intr *intr, const char *serial,
|
||||||
|
unsigned flags);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -225,3 +225,31 @@ sc_adb_parse_device_ip(char *str) {
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
sc_adb_parse_installed_apk_path(char *str) {
|
||||||
|
// str is expected to look like:
|
||||||
|
// "package:/data/app/.../base.apk=com.genymobile.scrcpy"
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
// We want to extract the path (which may contain '=', even in practice)
|
||||||
|
|
||||||
|
if (strncmp(str, "package:", 8)) {
|
||||||
|
// Does not start with "package:"
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *s = str + 8;
|
||||||
|
size_t len = strcspn(s, " \r\n");
|
||||||
|
s[len] = '\0';
|
||||||
|
|
||||||
|
char *p = strrchr(s, '=');
|
||||||
|
if (!p) {
|
||||||
|
// No '=' found
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Truncate at the last '='
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
return strdup(s);
|
||||||
|
}
|
||||||
|
|
|
@ -27,4 +27,15 @@ sc_adb_parse_devices(char *str, struct sc_vec_adb_devices *out_vec);
|
||||||
char *
|
char *
|
||||||
sc_adb_parse_device_ip(char *str);
|
sc_adb_parse_device_ip(char *str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the package path from the output of
|
||||||
|
* `adb shell pm list packages -f <package>`
|
||||||
|
*
|
||||||
|
* The parameter must be a NUL-terminated string.
|
||||||
|
*
|
||||||
|
* Warning: this function modifies the buffer for optimization purposes.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
sc_adb_parse_installed_apk_path(char *str);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -241,6 +241,28 @@ static void test_get_ip_truncated(void) {
|
||||||
assert(!ip);
|
assert(!ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_apk_path(void) {
|
||||||
|
char str[] = "package:/data/app/~~71mguyc6p-kNjQdNaNkToA==/com.genymobile."
|
||||||
|
"scrcpy-l6fiqqUSU7Ok7QLg-rIyJA==/base.apk=com.genymobile."
|
||||||
|
"scrcpy\n";
|
||||||
|
|
||||||
|
const char *expected = "/data/app/~~71mguyc6p-kNjQdNaNkToA==/com.genymobile"
|
||||||
|
".scrcpy-l6fiqqUSU7Ok7QLg-rIyJA==/base.apk";
|
||||||
|
char *path = sc_adb_parse_installed_apk_path(str);
|
||||||
|
assert(!strcmp(path, expected));
|
||||||
|
free(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_apk_path_invalid(void) {
|
||||||
|
// Does not start with "package:"
|
||||||
|
char str[] = "garbage:/data/app/~~71mguyc6p-kNjQdNaNkToA==/com.genymobile."
|
||||||
|
"scrcpy-l6fiqqUSU7Ok7QLg-rIyJA==/base.apk=com.genymobile."
|
||||||
|
"scrcpy\n";
|
||||||
|
|
||||||
|
char *path = sc_adb_parse_installed_apk_path(str);
|
||||||
|
assert(!path);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
(void) argc;
|
(void) argc;
|
||||||
(void) argv;
|
(void) argv;
|
||||||
|
@ -263,5 +285,8 @@ int main(int argc, char *argv[]) {
|
||||||
test_get_ip_no_wlan_without_eol();
|
test_get_ip_no_wlan_without_eol();
|
||||||
test_get_ip_truncated();
|
test_get_ip_truncated();
|
||||||
|
|
||||||
|
test_apk_path();
|
||||||
|
test_apk_path_invalid();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue