Android上でgethを使用する

##やったこと
Android上でgethライブラリの動作をサンプルベースで確認したのでメモとして記載。

###環境：
開発環境 Ubuntu16.04, Android studio
使用端末 zenfone3(Android7.0 )

##手順0：ドキュメントの確認。
下記ドキュメントを参考にする
https://github.com/ethereum/go-ethereum/wiki/Mobile%3A-Introduction

AndroidやiOS版でそれぞれライブラリがある。
同期方法はLightクライアントモードになっている。

この同期方法だと、ブロックヘッダを同期させるだけで、最新ブロックに到達する同期速度が早く、データ容量も少なくて済む。（15〜20分程度の同期で、300MBくらいで済んでしまう。）

##手順１：Android用のgethパッケージをダウンロードする。
ドキュメントどおりGo EthereumのサイトからAndroid のStable Release版でGeth1.7.0の:geth-android-all-1.7.0-6c6c7b2a.aarをダウンロードする。

https://geth.ethereum.org/downloads/

##手順２：Android Studioのプロジェクトにaarをインポートする。

Android Studioから任意のプロジェクトを新規に立ち上げ、
「File」 -> 「New」 -> 「New module...」 -> 「Import .JAR/.AAR Package」を選択する。
ダウンロードしたAARパッケージの格納先を指定する。



アプリケーションモジュール側(Module:app)のbuild.gradleのdependenciesに依存関係を記述する。
ドキュメント上ではcompile project(":geth")とあるが、インポート時に作成したプロジェクト名にしておく。

```:build.gradle(app)
dependencies {
　compile project(":geth-android-all-1.7.0-6c6c7b2a")
}
```

下のスクリーンショットのように「Sync Projcet with Gradle Files」を実行し
複数プロジェクトを同期させる。

![Screenshot from 2017-09-24 10-23-02.png](https://qiita-image-store.s3.amazonaws.com/0/142016/568ade76-429d-0c9d-c71d-7d4ba5428fe3.png)


##手順３：サンプルコードを作成する。

```java:
package com.example.umidachi.myapplication;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import android.util.Log;
import org.ethereum.geth.*;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        setTitle("Android In-Process Node");
        final TextView textbox = (TextView) findViewById(R.id.textbox);

        Context ctx = new Context();
        Log.d("GETH",getFilesDir() + "/.ethereum");
        try {
            Node node = Geth.newNode(getFilesDir() + "/.ethereum", new NodeConfig());

            node.start();

            NodeInfo info = node.getNodeInfo();
            textbox.append("My name: " + info.getName() + "\n");
            textbox.append("My address: " + info.getListenerAddress() + "\n");
            textbox.append("My protocols: " + info.getProtocols() + "\n\n");

            EthereumClient ec = node.getEthereumClient();
            textbox.append("Latest block: " + ec.getBlockByNumber(ctx, -1).getNumber() + ", syncing...\n");

            NewHeadHandler handler = new NewHeadHandler() {
                @Override public void onError(String error) { }
                @Override public void onNewHead(final Header header) {
                    MainActivity.this.runOnUiThread(new Runnable() {
                        public void run() { textbox.append("#" + header.getNumber() + ": " + header.getHash().getHex().substring(0, 10) + "…\n"); }
                    });
                }
            };
            ec.subscribeNewHead(ctx, handler,  16);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
```

これだけだと、アプリケーションがインターネットに繋がる権限が与えられずノード同士で同期できないので
AndroidManifest.xmlに権限を追加しておく

```:AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.umidachi.myapplication">

　　　↓（追加）
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        〜
    </application>

</manifest>
```

最終的にデバッグモードで実行した結果が次の通り。
サンプル通りに表示されたが、最初にLatest block:0, syncing...までしか表示されず、
少し待たないとSyncing以降のブロック番号が出力されないようだった。
（正常な挙動かわからないため、改善できたら追記します。）

![device-2017-09-24-125128.png](https://qiita-image-store.s3.amazonaws.com/0/142016/85a0b8a1-dec2-dc27-f304-8371b60427f1.png)


##補足：Android Studioの開発環境設定メモ。(Android StudioのインストールからAndroid端末の認識まで)
Android Studioのダウンロード

- https://developer.android.com/studio/index.html?hl=ja

インストール方法は次のとおり

- https://developer.android.com/studio/install.html

Ubuntu上でのスマートフォンの認識
下記のURLを参考に、 /etc/udev/rules.d/51-android.rules　を作成する。

- https://developer.android.com/studio/run/device.html

ASUSのzenfone3で稼働を確認する。
USBベンダーID ATTR{iVendor}="0b05"にする。
それ以外はドキュメントどおり。

```console: 51-android.rules
SUBSYSTEM=="usb", ATTR{idVendor}=="0b05", MODE="0666", GROUP="plugdev" 
```
51-android.rulesの参照権限を変える。

```
$ chmod a+r /etc/udev/rules.d/51-android.rules
```
Android端末でデバッグを可能にする

```:
Androidの画面上で[設定] > [端末情報] ＞[ビルド番号] を 7 回タップ。
[設定]に戻ると、[開発者向けオプション] が表示される。
[開発者向けオプション]からUSBデバッグをオンにしておく。
```

adb上でデバイスが認識されているか確認する。

```:
$ ./Android/Sdk/platform-tools/adb devices
（出力例）
　List of devices attached
　H1AZCY05L837GXZ	device

```
認識できていればAndroidStudioでもデバッグ時にデバイスが指定できるはず。



参考にさせてもらったサイト：
-「Mobile Clients: Libraries and Inproc Ethereum Nodes」
 https://github.com/ethereum/go-ethereum/wiki/Mobile-Clients:-Libraries-and-Inproc-Ethereum-Nodes
-[Mobile client not working - Permission denied #3509]
https://github.com/ethereum/go-ethereum/issues/3509
-[Qiita:Android でインターネットに接続するためのパーミッションを設定する]
 https://qiita.com/karur4n/items/5b439850caa4ae5b05d9
-[Manifest.permission]
https://developer.android.com/reference/android/Manifest.permission.html
-[Android ライブラリの作成]
https://developer.android.com/studio/projects/android-library.html?hl=ja