非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を選択し、ホスト名、ポート番号、データベース名を間違えず入力してください。
接続情報を作成したら、選択して接続ボタンを押してください。アプリ側が起動していればSQLの入力画面が表示されます。ここではSQLの実行だけでなく、テーブルの一覧や列名の閲覧も行えます。
まとめ
Androidのアプリケーション開発でSQLiteデータベースの使用は避けては通れません。しかしだからといって中身が覗けないままでは開発も大変です。幸いAndroidのフレームワークは標準で沢山のAPIが使えるので、小さなツールは作って埋め込んでしまいましょう。ServerSocketがあれば大抵のことができるはずです。今回はSQLiteDatabaseを覗くために使用しましたが、この手法は他のことにも応用ができます。ただし、リリースビルドには含まれると駄目なので、混入しないように注意しましょう。