AndroidでMQTTのPublisher/Subscriberを実装する場合、Paho Android Serviceライブラリを利用するのが便利そうです。このライブラリを利用したMQTTクライアントの作成手順をメモしました。
事前準備
android API 19が必要のため、あらかじめSDKマネージャでインスールしておきます。導入には下記の2つのjarファイルが必要なので、まずはこれらを準備します。
org.eclipse.paho.client.mqttv3-1.0.1.jar
下記の場所にあるようなので、ダウンロードします。
curl -O https://repo.eclipse.org/content/repositories/paho-releases/org/eclipse/paho/org.eclipse.paho.client.mqttv3/1.0.1/org.eclipse.paho.client.mqttv3-1.0.1.jar
org.eclipse.paho.android.service.jar
探しても見つからなかったため、ソースファイルから作成します。
git clone http://git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.java.git
cloneしてきたプロジェクトをeclipseにインポートし、まずandroid API 19のライブラリ(android.jar)のある場所にパスを通しておきます。そして、プロジェクト直下にlibsディレクトリを作って、そこに下記のjarファイルをコピーします。
- org.eclipse.paho.client.mqttv3-1.0.1.jar
- support-v4-r7.jar
support-v4-r7.jarはどこかから入手してくるか、もしくはpom.xmlのparentのエラーをなくしてmavenの依存ライブラリより入手します。
修正前
...
<parent>
<groupId>org.eclipse.paho</groupId>
<artifactId>android-service-parent</artifactId>
<version>1.0.1</version>
</parent>
<artifactId>org.eclipse.paho.android.service</artifactId>
<packaging>jar</packaging>
...
修正後
...
<groupId>org.eclipse.paho</groupId>
<version>1.0.1</version>
<artifactId>org.eclipse.paho.android.service</artifactId>
...
※org.eclipse.pahoのdependencyでエラーが出るけれど、support-v4-r7.jarが入手できていれば良いです。
続いてexportjar.xmlをAnt実行します。androidjarのパスがうまく指定されずにエラーとなっていたので、androidjarのパスをうまく指定するように上書きして実行しました。
修正前
<property name="androidjar" value="${sdk.dir}/platforms/android-${androidAPILevel}"/>
修正後
<property name="androidjar" value="/Applications/adt-bundle-mac/sdk/platforms/android-${androidAPILevel}"/>
プロジェクト直下にdistディレクトリが作成され、そこにorg.eclipse.paho.android.service.jarが作成されていれば成功です。
サンプルコード作成
適当なプロジェクトを作成し、そこのlibsディレクトリに下記jarをコピーします。
AndroidManifestを開き、Paho Android Serviceを利用するのに必要なPermissionとServiceを追加します。Main Activityは"MQTTMainActivity"としました。
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.mqttsample" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="MQTTMainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <service android:name="org.eclipse.paho.android.service.MqttService" > </service> </application> </manifest>
MQTTMainActivityを次のよう書きました。onCreateでMQTTサーバに接続し、onPauseでpublishするコードです。
MQTTMainActivity.java
package com.example.mqttsample; import org.eclipse.paho.android.service.MqttAndroidClient; import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttPersistenceException; import android.app.Activity; import android.os.Bundle; public class MQTTMainActivity extends Activity { MqttAndroidClient mqttAndroidClient; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mqttAndroidClient = new MqttAndroidClient(this, "tcp://xxx.xxx.xxx.xxx:1883", "piyo"); // (1) try { mqttAndroidClient.connect(); // (2) } catch (MqttException e) { e.printStackTrace(); } } @Override public void onPause() { super.onPause(); try { mqttAndroidClient.publish("topic/hoge", "hello world".getBytes(), 0, false); // (3) } catch (MqttPersistenceException e) { e.printStackTrace(); } catch (MqttException e) { e.printStackTrace(); } } }
(1) MqttAndroidClientのインスタンス作成時に引数としてContext、Server URI、Client IDを指定しています。Server URIはMQTTサーバのURLです。
(2) サーバに接続します。connectメソッドの引数には接続オプションやコールバッククラスを指定することもできます。
(3) MQTTサーバにpublishします。引数はそれぞれ、Topic、メッセージ、QoS、Retainです。
実行確認
MQTTの挙動をMacで確認する - マイナー・マイナーの手順を参考にBrokerとSubscriberを起動しておきます。そしてMQTTMainActivityを起動し、アプリがバックグラウンド状態になるたびにSubscriberのコンソールに"hello world"が表示されることを確認します。