I am writing app to schedule SMS from alarm Manager. It works for me only one time and second time onwards it generate the multiple SMS.
Times are saved in SQL LITE and after send a SMS from Broadcast receiver read the DB and set the next alarm.
if 1 SMS has sent, second time it sends 2 SMS. next time 3 sms, and so on. I am using AmarmManager array and PendingIntents array to set alarm.
here is my coding... Please elp me... i am spending fer day for this taks..
public void SetAlarm(MessageInfo info, long delay, int amcount)
{
try
{
AlarmMSGInfo = info;
SaveMSGINFOPreference();
//Save Sent Status to Preference..
//savePreferences("SENT", old);
// register the alarm broadcast here
AMCount = amcount;
registerReceiver(mReceiver, new IntentFilter("com.rememberme.rm") );
//pendingIntent = PendingIntent.getBroadcast( this, 0, new Intent("com.techblogon.alarmexample"),0 );
pendingIntent[amcount] = PendingIntent.getBroadcast( RememberMe.this,amcount, new Intent("com.rememberme.rm"),PendingIntent.FLAG_ONE_SHOT );
alarmManager[amcount] = (AlarmManager)(this.getSystemService( Context.ALARM_SERVICE ));
alarmManager[amcount].set( AlarmManager.RTC_WAKEUP, delay , pendingIntent[amcount] );
}
catch(Exception e)
{
//Toast.makeText(RememberMe.this, e.toString(), Toast.LENGTH_LONG).show();
Toast.makeText(RememberMe.this, "Alarm cannot be set...", Toast.LENGTH_LONG).show();
}
}
This is my Broadcast receiver ..
private void RegisterAlarmBroadcast()
{
//This is the call back function(BroadcastReceiver) which will be call when your
//alarm time will reached.
mReceiver = new BroadcastReceiver()
{
private static final String TAG = "Alarm Example Receiver";
#Override
public void onReceive(Context context, Intent intent)
{
String s = intent.getAction().toString();
if(intent.getAction() != null )
{
Log.i(TAG,"BroadcastReceiver::OnReceive() >>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
//Toast.makeText(context, "Congrats!. Your Alarm time has been reached", Toast.LENGTH_LONG).show();
MessageInfo temp= LoadMSGINFOPreference();
if(temp == null )
{
}
else
{
String snt = loadSavedPreferences("SENT");
if(snt== "")
Sent = 0;
else
Sent = Integer.valueOf(snt);
int status = 0;
if(Sent == 0)
{
//MessageInfo SentInfo = dbHandler.Get_MessageInfo(Sent);
//status = SentInfo.getStatus();
//}
//Toast.makeText(RememberMe.this, String.valueOf(msgType) , Toast.LENGTH_LONG).show();
//if(status == 0)
//{
if(temp.getMSGType() == 1)
{
_Recipients = ReadPhoneNumbers(temp.getRecipients());
_Message = temp.getMessage();
for(String number:_Recipients)
{
try
{
String num = number;
//Toast.makeText(context, "Congrats!. Your Alarm time has been reached : " + num + ":", Toast.LENGTH_LONG).show();
sendSMS(num, _Message);
}
catch (Exception e)
{
Toast.makeText(getApplicationContext(), e.toString(),Toast.LENGTH_LONG).show();
//Toast.makeText(getApplicationContext(),"SMS faild, please try again later!",Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
alarmManager[AMCount].cancel(pendingIntent[AMCount]);
}
//Updaate te record to set status = 1...(SEND)
temp.setStatus(1);
dbHandler.Update_MessageInfo(temp);
savePreferences("SENT", String.valueOf(temp.getID()));
//take nearest Record from da DB.
MessageInfo minfo = new MessageInfo();
ArrayList<MessageInfo> msgInfo_array_from_db = dbHandler.Get_MessageInfos();
if(msgInfo_array_from_db.size() > 0)
{
minfo = GetLatestMSGInfo(msgInfo_array_from_db);
//Set tat record to alarm manager...
SetAlarm(minfo, minfo.getDelay(), temp.getID());
}
//}
}
}
};
}
private void SaveMSGINFOPreference()
{
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
Editor prefsEditor = sp.edit();
Gson gson = new Gson();
String json = gson.toJson(AlarmMSGInfo);
prefsEditor.putString("AlarmMSGInfo", json);
prefsEditor.commit();
}
Related
I have a written a receiver for a NEW_OUTGOING_CALL intent (static receiver). In order not to hold the system, I do the lengthy part of the process in a AsyncTask.
Based on the number dialed, I may or may not start the AsyncTask (and proceed with regular processing). However, the tasks starts on its own, with the right param passed, and I cant figure out how !!
I've grep'ed the project, and there are no other calls to LongOperation other than the one in the CallOneShot function - but the traces surrounding the 'new' statement do not appear.
How can this happen ?
Please find the code attached, sorry for the length, I've tried to cut it down a bit
Thanks for the help
J.
package com.iper.phoneeco;
public class MyReceiver extends BroadcastReceiver {
private static final String TAG = "XXBroadcastReceiver";
FileWriter fDevLog;
MyPrefs myprefs=null;
public final static String EXTRA_MESSAGE = "com.iper.phoneeco.msg1";
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equalsIgnoreCase("android.intent.action.NEW_OUTGOING_CALL"))
{
Log.d(TAG,"OUTGOING CALL RECEIVED");
String phoneNumber = getResultData();
if (phoneNumber == null) {
// No reformatted number, use the original
phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
}
Log.d(TAG,"phone number:"+phoneNumber);
if (IsToProcess(phoneNumber)) {
Log.d (TAG,"Trapping the call");
// Lets Roll
CallOneShot(phoneNumber);
// and prevent other apps from calling as well
setResultData(null);
// abortBroadcast();
}
else {
Log.d (TAG,"Standard processing");
Toast.makeText(context, "standard processing" , Toast.LENGTH_LONG).show();
}
Log.d (TAG,"Finished processing intent");
}
//
// check is number against a list of exceptions, that we dont handle
//
private boolean IsToProcess(String num){
String[] excluded = {"15","17","18","112","911","991","08.*","^\\*.*","^#.*"};
for (String ex : excluded){
Log.d(TAG,"Exclusion test: "+ex + "versus: "+num);
if (num.matches(ex)) {
Log.d(TAG,"Exclusion FOUND: "+ex);
return false;
}
}
if (num.length() < myprefs.minLen) {
Log.d(TAG,"Exclusion FOUND: Numero trop court");
return false;
}
Log.d(TAG,"Exclusion not found: ");
return true;
}
//
// Displays a toast
//
void MyToast(String s, int col, int dur ) {
Toast toast=Toast.makeText(myprefs.ctx, s, dur);
toast.setGravity(Gravity.CENTER_HORIZONTAL, 0, 0);
toast.getView().setBackgroundColor(col );
LinearLayout toastLayout = (LinearLayout) toast.getView();
TextView toastTV = (TextView) toastLayout.getChildAt(0);
toastTV.setTextSize(20);
toast.show();
}
void MyToast(String s, int col) {
MyToast(s,col,Toast.LENGTH_LONG);
}
public void CallOneShot(String phoneNumber) {
Log.d (TAG,"CallOneShot");
MyToast (myprefs.ctx.getResources().getString(R.string.callbackipg)+" "+phoneNumber,Color.BLUE);
new LongOperation().execute(phoneNumber);
}
//
// the meat....
//
public class LongOperation extends AsyncTask<String, Void, String> {
String numToCall;
#Override
protected String doInBackground(String... params) {
int bytesRead;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
String msgres;
String response;
Log.d(TAG, "Clientthread started");
numToCall=params[0];
Log.d(TAG, "numTocall"+numToCall);
// and add to the call log
ContentValues values = new ContentValues();
values.put(CallLog.Calls.NUMBER, numToCall);
values.put(CallLog.Calls.DATE, System.currentTimeMillis());
values.put(CallLog.Calls.DURATION, 0);
values.put(CallLog.Calls.TYPE, CallLog.Calls.OUTGOING_TYPE);
values.put(CallLog.Calls.NEW, 1);
values.put(CallLog.Calls.CACHED_NAME, "");
values.put(CallLog.Calls.CACHED_NUMBER_TYPE, 0);
values.put(CallLog.Calls.CACHED_NUMBER_LABEL, "");
Log.d(TAG, "Inserting call log placeholder for " + numToCall);
ContentResolver resolver = myprefs.ctx.getContentResolver();
resolver.insert(CallLog.Calls.CONTENT_URI, values);
response=myprefs.ctx.getResources().getString(R.string.errundef);
return response;
}
protected void onPostExecute (String s) {
if (!s.equals("ok")) {
Log.d(TAG,"OnPostExecute - failed: "+s);
MyToast (myprefs.ctx.getResources().getString(R.string.errcallback)+"\n"+s,Color.RED);
}
}
}
}
Have you assign value to myprefs. It seems that you have initialized it to null and never assign it to any value
ok - stupid me is the answer - I had changed the name of the package, and an old version of the package was still on the emulator, trapping the intent ! once I removed it, it all went back to normal...
Many thanks for your help anyway
I'm developing an app that has a recurring task of sending call to the server and check whether the data is available for current date. I have implemented this successfully but I have an issue, when I kill the Process it's call the service again. I have monitored this through Logcat or it generate the PUSH notification too even the flag is not false (According to my logic). Why because I'm using *START_STICKY*?
I have used START_REDELIVER_INTENT flag too, it solved that issue but in the TaskManager of my cellphone my service status is on RESTART when I killed the process. Does the service is still running or it is in RESTART state?
I want my service run 24/7 without RESTART. either I kill the process like (weChat, Whatsapp, Viber) etc.
Can someone please sort out what I'm doing wrong? or give me the right direction. Help should be appreciated. Thanks
Service:
public int onStartCommand(Intent intent, int flags, final int startId) {
// Log.e("LocalService", "Received start id " + startId + ": " + intent);
Log.e("AlertService", "Alert-----Service Created");
// TODO Auto-generated method stub
ScheduledExecutorService scheduler =
Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate
(new Runnable() {
public void run() {
// call service
DateFormat df = new SimpleDateFormat("dd-MM-yyyy");
currentDate = df.format(Calendar.getInstance().getTime());
String[] separated_currentDate = currentDate.split("-");
int actual_date = Integer.parseInt(separated_currentDate[0]);
Log.e("CurrentDate of my Device", currentDate);
Log.e("ad",""+actual_date);
if(flag == false)
{
Log.e("Flag-Status", "FALSE");
try {
savingDateinPref(currentDate);
isInternetPresent = cm.isConnected();
if(isInternetPresent)
{
Log.e("Flag-Status", "Calling Service");
new DoInBackground().execute(currentDate);
// currentDate = null;
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
String val = prefs.getString("TAG_KEY", "defvalue");
String[] separated_val = val.split("-");
int pref_date = Integer.parseInt(separated_val[0]);
Log.e("pd", "" +pref_date);
if( (pref_date != actual_date) || ( pref_date < actual_date) || (pref_date > actual_date) )
{
flag = false;
Log.e("Flag-Status", "FALSE/bcoz date has been changed");
// String empty = null;
// savingDateinPref(empty);
}
}
}, 0, 5, TimeUnit.SECONDS);
return START_REDELIVER_INTENT;
}
I have a big problem that i couldn't find solution. Need your help.
When i try to send just one message in activity using service , it works.
But when i try to send 2 message following another( that means one after other ) , sends the message twice with the same publishTopic2 and pushMsg2.
Code is :
PushService.actionPush(getApplicationContext(),publishTopic1,pushMsg1);
PushService.actionPush(getApplicationContext(),publishTopic2,pushMsg2);
1- is this from the wrong usage of syncronized keyword ?
2- is it possibe to send two msg after another without
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);
}
}
}
When you call actionPush(), it does the following:
PUBLISH_TOPIC = publishTopic;
PushMesaj = pushMsg;
which saves the arguments in private static variables and then calls startService. If you do this twice, you will overwrite the private static variables with the second set of arguments.
You need to understand that the call to startService() is not synchronous. It doesn't start the service immediately and call onStart() before the method returns. The service will get started and the call to onStart() will occur sometime later (timing isn't under your control here).
You want to put these parameters in the Intent that you use to start the service, and retrieve the arguments from the Intent in onStart(). You can't reliably use static variables to do this.
EDIT: ADD CODE DETAILS
Change actionPush() to this:
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);
}
and in onStart() you can get the arguments out of the Intent like this:
String topic = intent.getStringExtra(EXTRA_TOPIC);
String message = intent.getStringExtra(EXTRA_MESSAGE);
I'm not going to rewrite the entire program for you. You'll have to figure out now what to do with the arguments. Maybe you can now store them in private static variables, but I don't know enough about your program to be able to say if that will work. A better solution would be to pass the arguments through the various methods that you've defined until they get down to the methods where they are used.
My application has a database where queued items will be stored if it doesn't notice any connectivity to Wifi or mobile network, like 3G og 4G. My problem is:
I have a BroadcastReciever which is registrered this way:
#Override
public void onResume() {
super.onResume();
if(networkMonitor == null)
networkMonitor = new CaseQueueReceiver();
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(networkMonitor, filter);
}
My BroadcastReciever is starting a Service to pick out items from this database and send them over either a webservice or mail. My BrodcastReciever is like this:
public class CaseQueueReceiver extends BroadcastReceiver {
boolean available;
QueueDB queueDB;
int count;
public CaseQueueReceiver() {
queueDB = new QueueDB(ContextHelper.context());
count = queueDB.countUnsentCases();
}
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
NetworkInfo info = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
String typeName = info.getTypeName();
String subtypeName = info.getSubtypeName();
available = info.isAvailable();
Log.i("Network Monitor", "Network Type: " + typeName + ", subtype: " + subtypeName + ", available: " + available);
if (available && count > 0) {
Intent service = new Intent(context, SendQueuedCasesService.class);
context.startService(service);
}
}
}
}
As you can see if the internet connection is available and the database contains something, I will start a service to send these items in the database.
My Service looks like this:
public class SendQueuedCasesService extends Service {
boolean available;
DatabaseHandler db;
QueueDB queueDB;
HashMap<String, String> queueHashMap;
CreateTransaction transaction;
String pcn, file;
int sent;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
db = new DatabaseHandler(ContextHelper.context());
queueDB = new QueueDB(ContextHelper.context());
queueHashMap = new HashMap<String, String>();
transaction = new CreateTransaction(ContextHelper.context());
queueDB = new QueueDB(this);
int count = queueDB.countUnsentCases();
Log.w("Unsent cases count: ", Integer.toString(count));
if (count > 0) {
queueHashMap = queueDB.getUnsetCases();
Iterator<Entry<String, String>> it = queueHashMap.entrySet().iterator();
while(it.hasNext()) {
Map.Entry pairs = it.next();
pcn = pairs.getKey().toString();
Log.w("PCN in Queued Cases: ", pcn);
file = pairs.getKey().toString();
Log.w("Nist File Path: ", file);
try
{
sent = transaction.createTransaction(pcn, file);
if(sent == -2)
{
queueDB.deleteUnSentCase(pcn);
db.updateDB(pcn, "");
}
else
break;
} catch(MailException e) {
Log.e("MailException: ", e.getMessage());
}
}
Intent i = new Intent(this, WorkflowChooser.getCurrentWorkflow());
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
}
}
My problem is that when I start the application this will block the UI for a while and then show the UI. A other problems is that this service isn't triggered if I turn off and the on the WiFi again. Why is this happening?
My problem is that when I start the application this will block the UI for a while and then show the UI.
Service runs in UI thread. That's the problem.
You can try to use IntentService. It will handle all the threading for you automatically.
You should create an AsyncTask or a new thread which handles the Service.
I want to block a specific phone number that is in my database
I do a comparison between the number the user dialed, and the number in memory. If they are equal, I block the call.
My code:
public void onReceive(Context context, Intent intent) {
PlaceDataSQL placeDataSQL =new PlaceDataSQL(context);
ArrayList<String> getUsersPhoneNumbers= placeDataSQL.getUsersPhoneNumbers();
//TODO
//===========
//here I need to check the number
Bundle b = intent.getExtras();
String incommingNumber = b.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
//String outGoingNumber = b.getString(TelephonyManager.);
Boolean find=false;
try {
for(int i=0;i<getUsersPhoneNumbers.size();i++)
{
if(incommingNumber.equals(getUsersPhoneNumbers.get(i)))
{
find=true;
break;
}
}
} catch (Exception e) {
incommingNumber="";
}
// ========================================
//here the problem
//=========================================
String phonenumber=b.getString(Intent.EXTRA_PHONE_NUMBER);
try {
for(int i=0;i<getUsersPhoneNumbers.size();i++)
{
if(phonenumber.equals(getUsersPhoneNumbers.get(i)))
{
find=true;
break;
}
}
if (!find)
return;
}catch (Exception e) {
phonenumber="";
}
if (!find)
return;
/* examine the state of the phone that caused this receiver to fire off */
String phone_state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (phone_state.equals(TelephonyManager.EXTRA_STATE_RINGING))
{
logMe("Phone Ringing: the phone is ringing, scheduling creation call answer screen activity");
Intent i = new Intent(context, CallAnswerIntentService.class);
i.putExtra("delay", 100L);
i.putExtra("number", incommingNumber);
context.startService(i);
logMe("Phone Ringing: started, time to go back to listening");
}
if (phone_state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK))
{
Intent i = new Intent(context,InCallScreenGuardService.class);
i.putExtra("delay", 100L);
i.putExtra("number", phonenumber);
logMe("Phone Offhook: starting screen guard service");
context.startService(i);
}
if (phone_state.equals(TelephonyManager.EXTRA_STATE_IDLE))
{
Intent i = new Intent(context,InCallScreenGuardService.class);
logMe("Phone Idle: stopping screen guard service");
context.stopService(i);
}
return;
}
The problem:
I can get incoming numbers but I can't get outgoing numbers?
You will need a BroadcastReciever for this.
public class OutgoingCallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if(null == bundle)
return;
String phonenumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Log.i("OutgoingCallReceiver",phonenumber);
Log.i("OutgoingCallReceiver",bundle.toString());
String info = "Detect Calls sample application\nOutgoing number: " + phonenumber;
Toast.makeText(context, info, Toast.LENGTH_LONG).show();
}
}