我有一个大问题,我找不到解决方案。需要你的帮助。
当我尝试使用 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);
}
}
}