One IT Thing

IT業界を楽しむ為の学習系雑記

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

執筆者:

関連記事

Android操作動画をGIF画像化する(Windows編)

Web上のスマホ操作説明に動画を入れ、直感的で分かり易くしたいことがあります。 Android + Windows環境かつ無料で行う場合は「AZ スクリーンレコーダー」と「openAVItoGIF」の …

Termuxで動作が確認できたターミナルゲーム4つ

Android端末をroot化せずにLinux環境を独自構築する神アプリ「Termux」。  play.google.comTermux – Apps on Google Playhttps …

B2BスマホアプリをGooglePlay、AppStoreに公開することがお勧め出来ない7つの理由とその対策

商材の性質やシーンに応じてスマホアプリをGooglePlayやAppleStoreのようなストアに公開することがマイナスに働くこともあります。 商材として価値の有る電子データをお持ちの商社さんとアプリ …

adb devicesコマンドでAndroid端末を認識しない

目次1 事象2 原因3 解決 事象 USB接続するAndroidによって以下のエラーが出たりします。 C:\src\ionic\awsomeapp>adb devices List of dev …

UserAgent判定JSライブラリ「UAParser.js」と「Platform.js」の比較

(私はUAParser.jsを使っています) ネットを探すとUA文字列を解析してブラウザ判定をするコードが一杯出てきます。 でもUA解析プログラムを自前で作ってシステムに組み込むとなると、新しいブラウ …


shingo nakanishi。東京で消耗中の職歴20年越え中年ITエンジニアです。「生涯現役プログラマを楽しむ」ことができる働き方探しをライフワークにしています。

19歳(1996年)から書き始めた個人日記が5,000日を超え、残りの人生は発信をして行きたいと思い、令和元日からこのサイトを開始しました。勉強と試行錯誤をしながら、自分が経験したIT関連情報を投稿しています。