Android MQTT mosquitto如何在后台运行

标签 android mqtt

我现在正在尝试使用 MQTT 库,另外两台本地主机可以相互通信 (此示例代码:https://github.com/bytehala/android-mqtt-quickstart)

但我唯一要解决的是

关闭时,无法接收消息

请告诉我如何在后台操作

我的代码 mqttcallbackhandler.java

     public class MqttCallbackHandler implements MqttCallback {

  /** {@link Context} for the application used to format and import external strings**/
      private Context context;
  /** Client handle to reference the connection that this handler is attached to**/
  private String clientHandle;

          MainActivity main;

  /**
   * Creates an <code>MqttCallbackHandler</code> object
   * @param context The application's context
   * @param clientHandle The handle to a {@link Connection} object
   */
      public MqttCallbackHandler(Context context, String clientHandle)
      {
        this.context = context;
        this.clientHandle = clientHandle;
      }

  /**
   * @see org.eclipse.paho.client.mqttv3.MqttCallback#connectionLost(java.lang.Throwable)
   */
  @Override
  public void connectionLost(Throwable cause) {
//    cause.printStackTrace();
    if (cause != null) {
      Connection c = Connections.getInstance(context).getConnection(clientHandle);
      c.addAction("Connection Lost");
      c.changeConnectionStatus(ConnectionStatus.DISCONNECTED);

      //format string to use a notification text
      Object[] args = new Object[2];
      args[0] = c.getId();
      args[1] = c.getHostName();

      String message = context.getString(R.string.connection_lost, args);

      //build intent
      Intent intent = new Intent();
      intent.setClassName(context, "org.eclipse.paho.android.service.sample.MainActivity");
      intent.putExtra("handle", clientHandle);

      //notify the user
      Notify.notifcation(context, message, intent, R.string.notifyTitle_connectionLost);
    }
  }

  /**
   * @see org.eclipse.paho.client.mqttv3.MqttCallback#messageArrived(java.lang.String, org.eclipse.paho.client.mqttv3.MqttMessage)
   */
  @Override
  public void messageArrived(String topic, MqttMessage message) throws Exception {

    //Get connection object associated with this object
    Connection c = Connections.getInstance(context).getConnection(clientHandle);

    //create arguments to format message arrived notifcation string
    String[] args = new String[2];
    args[0] = new String(message.getPayload());
    args[1] = topic+";qos:"+message.getQos()+";retained:"+message.isRetained();

    //get the string from strings.xml and format
    String messageString = context.getString(R.string.messageRecieved, (Object[]) args);

    //create intent to start activity
    Intent intent = new Intent();
    intent.setClassName(context, "org.eclipse.paho.android.service.sample.ConnectionDetails");
    intent.putExtra("handle", clientHandle);

    //format string args
    Object[] notifyArgs = new String[3];
    notifyArgs[0] = c.getId();
    notifyArgs[1] = new String(message.getPayload());
    notifyArgs[2] = topic;

    Log.d("won", "msg2=" + notifyArgs[1] + "");

    MainActivity.MessageReceive(notifyArgs[1] + "");

    //notify the user
//    Notify.notifcation(context, context.getString(R.string.notification, notifyArgs), intent, R.string.notifyTitle);
    //update client history
    c.addAction(messageString);

  }

  /**
   * @see org.eclipse.paho.client.mqttv3.MqttCallback#deliveryComplete(org.eclipse.paho.client.mqttv3.IMqttDeliveryToken)
   */
  @Override
  public void deliveryComplete(IMqttDeliveryToken token) {
    // Do nothing
  }

}

最佳答案

好吧,您可以使用在您的应用程序开始时执行的服务

在你的 list 中添加这个以便你声明你的服务

<service
        android:enabled="true"
        android:name=".Mqttservice"
/>

Mqttservice.java

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;

import org.eclipse.paho.client.mqttv3.IMqttAsyncClient;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
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.MemoryPersistence;


public class Mqttservice extends Service {
    private String ip="brokerip",port="1883";
    private final IBinder mBinder = new LocalBinder();
    private Handler mHandler;

private class ToastRunnable implements Runnable {//to toast to your main activity for some time
    String mText;
    int mtime;

    public ToastRunnable(String text, int time) {
        mText = text;
        mtime = time;
    }

    @Override
    public void run() {

        final Toast mytoast = Toast.makeText(getApplicationContext(), mText, Toast.LENGTH_LONG);
        mytoast.show();
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mytoast.cancel();
            }
        }, mtime);
    }
}

private static final String TAG = "mqttservice";
private static boolean hasWifi = false;
private static boolean hasMmobile = false;
private ConnectivityManager mConnMan;
    private volatile IMqttAsyncClient mqttClient;
private String uniqueID;


class MQTTBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {

        IMqttToken token;
        boolean hasConnectivity = false;
        boolean hasChanged = false;
        NetworkInfo infos[] = mConnMan.getAllNetworkInfo();
        for (int i = 0; i < infos.length; i++) {
            if (infos[i].getTypeName().equalsIgnoreCase("MOBILE")) {
                if ((infos[i].isConnected() != hasMmobile)) {
                    hasChanged = true;
                    hasMmobile = infos[i].isConnected();
                }
                Log.d(TAG, infos[i].getTypeName() + " is " + infos[i].isConnected());
            } else if (infos[i].getTypeName().equalsIgnoreCase("WIFI")) {
                if ((infos[i].isConnected() != hasWifi)) {
                    hasChanged = true;
                    hasWifi = infos[i].isConnected();
                }
                Log.d(TAG, infos[i].getTypeName() + " is " + infos[i].isConnected());
            }
        }
        hasConnectivity = hasMmobile || hasWifi;
        Log.v(TAG, "hasConn: " + hasConnectivity + " hasChange: " + hasChanged + " - " + (mqttClient == null || !mqttClient.isConnected()));
        if (hasConnectivity && hasChanged && (mqttClient == null || !mqttClient.isConnected())) {
                doConnect();

        }



    }
}


public class LocalBinder extends Binder {
    public Mqttservice getService() {
        // Return this instance of LocalService so clients can call public methods
        return Mqttservice.this;
    }
}

@Override
public IBinder onBind(Intent intent) {
    return mBinder;
}

public void publish(String topic, MqttMessage message) {
    SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);// we create a 'shared" memory where we will share our preferences for the limits and the values that we get from onsensorchanged
    try {

        mqttClient.publish(topic, message);

    } catch (MqttException e) {
        e.printStackTrace();
    }

}


@Override
public void onCreate() {

    mHandler = new Handler();//for toasts
    IntentFilter intentf = new IntentFilter();
    setClientID();
    intentf.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
    registerReceiver(new MQTTBroadcastReceiver(), new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
    mConnMan = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    Log.d(TAG, "onConfigurationChanged()");
    android.os.Debug.waitForDebugger();
    super.onConfigurationChanged(newConfig);

}

@Override
public void onDestroy() {
    super.onDestroy();
    Log.d("Service", "onDestroy");

}


private void setClientID() {
    uniqueID = android.provider.Settings.Secure.getString(getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
    Log.d(TAG, "uniqueID=" + uniqueID);

}


private void doConnect() {
    String broker = "tcp://" + ip + ":" + port;
    Log.d(TAG, "mqtt_doConnect()");
    IMqttToken token;
    MqttConnectOptions options = new MqttConnectOptions();
    options.setCleanSession(true);
    options.setMaxInflight(100);//handle more messages!!so as not to disconnect
    options.setAutomaticReconnect(true);
    options.setConnectionTimeout(1000);
    try {

        mqttClient = new MqttAsyncClient(broker, uniqueID, new MemoryPersistence());
        token = mqttClient.connect(options);
        token.waitForCompletion(3500);

        mqttClient.setCallback(new MqttCallback() {
            @Override
            public void connectionLost(Throwable throwable) {
                try {
                    mqttClient.disconnectForcibly();
                    mqttClient.connect();
                } catch (MqttException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void messageArrived(String topic, MqttMessage msg) throws Exception {
                Log.i(TAG, "Message arrived from topic " + topic);

                if (topic.equals("Sensors/message")) {


                } else if (topic.equals("Sensors/" + uniqueID)) {
                }
                else{

                }

            }

            @Override
            public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
                System.out.println("published");
            }
        });

        mqttClient.subscribe("Sensors/" + uniqueID, 0);
        mqttClient.subscribe("Sensors/message", 0);

    } catch (MqttSecurityException e) {
        e.printStackTrace();
    } catch (MqttException e) {
        switch (e.getReasonCode()) {
            case MqttException.REASON_CODE_BROKER_UNAVAILABLE:
                mHandler.post(new ToastRunnable("WE ARE OFFLINE BROKER_UNAVAILABLE!", 1500));
                break;
            case MqttException.REASON_CODE_CLIENT_TIMEOUT:
                mHandler.post(new ToastRunnable("WE ARE OFFLINE CLIENT_TIMEOUT!", 1500));
                break;
            case MqttException.REASON_CODE_CONNECTION_LOST:
                mHandler.post(new ToastRunnable("WE ARE OFFLINE CONNECTION_LOST!", 1500));
                break;
            case MqttException.REASON_CODE_SERVER_CONNECT_ERROR:
                Log.v(TAG, "c" + e.getMessage());
                e.printStackTrace();
                break;
            case MqttException.REASON_CODE_FAILED_AUTHENTICATION:
                Intent i = new Intent("RAISEALLARM");
                i.putExtra("ALLARM", e);
                Log.e(TAG, "b" + e.getMessage());
                break;
            default:
                Log.e(TAG, "a" + e.getMessage());
        }
    }
    mHandler.post(new ToastRunnable("WE ARE ONLINE!", 500));

}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.v(TAG, "onStartCommand()");
    return START_STICKY;
}

在你的 main 中 oncreate 添加这个

Intent mymqttservice_intent = new Intent(this, Mqttservice.class);
        startService(mymqttservice_intent);

关于Android MQTT mosquitto如何在后台运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38005444/

相关文章:

android - 使用 ListFragment 填充自定义 View 列表

android - clientID 有什么用?

go - 使用 Goroutine 订阅 MQTT 消息

Android Skobbler Maps 2.4 SDK - 离线/预 bundle map 崩溃

c - ESP32 无法连接到 MQTT 代理 : mqtt_client: Error network response

mqtt - 使用 MQTT 发送命令 - 有模式吗?

node.js - 是否可以将 MQTT 客户端连接到以 Node.JS 作为中间网关的 RabbitMQ?

Android通话记录日期转换

java - 使用 PyJnius 从 Python 实现 Java 接口(interface)

android - Android 模拟器、Visual Studio、Xamarin 上的屏幕分辨率较低