这段时间学习了推送技术,对xmpp和mqtt 协议做了下比较。
xmpp基于xml信息传递,所以传输信息量比较大,在保持长链接情况下功耗会比较大。
可能还是比较适合用来做聊天之类的通讯应用,而对于智能和物联低功耗设备的推送来说,感觉比较笨重。
而mqtt协议就是针对网络带宽低,高延时,通信不稳定的环境设计的,特别适合物联设备。低通讯量连接保持,简约轻便。
可见,提供的功能已经很完整了。
mqtt 详细协议可见:
http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
中文版的:
http://wenku.baidu.com/link?url=eyG24CVjmmA_J5KbR_Y8xzDOkq5YsrChshcHxcZQzav2OcVE9KNxukXr1uix1ACPTw36QIKwHRTmLqjM1Bm7qqPwVQYG9BzIv_BdJvPoU8_
现在有很多基于mqtt的开源实现,包含客户端和服务器端(或者说中间件)。
我做了一个demo,客户选用paho 提供client-mqtt 和 android server库,中间件是apollo。
apollo 下载地址:
http://activemq.apache.org/apollo/download.html
下载完解压按照里面的readme 建立和运行自己的broker,依赖java运行环境。
client-mqtt 和 android server库地址:
打包很简单,新建org\eclipse\paho\client\mqttv3\internal\nls 目录,把它们都放到这个目录下。
然后在org 目录外执行 jar -cvf properties.jar ./* , 之后把properties.jar 放入libs下。
4. 在androidManifest 里面添加
<service android:name="org.eclipse.paho.android.service.MqttService"> service>5. 在自己的activity或者service里面通过调用paho.android.service MqttAndroidClient 类实现发布和订阅。
package com.tww.test;
import android.content.ComponentName;
import android.content.Context;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerManager;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.android.service.MqttTraceHandler;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttSecurityException;
import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence;
import java.io.IOException;
import java.io.InputStream;
import javax.net.ssl.SSLSocketFactory;
public class MainActivity extends AppCompatActivity implements View.OnClickListener,ServiceConnection, MqttCallback, IMqttActionListener,MqttTraceHandler {
private static final String TAG = "MainActivity";
private Button mButton;
private MqttAndroidClient mMqttAndroidClient;
private String host = "tcp://192.168.43.224:61613";
private String userName = "admin";
private String passWord = "password";
private IMqttToken mConnectToken;
private PowerManager.WakeLock mWakeLock;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = (Button) findViewById(R.id.button);
mButton.setOnClickListener(this);
mMqttAndroidClient = new MqttAndroidClient(this,host,"123456789",new MqttDefaultFilePersistence(getCacheDir().getAbsolutePath()));
mMqttAndroidClient.setCallback(this);
mMqttAndroidClient.setTraceEnabled(true);
mMqttAndroidClient.setTraceCallback( this);
Log.d(TAG,"onCreate");
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(true);
options.setUserName(userName);
options.setPassword(passWord.toCharArray());
options.setConnectionTimeout(60);
options.setKeepAliveInterval(2*60);
options.setMqttVersion(3);
try {
InputStream caInput = getResources().getAssets().open("keystore.bks");
if(caInput!=null){
Log.d(TAG,"do setSocketFactory");
SSLSocketFactory sslSocketFactory = mMqttAndroidClient.getSSLSocketFactory(caInput,"password");
options.setSocketFactory(sslSocketFactory);
}
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG,"do connect IOException:"+e);
}catch (MqttSecurityException e) {
e.printStackTrace();
Log.e(TAG,"do connect MqttSecurityException:"+e);
}
try {
Log.d(TAG,"do connect");
mConnectToken = mMqttAndroidClient.connect(options,this);
} catch (MqttException e) {
Log.e(TAG,"connect MqttException:"+e);
e.printStackTrace();
}
PowerManager powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
mWakeLock.setReferenceCounted(false);
mWakeLock.acquire();
}
@Override
protected void onDestroy(){
super.onDestroy();
if(mMqttAndroidClient != null){
try {
mMqttAndroidClient.disconnect();
} catch (MqttException e) {
e.printStackTrace();
}
mMqttAndroidClient.close();
}
mWakeLock.release();
}
@Override
public void onClick(View v) {
if(v.getId()==R.id.button){
}
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG,"onServiceConnected");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG,"onServiceDisconnected");
}
@Override
public void connectionLost(Throwable throwable) {
Log.d(TAG,"connectionLost");
}
@Override
public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
Log.d(TAG,"messageArrived:"+mqttMessage.toString());
}
@Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
Log.d(TAG,"deliveryComplete");
}
@Override
public void onSuccess(IMqttToken iMqttToken) {
if(mConnectToken.equals(iMqttToken)){
try {
Log.d(TAG,"connect success, do subscribe");
mMqttAndroidClient.subscribe("test",1);
} catch (MqttException e) {
e.printStackTrace();
}
}
}
@Override
public void onFailure(IMqttToken iMqttToken, Throwable throwable) {
if(mConnectToken.equals(iMqttToken)){
Log.d(TAG,"onFailure success:"+throwable.toString());
}
}
@Override
public void traceDebug(String s, String s1) {
Log.d(s,s1);
}
@Override
public void traceError(String s, String s1) {
Log.e(s,s1);
}
@Override
public void traceException(String s, String s1, Exception e) {
Log.e(s,s1,e);
}
}