Help us understand the problem. What is going on with this article?

AndroidのSQLiteDatabaseの覗き方

More than 5 years have passed since last update.

非root端末のSQLiteDatabaseを覗きたい

Androidアプリの開発で非root端末のSQLiteDatabaseは覗けない。
厳密には覗けないわけではなく、該当するアプリからは
アクセスできるのだけど、これでは勝手が悪い。
開発中はSQLを直接叩きたかった。
だから無理矢理に覗く方法を作りました。

どうやって?

アプリ側に1クラスで完結する小さなプログラムを埋め込み、
そこ経由でアクセスできるようにした。
要はバックドアのようなもの。
もちろん開発専用なので間違ってもリリースビルドには入れては行けない。

サンプルプログラム

説明にに使用したアプリケーションはこちらになります。
このアプリケーションのbuild.gradleとMyApplication.javaが該当します。

使い方

使い方は次の3ステップです。

  • 小さなプログラムを埋め込む
  • Application#onCreateで埋め込んだプログラムをキックする
  • telnetで繋いでSQLを実行する

それでは1つずつ見て行きましょう。

小さなプログラムを埋め込む

AndroidManifest.xmlにINTERNETパーミッションを追加します。

    <uses-permission android:name="android.permission.INTERNET"/>

次にbuild.gradleのdependanciesに次の行を追加します。

    debugCompile 'net.cattaka:telnetsqlite:1.0.0'

デバッグ専用なのでdebugCompileとしています。
compileにするとリリース版ビルドに含まれてしまうのでご注意ください。

Application#onCreateで埋め込んだプログラムをキックする

カスタムアプリケーションクラスに次の様なコードを追加します。
カスタムアプリケーションクラスがない場合は作ってください。

public class MyAppliction extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        // SQLiteにアクセするためのサーバーを起動する(開発時専用)
        try {
             Class<?> clazz = Class.forName("net.cattaka.telnetsqlite.TelnetSqliteService");
            Thread serverThread = (Thread)clazz.getMethod("createTelnetSqliteServer", Context.class, int.class).invoke(null, this, 12080);
            serverThread.start();
       } catch (Exception e) {
            // ignore
        }
    }
}

serverThreadを生成するときの12080という値は、サーバーのポート番号です。
必要ならば適宜の値を変更してください。
リフレクションを使用しているのはリリースビルドでコンパイルエラーにならないようにするためで、
もしリリース時にコードごと消すならばリフレクション無しで書いても大丈夫です。

telnetで繋いでSQLを実行する

アプリケーションを起動して、PCからtelnetで接続します。
接続方法は2つあります。

1つめはデバイスIPアドレスを指定する方法です。adb shell netcfgコマンドでIPアドレスを調べた後に、次のコマンドを実行します。

$ telnet <マシンのIPアドレス> <上で指定したポート番号>

2つめはadbコマンドのforwardを使ってlocalhost経由で接続する方法です。通常はUSBでデバイスを繋ぐのでこちらのほうが便利です。

$ adb forward tcp:<上で指定したポート番号> tcp:<上で指定したポート番号>
$ telnet localhost <上で指定したポート番号>

telnetの接続に成功したら、一行目に開きたいデータベースファイル名(SQLiteOpenHelperのコンストラクタに指定したデータベース名のこと)を指定します。それ以降はSQLを書いてEnterを押すとそのまま実行されます。

$ telnet ctk070 12080
Trying 192.168.3.70...
Connected to ctk070.xxx.yyyy.
Escape character is '^]'.
data.db                       <-データベースファイル名を入力
S
$
select * from checkListItem   <-SQLを入力して実行
S5
+id,entryId,sort,label        <-テーブルの列名(先頭に+が付いてる)
-1,1,1,財布                    <-以下テーブルのデータ(先頭に-が付いてる)
-2,1,2,鍵
-3,1,3,携帯電話
-4,1,4,手帳
-5,1,5,名刺

$

GUIツールを使う

telnetで接続できるのは便利ですが、成形もされていないので見づらいです。幸いなことに対応したRdbAssistantというGUIのSQLエディタがあります。このSQLエディタはJavaアプリケーションとして動作するため、Javaランタイムがある環境ならばどこでも動作します。

起動すると最初に接続情報を作りましょう。接続の種類のTelnetSqliteを選択し、ホスト名、ポート番号、データベース名を間違えず入力してください。

20140927_1.png

接続情報を作成したら、選択して接続ボタンを押してください。アプリ側が起動していればSQLの入力画面が表示されます。ここではSQLの実行だけでなく、テーブルの一覧や列名の閲覧も行えます。

20140927_2.png

まとめ

Androidのアプリケーション開発でSQLiteデータベースの使用は避けては通れません。しかしだからといって中身が覗けないままでは開発も大変です。幸いAndroidのフレームワークは標準で沢山のAPIが使えるので、小さなツールは作って埋め込んでしまいましょう。ServerSocketがあれば大抵のことができるはずです。今回はSQLiteDatabaseを覗くために使用しましたが、この手法は他のことにも応用ができます。ただし、リリースビルドには含まれると駄目なので、混入しないように注意しましょう。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした