0

我有一个大问题,我找不到解决方案。需要你的帮助。

当我尝试使用 service 在活动中仅发送一条消息时,它可以工作。但是当我尝试在另一个之后发送 2 条消息(这意味着一个接一个),使用相同的 publishTopic2 和 pushMsg2 发送消息两次。

代码是:

PushService.actionPush(getApplicationContext(),publishTopic1,pushMsg1);
PushService.actionPush(getApplicationContext(),publishTopic2,pushMsg2);

1-这是由于同步关键字的错误使用造成的吗?2-是否可以在没有的情况下一个接一个地发送两个味精

public class PushService
        extends Service
{
    // this is the log tag
    public static final String TAG = "DemoPushService";
    public static String IncomingText = "";

    private static String PushMesaj = "";

    // the IP address, where your MQTT broker is running.
    private static final String MQTT_HOST = "";
    // the port at which the broker is running.
    private static int MQTT_BROKER_PORT_NUM = 1883;
    // Let's not use the MQTT persistence.
    private static MqttClientPersistence MQTT_PERSISTENCE = null;
    // We don't need to remember any state between the connections, so we use a
    // clean start.
    private static boolean MQTT_CLEAN_START = true;
    // Let's set the internal keep alive for MQTT to 15 mins. I haven't tested
    // this value much. It could probably be increased.
    private static short MQTT_KEEP_ALIVE = 60 * 15;
    // Set quality of services to 0 (at most once delivery), since we don't want
    // push notifications
    // arrive more than once. However, this means that some messages might get
    // lost (delivery is not guaranteed)
    // private static int[] MQTT_QUALITIES_OF_SERVICE = { 0 } ;
    private static int MQTT_QUALITY_OF_SERVICE = 2;
    // The broker should not retain any messages.
    // private static boolean MQTT_RETAINED_PUBLISH = false;

    // MQTT client ID, which is given the broker. In this example, I also use
    // this for the topic header.
    // You can use this to run push notifications for multiple apps with one
    // MQTT broker.
    public static String MQTT_CLIENT_ID = "begining";
    public static String SUBSCRIBE_TOPIC = "begining";
    private static String PUBLISH_TOPIC = "begining";
    // These are the actions for the service (name are descriptive enough)
    private static final String ACTION_START = MQTT_CLIENT_ID + ".START";
    private static final String ACTION_STOP = MQTT_CLIENT_ID + ".STOP";
    private static final String ACTION_SUBSCRIBE = MQTT_CLIENT_ID
            + ".SUBSCRIBE";
    private static final String ACTION_PUBLISH = MQTT_CLIENT_ID + ".PUBLISH";

    private static final String ACTION_KEEPALIVE = MQTT_CLIENT_ID
            + ".KEEP_ALIVE";
    private static final String ACTION_PUSHMESSAGE = MQTT_CLIENT_ID
            + ".PUSH_MESSAGE";
    private static final String ACTION_PUSHMESSAGE2 = MQTT_CLIENT_ID
            + ".PUSH_MESSAGE";
    private static final String ACTION_RECONNECT = MQTT_CLIENT_ID
            + ".RECONNECT";

    // Connection log for the push service. Good for debugging.
    private ConnectionLog mLog;

    // Connectivity manager to determining, when the phone loses connection
    private ConnectivityManager mConnMan;
    // Notification manager to displaying arrived push notifications
    private NotificationManager mNotifMan;

    // Whether or not the service has been started.
    private boolean mStarted;

    // This the application level keep-alive interval, that is used by the
    // AlarmManager
    // to keep the connection active, even when the device goes to sleep.
    private static final long KEEP_ALIVE_INTERVAL = 1000 * 60 * 28;

    // Retry intervals, when the connection is lost.
    private static final long INITIAL_RETRY_INTERVAL = 1000 * 10;
    private static final long MAXIMUM_RETRY_INTERVAL = 1000 * 60 * 30;

    // Preferences instance
    private SharedPreferences mPrefs;
    // We store in the preferences, whether or not the service has been started
    public static final String PREF_STARTED = "isStarted";
    // We also store the deviceID (target)
    public static final String PREF_DEVICE_ID = "deviceID";
    // We store the last retry interval
    public static final String PREF_RETRY = "retryInterval";

    // Notification title
    public static String NOTIF_TITLE = "Hey !!!";
    // Notification id
    private static final int NOTIF_CONNECTED = 0;

    // This is the instance of an MQTT connection.
    private MQTTConnection mConnection;
    private long mStartTime;

    private static clsUser yourInfo;
    public static clsOnlineUsers onlineUsers;
    private static clsUser myInfo;

    // Static method to start the service
    public static void actionStart(Context ctx)
    {
        Intent i = new Intent(ctx, PushService.class);
        i.setAction(ACTION_START);
        ctx.startService(i);
    }

    public static void actionSubscribe(Context ctx)
    {
        Intent i = new Intent(ctx, PushService.class);
        i.setAction(ACTION_SUBSCRIBE);
        ctx.startService(i);
    }

    public static void actionPublish(Context ctx)
    {
        Intent i = new Intent(ctx, PushService.class);
        i.setAction(ACTION_PUBLISH);
        ctx.startService(i);
    }

    // Static method to stop the service
    public static void actionStop(Context ctx)
    {
        Intent i = new Intent(ctx, PushService.class);
        i.setAction(ACTION_STOP);
        ctx.startService(i);
    }

    // Static method to send a keep alive message
    public static void actionPing(Context ctx)
    {
        Intent i = new Intent(ctx, PushService.class);
        i.setAction(ACTION_KEEPALIVE);
        ctx.startService(i);
    }

    public static void actionPush(Context ctx, String publishTopic,
            String pushMsg)
    {
        PUBLISH_TOPIC = publishTopic;
        PushMesaj = pushMsg;
        Intent i = new Intent(ctx, PushService.class);
        i.setAction(ACTION_PUSHMESSAGE);
        ctx.startService(i);
    }

    @Override
    public void onCreate()
    {
        super.onCreate();

        log("Creating service");
        mStartTime = System.currentTimeMillis();

        try {
            mLog = new ConnectionLog();
            Log.i(TAG, "Opened log at " + mLog.getPath());
        } catch (IOException e) {
            Log.e(TAG, "Failed to open log", e);
        }

        // Get instances of preferences, connectivity manager and notification
        // manager
        mPrefs = getSharedPreferences(TAG, MODE_PRIVATE);
        mConnMan = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
        mNotifMan = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        mPrefs.edit().putLong(PREF_RETRY, INITIAL_RETRY_INTERVAL).commit();
        mPrefs.edit().putBoolean(PREF_STARTED, false).commit();

        /*
         * If our process was reaped by the system for any reason we need to
         * restore our state with merely a call to onCreate. We record the last
         * "started" value and restore it here if necessary.
         */
        handleCrashedService();
    }

    // This method does any necessary clean-up need in case the server has been
    // destroyed by the system
    // and then restarted
    private void handleCrashedService()
    {
        if (wasStarted() == true) {
            log("Handling crashed service...");
            // stop the keep alives
            // stopKeepAlives();

            // Do a clean start
            start();
        }
    }

    @Override
    public void onDestroy()
    {
        log("Service destroyed (started=" + mStarted + ")");

        // Stop the services, if it has been started
        if (mStarted == true) {
            stop();
        }

        try {
            if (mLog != null)
                mLog.close();
        } catch (IOException e) {
        }
    }

    @Override
    public synchronized void onStart(Intent intent, int startId)
    {
        super.onStart(intent, startId);
        log("Service started with intent=" + intent);
        if (intent == null) {
            start();
            return;
        }
        // Do an appropriate action based on the intent.
        if (intent.getAction().equals(ACTION_STOP) == true) {
            stop();
            stopSelf();
        } else if (intent.getAction().equals(ACTION_START) == true) {
            start();
        } else if (intent.getAction().equals(ACTION_KEEPALIVE) == true) {
            keepAlive();
        } else if (intent.getAction().equals(ACTION_PUBLISH) == true) {
            publish();
        } else if (intent.getAction().equals(ACTION_SUBSCRIBE) == true) {
            subscribe();
        } else if (intent.getAction().equals(ACTION_PUSHMESSAGE) == true) {
            sendMessage();
        } else if (intent.getAction().equals(ACTION_RECONNECT) == true) {
            if (isNetworkAvailable()) {
                reconnectIfNecessary();
            }
        }
    }

    private void subscribe()
    {
        // TODO Auto-generated method stub
        try {
            mConnection.subscribeToTopic(SUBSCRIBE_TOPIC);
        } catch (MqttException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private void publish()
    {

        try {
            // Send a keep alive, if there is a connection.
            if (mStarted == true && mConnection != null) {
                mConnection.sendPushMessage(1);
            }
        } catch (MqttException e) {
            log("MqttException: "
                    + (e.getMessage() != null ? e.getMessage() : "NULL"), e);

            mConnection.disconnect();
            mConnection = null;
            cancelReconnect();
        }
    }

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

    // log helper function
    private void log(String message)
    {
        log(message, null);
    }

    private void log(String message, Throwable e)
    {
        if (e != null) {
            Log.e(TAG, message, e);

        } else {
            Log.i(TAG, message);
        }

        if (mLog != null) {
            try {
                mLog.println(message);
            } catch (IOException ex) {
            }
        }
    }

    // Reads whether or not the service has been started from the preferences
    private boolean wasStarted()
    {
        return mPrefs.getBoolean(PREF_STARTED, false);
    }

    // Sets whether or not the services has been started in the preferences.
    private void setStarted(boolean started)
    {
        mPrefs.edit().putBoolean(PREF_STARTED, started).commit();
        mStarted = started;
    }

    private synchronized void start()
    {
        log("Starting service...");

        // Do nothing, if the service is already running.
        if (mStarted == true) {
            Log.w(TAG, "Attempt to start connection that is already active");
            return;
        }

        // Establish an MQTT connection
        connect();

        // Register a connectivity listener
        registerReceiver(mConnectivityChanged, new IntentFilter(
                ConnectivityManager.CONNECTIVITY_ACTION));

    }

    private synchronized void stop()
    {
        // Do nothing, if the service is not running.
        if (mStarted == false) {
            Log.w(TAG, "Attempt to stop connection not active.");
            return;
        }

        // Save stopped state in the preferences
        setStarted(false);

        // Remove the connectivity receiver
        unregisterReceiver(mConnectivityChanged);
        // Any existing reconnect timers should be removed, since we explicitly
        // stopping the service.
        cancelReconnect();

        // Destroy the MQTT connection if there is one
        if (mConnection != null) {
            mConnection.disconnect();
            mConnection = null;
        }
    }

    private clsUser setUserInfo(String deviceId)
    {
        clsUser u = new clsUser();

        dbUser du = new dbUser(getApplicationContext(), dbUser.DATABASE_NAME,
                null, dbUser.DATABASE_VERSION);

        Cursor c1 = du.Getby(null, null, null, null, null, null, null, null,
                null, deviceId, null, null, null);

        u = du.setProperties(c1);
        c1.close();
        du.close();
        return u;

    }

    //
    private synchronized void connect()
    {
        log("Connecting...");

        // Create a new connection only if the device id is not NULL
        if (MQTT_CLIENT_ID == null) {
            log("Device ID not found.");
        } else {
            try {
                MQTT_CLIENT_ID = Config.id(getApplication());
                myInfo = setUserInfo(MQTT_CLIENT_ID);
                mConnection = new MQTTConnection(MQTT_HOST, "user/"
                        + MQTT_CLIENT_ID + "/#");

            } catch (MqttException e) {
                // Schedule a reconnect, if we failed to connect
                log("MqttException: "
                        + (e.getMessage() != null ? e.getMessage() : "NULL"));
                if (!isNetworkAvailable()) {
                    scheduleReconnect(mStartTime);
                }
            }
            setStarted(true);
        }
    }

    private synchronized void keepAlive()
    {
        try {
            // Send a keep alive, if there is a connection.
            if (mStarted == true && mConnection != null) {
                mConnection.sendKeepAlive();
            }
        } catch (MqttException e) {
            log("MqttException: "
                    + (e.getMessage() != null ? e.getMessage() : "NULL"), e);

            mConnection.disconnect();
            mConnection = null;
            cancelReconnect();
        }
    }

    private void sendMessage()
    {
        try {
            // Send a keep alive, if there is a connection.
            if (mStarted == true && mConnection != null) {
                mConnection.sendPushMessage(); // this does the job
            }
        } catch (MqttException e) {
            log("MqttException: "
                    + (e.getMessage() != null ? e.getMessage() : "NULL"), e);

            mConnection.disconnect();
            mConnection = null;
            cancelReconnect();
        }
    }

    // Schedule application level keep-alives using the AlarmManager
    private void startKeepAlives()
    {
        Intent i = new Intent();
        i.setClass(this, PushService.class);
        i.setAction(ACTION_KEEPALIVE);
        PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
        AlarmManager alarmMgr = (AlarmManager) getSystemService(ALARM_SERVICE);
        alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP,
                System.currentTimeMillis() + KEEP_ALIVE_INTERVAL,
                KEEP_ALIVE_INTERVAL, pi);
    }

    // Remove all scheduled keep alives
    private void stopKeepAlives()
    {
        Intent i = new Intent();
        i.setClass(this, PushService.class);
        i.setAction(ACTION_KEEPALIVE);
        PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
        AlarmManager alarmMgr = (AlarmManager) getSystemService(ALARM_SERVICE);
        alarmMgr.cancel(pi);
    }

    // We schedule a reconnect based on the starttime of the service
    public void scheduleReconnect(long startTime)
    {
        // the last keep-alive interval
        long interval = mPrefs.getLong(PREF_RETRY, INITIAL_RETRY_INTERVAL);

        // Calculate the elapsed time since the start
        long now = System.currentTimeMillis();
        long elapsed = now - startTime;

        log(String.valueOf(elapsed));

        // Set an appropriate interval based on the elapsed time since start
        if (elapsed < interval) {
            interval = Math.min(interval * 4, MAXIMUM_RETRY_INTERVAL);
        } else {
            interval = INITIAL_RETRY_INTERVAL;
        }

        log("Rescheduling connection in " + interval + "ms.");

        // Save the new internval
        mPrefs.edit().putLong(PREF_RETRY, interval).commit();

        // Schedule a reconnect using the alarm manager.
        Intent i = new Intent();
        i.setClass(this, PushService.class);
        i.setAction(ACTION_RECONNECT);
        PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
        AlarmManager alarmMgr = (AlarmManager) getSystemService(ALARM_SERVICE);
        alarmMgr.set(AlarmManager.RTC_WAKEUP, now + interval, pi);
    }

    // Remove the scheduled reconnect
    public void cancelReconnect()
    {
        Intent i = new Intent();
        i.setClass(this, PushService.class);
        i.setAction(ACTION_RECONNECT);
        PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
        AlarmManager alarmMgr = (AlarmManager) getSystemService(ALARM_SERVICE);
        alarmMgr.cancel(pi);
    }

    private synchronized void reconnectIfNecessary()
    {
        if (mStarted == true && mConnection == null) {
            log("Reconnecting...");
            connect();
        }
    }

    private class MQTTConnection
            implements MqttCallback
    {
        MqttClient mqttClient = null;
        MqttConnectOptions conOpt;
        String myDeviceId;

        // Creates a new connection given the broker address and initial topic
        public MQTTConnection(String brokerHostName, String initTopic)
                throws MqttException
        {
            // Create connection spec

        }

        private void publish(String topicName, int qos, String payload,
                boolean retained) throws MqttException
        {

        }

        /*
         * Sends a message to the message broker, requesting that it be
         * published to the specified topic.
         */
        private void publishToTopic(String topicName, String message)
                throws MqttException
        {

            if ((mqttClient == null) || (mqttClient.isConnected() == false)) {
                // quick sanity check - don't try and publish if we don't have
                // a connection
                log("No connection to public to");
            } else {
                publish(topicName, MQTT_QUALITY_OF_SERVICE, message, false);
            }

        }

        /*
         * Send a request to the message broker to be sent messages published
         * with the specified topic name. Wildcards are allowed.
         */
        private void subscribeToTopic(String topicName1) throws MqttException
        {

            if ((mqttClient == null) || (mqttClient.isConnected() == false)) {
                // quick sanity check - don't try and subscribe if we don't have
                // a connection
                log("Subscribtion failed : Connection error" + "No connection");
            } else {

                mqttClient.subscribe(topicName1, 0);
                Log.v(TAG, "Subscribe To : " + topicName1);

            }
        }

        public void sendPushMessage(int sira) throws MqttException
        {

            publishToTopic(PUBLISH_TOPIC, PushMesaj);
        }
    }

}
4

1 回答 1

1

当您调用 时actionPush(),它会执行以下操作:

    PUBLISH_TOPIC = publishTopic;
    PushMesaj = pushMsg;

它将参数保存在private static变量中,然后调用startService. 如果您这样做两次,您将private static使用第二组参数覆盖变量。

您需要了解对的调用startService()不是同步的。它不会立即启动服务并onStart()在方法返回之前调用。该服务将启动,并且调用onStart()将在稍后的某个时间发生(这里的时间不受您的控制)。

您希望将这些参数放在Intent用于启动服务的 中,并从Intentin 中检索参数onStart()。您不能可靠地使用static变量来执行此操作。

编辑:添加代码细节

改成actionPush()这样:

static final String EXTRA_TOPIC = "EXTRA_TOPIC";
static final String EXTRA_MESSAGE = "EXTRA_MESSAGE";

public static void actionPush(Context ctx, String publishTopic,
        String pushMsg)
{
    Intent i = new Intent(ctx, PushService.class);
    i.setAction(ACTION_PUSHMESSAGE);
    i.putExtra(EXTRA_TOPIC, publishTopic);
    i.putExtra(EXTRA_MESSAGE, pushMsg);
    ctx.startService(i);
}

并且onStart()您可以从以下内容中获取论点Intent

String topic = intent.getStringExtra(EXTRA_TOPIC);
String message = intent.getStringExtra(EXTRA_MESSAGE);

我不会为你重写整个程序。你现在必须弄清楚如何处理这些论点。也许您现在可以将它们存储在private static变量中,但是我对您的程序的了解还不够,无法说这是否可行。更好的解决方案是通过您定义的各种方法传递参数,直到它们到达使用它们的方法。

于 2013-03-26T16:18:11.327 回答