【Android】Androidでのredis client作成 - publish/subscribe編

# 00. はじめに
redisはいわゆるNoSQLデータベースの一つで、その名(REmote DIctionary Server)の通りキー・バリューDBです。
メッセージング機能を有しているので、一つのPCから複数のPCにメッセージを送ることが可能です。
![概略.png](https://qiita-image-store.s3.amazonaws.com/0/235452/452e0ab3-43b4-4974-f730-b4779b8f5984.png)
Androidでメッセージの送受信を行うことができれば、Android端末をリモコンとするアプリケーションの作成も容易になるので、その方法を記述していきます。
![Android redis.png](https://qiita-image-store.s3.amazonaws.com/0/235452/2fa1dd85-9e67-8180-3201-b9609727fbf4.png)

# 01. Android Projectへの追加
今回はjedisというライブラリを使用します。
まずライブラリを使用するため、gradleのdependenciesに以下を追加します。

```gradle
compile 'redis.clients:jedis:2.9.0'
```

次にREmoteの名の通り、ネットワークを使用するのでパーミッションを追加します。
（ビルド後にパーミッション忘れてたのに気付くのはあるあるだと思う）

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

また、接続先redisのprotected-modeをOFFっておきます。

```bush:/etc/redis/redis.conf
protected-mode no
```

# 02. publish
publishを行うのは簡単です。

```java
private void publish(final String host, final int port, final String channel, final String message) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            if(!TextUtils.isEmpty(host) && port > 0) {
                try {
                    // 指定したホスト、ポートでJedisオブジェクトを生成する
                    Jedis jedis = new Jedis(host, port);
                    // publish
                    jedis.publish(channel, message);
                    // 切断
                    jedis.quit();
                } catch (Exception e) {
                    // pass
                }
            }
        }
    }).start();
}
```

AndroidではUI Threadで通信処理を行うことができないので、まず別Threadを立てます。
そして立てたThread内でjedisオブジェクトを作成し、publishを行います。
最後に切断を行って完了です。
簡単でしょ？

# 03. subscribe
subscribeは少し面倒です。
まず、subscribe結果を受け取るJedisPubSubオブジェクトを作成します。
（作成はMain Thread内でOK）

```java
final JedisPubSub jedisPubSub = new JedisPubSub() {
    // subscribeで受信した際に呼ばれる
    @Override
    public void onMessage(final String channel, final String message) {
        Log.i(TAG, "onMessage(channel:" + channel + ", message:" + message + ")");
    }

    // psubscribeで受信した際に呼ばれる
    @Override
    public void onPMessage(String pattern, String channel, String message) {
        Log.i(TAG, "onPMessage(pattern:" + pattern + ", channel:" + channel + ", message:" + message + ")");
    }

    // subscribe開始時に呼ばれる
    @Override
    public void onSubscribe(String channel, int subscribedChannels) {
        Log.i(TAG, "onSubscribe(channel:" + channel + ", subscribedChannels:" + subscribedChannels + ")");
    }

    // unsubscribe時に呼ばれる
    @Override
    public void onUnsubscribe(String channel, int subscribedChannels) {
        Log.i(TAG, "onUnsubscribe(channel:" + channel + ", subscribedChannels:" + subscribedChannels + ")");
    }

    // psubscribeに呼ばれる
    @Override
    public void onPSubscribe(String pattern, int subscribedChannels) {
        Log.i(TAG, "onPSubscribe(pattern:" + pattern + ", subscribedChannels:" + subscribedChannels + ")");
    }

    // punsubscribe時に呼ばれる
    @Override
    public void onPUnsubscribe(String pattern, int subscribedChannels) {
        Log.i(TAG, "onPUnsubscribe(pattern:" + pattern + ", subscribedChannels:" + subscribedChannels + ")");
    }
};
```

Android Studioに自動生成させるとスーパークラスのメソッドを呼ぶように記述されますが、スーパークラスでは何もしていないので呼ぶ必要はありません。
次に別スレッド（Main Thread外）にてsubscribeを開始します。

```java
new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            // 指定したホスト、ポートでJedisオブジェクトを生成する
            Jedis jedis = new Jedis(mHost, mPort);
            // channelを指定してsubscribeを開始する
            jedis.subscribe(jedisPubSub, channels);
            // 接続終了依頼
            jedis.quit();
        } catch (Exception e) {
            // pass
        }
    }
}).start();
```

以上でsubscribeを行えます。
subscribeを終了する際は引数で渡したJedisPubSubオブジェクトのJedisPubSub#unsubscribe()をコールします。

```java
new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            jedisPubSub.unsubscribe();
        } catch (Exception e) {
            // pass
        }
    }
}).start();
```

# 04. サンプルアプリ
<img width=50% src="https://qiita-image-store.s3.amazonaws.com/0/235452/74fda08e-b254-845e-5048-329be46e5167.png"/>
今回のpublish/subscribeに関してサンプルアプリを作成したので、詳しくは以下リポジトリのMainActivity.javaを見てください。
https://github.com/entan05/RedisTest

# 98. 参考
Jedis |　https://github.com/xetorthio/jedis
Android Studioでライブラリを取り込む３つの方法 | http://sakebook.hatenablog.com/entry/2014/08/17/004540
Cannot connect to redis using jedis | https://stackoverflow.com/questions/37867633/cannot-connect-to-redis-using-jedis
Android でインターネットに接続するためのパーミッションを設定する | https://qiita.com/karur4n/items/5b439850caa4ae5b05d9
A Simple Jedis Publish / Subscribe Example | http://basrikahveci.com/2012/06/20/a-simple-jedis-publish-subscribe-example/

# 99. 変更履歴

|日付|変更内容|
|:--|:--|
|2018/02/26|投稿|
|2018/03/01|サンプルアプリのコードをGithubへのリンクへ変更|