AndroidアプリとNode.jsで連携してHello World

「次の案件でAndroidアプリ作ってね、サーバサイドはNode.js使うよ」という話が飛んできたので軽く予習。

#目標

Androidアプリから、Node.jsで作成したサーバサイドアプリにHTTP GETリクエストを飛ばし、取得した文字列を画面に表示する。
とりあえずこれができれば、あとは大体ビジネスロジックの問題になるのではないかと。

#環境

* Windows10 64bit
* Android Studio 2.2.3
* Node.js 6.9.5

Androidアプリ開発はプライベートでやっているものの、専ら使用しているのはIntellij IDEA＋Scala。
間違いなく業務では使えないと思うので、鉄板と思われるAndroid Studioを使用。
ここで開発言語を確認するの忘れたことに気づきましたが、Javaと仮定して進めます。9割方間違いないでしょうし。
Node.jsは初めて触るので全く勝手が分かりません。とりあえずバージョンは安定版を選択しました。

#環境構築

Android StudioもNode.jsもインストーラを叩いて適当に進めるのみ。
Android Studioのインストール中にAndroid SDKのインストールが行われるようですが、これは既にインストール済みのため、既存のパスを指定することでスキップしました。

#Node.jsでサーバサイドアプリを作成

リクエストを受けたらテキストを返すだけです。

```js:server.js
const http = require('http');
const server = http.createServer(
	function (request, response) {
		response.writeHead(200, {'Content-Type': 'text/plain'});
		response.write('Hello World From Node.JS!!!');
		response.end();
	}
);
server.listen(80);
```

ES6も全く触ってないことに気づいたので、これも要予習ですね。

#Androidアプリ作成

Android Studioで新規プロジェクトを作成。Empty Activityをベースにします。

##準備

やることはGETリクエストを投げてレスポンスを表示するだけ、なのですが、Android SDKベースで実装すると結構面倒。
なので、おもむろに[OkHttp](http://square.github.io/okhttp/)を投入します。
build.gradleにOkHttp用の記載を追加。

```gradle:build.gradle
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.0.1'

    // Add
    compile 'com.squareup.okhttp3:okhttp:3.6.0'

    testCompile 'junit:junit:4.12'
}
```

インターネットアクセスのための権限の追加も忘れずに。

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

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
```

##処理を書く

プロジェクト作成時に存在しているMainActivity.javaを書き換えます。
とりあえず動けば良いやということで汚いコードになってますが。
コード中のURLはNode.jsを動かしているPCのIPアドレスです。
また、"Hello World!"を表示しているTextViewのIDを"MainText"としています。

```java:MainActivity.java
package com.gmail.lsetzl.nodejstest2;

import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.widget.TextView;

import java.io.IOException;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity {

    Handler redrawHandler;
    String text = "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        redrawHandler = new Handler();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Request request = new Request.Builder().url("http://192.168.0.7/").get().build();
        OkHttpClient client = new OkHttpClient().newBuilder().build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                // nothing
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                text = response.body().string();
                redrawHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        ((TextView)findViewById(R.id.MainText)).setText(text);
                    }
                });
            }
        });
        return super.onTouchEvent(event);
    }
}
```

#実行

コマンドプロンプトなりPowerShellからserver.jsが存在するパスに移動して

```
node server.js
```

でサーバサイドアプリを起動。

そしてAndroid Studioでアプリを実行。
とりあえずUSBで接続している実機を動作環境として実行するとアプリが起動。
で、適当な所をタップするとNode.jsにリクエストが送信され、"Hello World From Node.JS!!!"が表示されます。