Wednesday, April 10, 2013

[android help] On boot_completed notification not shown


I am creating an app which shows notification in future date. For showing notifications in future i have taken help of AlarmManager.


On button click in one of my activities i create notification like this



Intent myIntent = new Intent(getApplicationContext(),
BootService.class);
myIntent.putExtra("stuffid", stuffId);
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(),
stuffId, myIntent, 0);

AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);

Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month - 1);
calendar.set(Calendar.DAY_OF_MONTH, day);

calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, 00);

alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),pendingIntent);
// Tried set repeating also :(
// alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 30*1000, pendingIntent);


Here is my code for BootService class:



public class BootService extends Service {
DBController dbController = new DBController(this);

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

@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

LoadAlarmsFromDatabase();

int stuffId = intent.getIntExtra("stuffid", 0);
if(stuffId > 0)
new GetStuffDataAsync().execute(stuffId);

return super.onStartCommand(intent, flags, startId);
}

private void LoadAlarmsFromDatabase() {
DBController dbController = new DBController(this);
// Iterate over array and call addnotification no of time
...
addNotification(stuff.getStuffId(), calendar);
dbController.close();
}

private void addNotification(int stuffid, Calendar cal) {

Calendar rightNow = Calendar.getInstance();
long rightNowMillis = rightNow.getTimeInMillis();

// Add to alarm only when its greate than current date
if (cal.getTimeInMillis() > rightNowMillis) {
Log.v(TAG, "addNotification " + stuffid + ", " + cal);
Intent intent = new Intent(getApplicationContext(),
BootService.class);

intent.putExtra("stuffid", Integer.toString(stuffid));

PendingIntent mAlarmSender = PendingIntent.getBroadcast(
getApplicationContext(), stuffid, intent, PendingIntent.FLAG_UPDATE_CURRENT);

AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
//am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), mAlarmSender);
am.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 30*1000, mAlarmSender);

}
}

public class GetStuffDataAsync extends AsyncTask {

@Override
protected Stuff doInBackground(Integer... params) {
int stuffId = params[0];
Stuff stuff = dbController.getStuffInfo(stuffId);
dbController.close();

return stuff;
}

@Override
protected void onPostExecute(Stuff result) {
Context ctx = getApplicationContext();

Intent notificationIntent = new Intent(ctx, AndroidAlarmService.class);
PendingIntent contentIntent = PendingIntent.getActivity(ctx,
1, notificationIntent,
PendingIntent.FLAG_CANCEL_CURRENT);

NotificationManager nm = (NotificationManager) ctx
.getSystemService(Context.NOTIFICATION_SERVICE);

NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx);

builder.setContentIntent(contentIntent)
.setSmallIcon(R.drawable.ic_launcher)
.setTicker("Reminder: " + result.getName() + " expires on " + result.getExpiresOn())
.setWhen(System.currentTimeMillis())
.setAutoCancel(true)
.setContentTitle("NotifyWhenMyStuffExpires")
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentText(result.getName() + " expires on " + result.getExpiresOn());


Resources res = ctx.getResources();
if(result.getHasPhoto() == 1){
Bitmap bm = result.getPhoto();
builder.setContentIntent(contentIntent).setLargeIcon(bm);
}
else
builder.setContentIntent(contentIntent).setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.ic_launcher));

Notification n = builder.build();

nm.notify(1, n);
}

}

}


On testing the application i see notification getting shown, problem is specific to booting the phone. In code above i am re-creating the notifications by calling LoadAlarmsFromDatabase


To handle recreating of alarms on boot i have used BroadcastReceiver


public class BootReceiver extends BroadcastReceiver {



private final String TAG = "BootService";

@Override
public void onReceive(Context context, Intent intent) {
android.os.Debug.waitForDebugger();

if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
android.os.Debug.waitForDebugger();

Intent mServiceIntent = new Intent(context,BootService.class);
mServiceIntent.setAction("com.whenmystuffexpires.BootService");
ComponentName service = context.startService(mServiceIntent);

if (null == service) {
// something really wrong here
Log.e(TAG, "Could not start BootService ");
Log.v(TAG, "BootReceiver - Could not start BootService ");
}



} else {
Log.e(TAG, "Received unexpected intent " + intent.toString());
Log.v(TAG, "Received unexpected intent " + intent.toString());
}
}
}


With debugger attached i see breakpoint getting hit and loadalarmfromdatabase getting called. But notifications are not getting shown.


Here is how my Reciever is declared in manifest



android:name=".BootService"
android:enabled="true" />

android:name=".BootReceiver"
android:enabled="true" >







Some more facts:



  1. On rebooting using ADB shell, notification DOES work!.


    $ am broadcast -a android.intent.action.BOOT_COMPLETED




  2. I am testing it on Gingerbread.




  3. Problem is only on reboot of phone.




.

stackoverflow.comm

No comments:

Post a Comment

Google Voice on T-Mobile? [General]

Google Voice on T-Mobile? So I recently switched from a GNex on Verizon to a Moto X DE on T-Mobile. I had always used Google Voice for my v...