應用包名com.packagename。
沒有root權限的手機,使用adb shell無法直接獲取到/data/data/com.packagename下的數據,因為沒有訪問的權限。
這個時候,就可以使用run-as來獲取應用數據協助開發調試。
$ adb shell
$ run-as com.packagename
$ pwd
/data/data/com.packagename #run-as命令當前已自動切換到用戶目錄
$ ls -l
drwxrwx--x app_83 app_83 2010-01-17 08:01 files
drwxrwx--x app_83 app_83 2010-01-17 08:01 databases
drwxrwx--x app_83 app_83 2010-01-17 08:01 shared_prefs
drwxr-xr-x system system 2010-01-17 08:01 lib
$ ls databases
test.db
$ cat databases/skyAppStroe.db > /sdcard/test.db
$ ls -l /sdcard/test.db
----rwxr-x system sdcard_rw 8192 2010-01-17 08:04 test.db
$ exit
$ pwd
/
注意:
1.使用run-as后,是無法使用cp命令將應用數據拷貝到sd卡的,沒有權限
2.如果apk已經簽名,並且設置了android:debuggable="false",將無法使用該命令。
3.如果無法使用run-as來直接獲取應用數據,可以在自己的應用里實現讀取應用數據到sd卡的功能,應用本身對自己的數據是有訪問權限的。
4./data/data/com.packagename/lib目錄不需要執行run-as就擁有訪問權限,為apk間共享so提供了便利
android2.3.3_r1中run-as.c中主要代碼:
/* 沒有傳入包名則退出 */
if (argc < 2)
usage();
/* 非'shell'用戶或'root'用戶則退出 */
myuid = getuid();
if (myuid != AID_SHELL && myuid != AID_ROOT) {
panic("only 'shell' or 'root' users can run this program\n");
}
/* 根據傳入包名獲取應用信息,失敗則退出 */
pkgname = argv[1];
if (get_package_info(pkgname, &info) < 0) {
panic("Package '%s' is unknown\n", pkgname);
return 1;
}
/* reject system packages */
if (info.uid < AID_APP) {
panic("Package '%s' is not an application\n", pkgname);
return 1;
}
/* 如果設置了android:debuggable="false",則退出 */
if (!info.isDebuggable) {
panic("Package '%s' is not debuggable\n", pkgname);
return 1;
}
/* 檢查/data/data/com.packagename目錄是否可用 */
if (check_data_path(info.dataDir, info.uid) < 0) {
panic("Package '%s' has corrupt installation\n", pkgname);
return 1;
}
/* 切換當前工作目錄為/data/data/com.packagename,失敗則退出 */
{
int ret;
do {
ret = chdir(info.dataDir);
} while (ret < 0 && errno == EINTR);
if (ret < 0) {
panic("Could not cd to package's data directory: %s\n", strerror(errno));
return 1;
}
}
/* Ensure that we change all real/effective/saved IDs at the
* same time to avoid nasty surprises.
*/
/* 切換真實/有效/saved 用戶ID和組ID*/
uid = gid = info.uid;
if(setresgid(gid,gid,gid) || setresuid(uid,uid,uid)) {
panic("Permission denied\n");
return 1;
}
/* 用戶在包名參數后指定了要執行的命令,就執行這個命令 */
if (argc >= 3 ) {
if (execvp(argv[2], argv+2) < 0) {
panic("exec failed for %s Error:%s\n", argv[2], strerror(errno));
return -errno;
}
}
/* 用戶沒有傳入要執行的命令,執行默認的shell命令子進程,此時可以執行exit命令退出 */
execlp("/system/bin/sh", "sh", NULL);
panic("exec failed\n");
return 1;
參考:
http://www.iandroid.cn/bbs/android-1506-1-1.html
http://www.cnblogs.com/over140/archive/2012/06/13/2547706.html
