android C++ database

AndroidからSQLiteのDBファイルを取り出す方法をAndroidソースから調べる

投稿日:2019年5月29日

AndroidからDBファイルを取り出し、PCに持ってきて、「PupSQLite」や「DB Browser for SQLite」などのツールで内容を確認出来るようにします。

コマンドラインで自動取得できるようにしておくことで、CIサイクル中にDBファイルを取ってきてスキーマ自動作成などが出来る環境を整えておきます。

DBファイルの場所を確認

PCにAndroidをUSB接続し、認識しているか確認します。

C:\>adb devices
List of devices attached
FA7761800334    device

Androidのシェルに入ります。

C:\>adb shell
htc_ocnuhljapan:/ $

run-asで開発アプリのパッケージディレクトリに入ります。root化しない限りこのディレクトリから外へはアクセス出来ません。また、インストールしたユーザに入られてクラックされても困りますから、アプリがリリースビルドされている場合はこの操作は出来ません。

htc_ocnuhljapan:/ $ run-as jp.co.xyz
htc_ocnuhljapan:/data/data/jp.co.xyz $ pwd
/data/data/jp.co.xyz

パッケージディレクトリ内にdatabasesというディレクトリがあります。

htc_ocnuhljapan:/data/data/jp.co.xyz $ ls
app_database app_webview code_cache shared_prefs
app_textures cache       databases

この中にアプリで作成したSQLiteのDBファイルが保存されています。

htc_ocnuhljapan:/data/data/jp.co.xyz $ cd databases
htc_ocnuhljapan:/data/data/jp.co.xyz/databases $ ls
awesomeapp.db  ← SQLIteのDBファイル

このawesomeapp.dbをPCに持ってくる方法を考えます。

Android5からアクセス権限が厳しくなった

Android5(Lolipop)からAndroidOS内のパーミッションが厳しくなりました。それ以前は一旦外から直接アクセスできるディレクトリにDBファイルをコピーしておき、adb pullを使って取ってきていました。

set PACKAGE=jp.co.xyz.awsameapp
set TEMPFILE=/mnt/shell/emulated/0/Android/data/%PACKAGE%/files
set DBFILEE=awsameapp.db

adb -d shell "run-as %PACKAGE% cat databases/%DBFILE% > %TEMPFILE%/%DBFILE%"

adb pull %TEMPFILE%/%DBFILE% 

自パッケージディレクトリ以外に完全にアクセス出来なくなった為、昨今のAndroidではこの手法が取れなくなってしまいました。

回避策

Androidのadbコマンド関連ソースを見ると、/system/core/adb/commandline.cppの中で、adbにはexec-outという公開されていないオプションが有り、out_to_file(int inFd, int outFd)という関数を呼んでいて、指定したファイルデスクプリタの内容をPCの標準出力に流してくれることが分かります。

// adbオプションでexec-outが指定されたか判定をしてる

    else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {

        (snip)

        if (exec_in) {
            copy_to_file(STDIN_FILENO, fd);
        } else {
            copy_to_file(fd, STDOUT_FILENO);
        }

// 入力ファイルデスクリプタ内容をPCの標準出力にコピーしてる

static void copy_to_file(int inFd, int outFd) {
    const size_t BUFSIZE = 32 * 1024;
    char* buf = (char*) malloc(BUFSIZE);
    if (buf == nullptr) fatal("couldn't allocate buffer for copy_to_file");
    int len;
    long total = 0;
    int old_stdin_mode = -1;
    int old_stdout_mode = -1;

    D("copy_to_file(%d -> %d)", inFd, outFd);

    stdinout_raw_prologue(inFd, outFd, old_stdin_mode, old_stdout_mode);

    while (true) {
        if (inFd == STDIN_FILENO) {
            len = unix_read(inFd, buf, BUFSIZE);
        } else {
            len = adb_read(inFd, buf, BUFSIZE);
        }
        if (len == 0) {
            D("copy_to_file() : read 0 bytes; exiting");
            break;
        }
        if (len < 0) {
            D("copy_to_file(): read failed: %s", strerror(errno));
            break;
        }
        if (outFd == STDOUT_FILENO) {
            fwrite(buf, 1, len, stdout);
            fflush(stdout);
        } else {
            adb_write(outFd, buf, len);
        }
        total += len;
    }

    stdinout_raw_epilogue(inFd, outFd, old_stdin_mode, old_stdout_mode);

    D("copy_to_file() finished after %lu bytes", total);
    free(buf);
}

この機能を利用すると端末内のdatabases/awsomeapp.dbファイルをcatし、ローカルPCのカレントディレクトリにリダイレクトできるようになります。

adb exec-out run-as jp.co.xyz cat databases/awesomeapp.db > ./awesomeapp.db

後はこれを直接使用するなり、Cordova系のハイブリッドアプリであればpackage.jsonでnpmスクリプト定義しておくなりしておきます。

以下「npm run getdb」を実行するとカレントディレクトリにDBファイルが吐き出されるpackage.json。

{
    (snip)

    "scripts": {

        (snip)

        "getdb": "adb exec-out run-as jp.co.xyz cat databases/awesomeapp.db > ./awesomeapp.db"
    },

exec-outはadbコマンドのヘルプにも出ておらず、GoogleのAndroid Deveropersサイトのドキュメントにも載っていないイースターエッグ的なオプションです。今後無くなる可能性は無きにしも非ずです。

今の所exec-outオプションの存在はネット検索で情報が見つかりますが、もしexec-outが無くなったらネットに新しい方法が流れるまで時間が掛かるかも知れません。自分でソースを調べればネットに情報が出てくるまで待たなくて済みます。

補足

/development/tools/winscope/capture_sf_trace.shというシェルの中でこんなadbコマンド使用例があります。

adb exec-out su root cat /data/misc/trace/layerstrace.pb >"$outfile"

exec-outはGoogle内のプログラマが使う為のオプションなんですね。ついでに利用させて貰いましょう。

-android, C++, database

執筆者:

関連記事

History APIを使ってIonic(3以前のSPA)でブラウザの戻るボタンやAndroidバックキーを押すと前サイトに戻ってしまう件に対応する

Ionic2や3ではまだAngular Routerを採用していなかったので、ページ遷移をしてもブラウザ履歴が積まれず、Androidのバックキーやブラウザの戻るボタンを押すとサイトに入ってくる前のペ …

Android版ChromiumをVirtualBoxにインストールしたUbuntuでビルドしてみる

「Chromium」はChromeの開発ソースが公開されたプロジェクトです。 www.chromium.org  1 UserGet the Code: Checkout, Build, & …

Android+ChromeでlocalhostアクセスしてPCサーバへPort Forward(Fwdアプリ使用)

昨今はプライバシーの侵害防止、セキュリティ観点から、HTTPS環境下でないと使えないHTML5 APIが増えました。 反してAndroid7でオレオレ証明書に関する仕様が変わり、Android6だった …

Stripe + Javaでオーソリ(与信の確保)を実装する

Stripeでチャリンチャリン、サービスを開発するエンジニアにとっては夢がありますよね。 例え自分で個人的に売るものが無かったとしても、Web決済システムを構築できるノウハウを持っておけば、公的な仕事 …

mkcertとhttp-serverでHTTPS環境を作りAndroid(chrome)、iPhone(safari)から接続

簡単にパーフェクトなオレオレ証明書が作れるとgithub上で人気上昇中の「mkcert」。 GitHub  135 UsersFiloSottile/mkcerthttps://github …

 

shingo.nakanishi
 

東京在勤、1977年生まれ、IT職歴2n年、生涯技術者として楽しく生きることを目指しています。デスマに負けず健康第一。