The value for myRange is always 1, 2 or 3.
It is giving a nullpointer exception error.pending must be specified.
If I do not check myRange value inside if statement, it does not give an error but it does not create pendingIntent2 and pendingIntent3.
I tried sending different Request code but it did not work.
private PendingIntent createGeofencePendingIntent(int myRange) {
Log.d(TAG, "createGeofencePendingIntent");
Toast.makeText(getContext(),"creating intent function" + myRange ,Toast.LENGTH_SHORT).show();
if ( geoFencePendingIntent1 != null && myRange == 1)
return geoFencePendingIntent1;
if ( geoFencePendingIntent2 != null && myRange == 2 )
return geoFencePendingIntent2;
if ( geoFencePendingIntent3 != null && myRange == 3)
return geoFencePendingIntent3;
if(myRange == 1)
{
Toast.makeText(getContext(),"creating intent 1",Toast.LENGTH_SHORT).show();
Intent intent1 = new Intent( getContext(), GeofenceTransitionService.class);
intent1.putExtra("region",inString[0]);
geoFencePendingIntent1 = PendingIntent.getService(
getContext(), GEOFENCE_REQ_CODE, intent1, PendingIntent.FLAG_UPDATE_CURRENT );
return geoFencePendingIntent1;
}
else if (myRange ==2)
{
Toast.makeText(getContext(),"creating intent 2",Toast.LENGTH_SHORT).show();
Intent intent2 = new Intent( getContext(), GeofenceTransitionService.class);
intent2.putExtra("region",inString[1]);
geoFencePendingIntent2 = PendingIntent.getService(
getContext(), 5, intent2, PendingIntent.FLAG_NO_CREATE );
return geoFencePendingIntent2;
}
else if (myRange == 3)
{
Intent intent3 = new Intent( getContext(), GeofenceTransitionService.class);
return PendingIntent.getService(
getContext(), GEOFENCE_REQ_CODE, intent3, PendingIntent.FLAG_UPDATE_CURRENT );
}
geoRange++;
// Toast.makeText(getContext(), "leaving my geofence", Toast.LENGTH_SHORT).show();
return null;
}
You have several problems here. The first one is this:
geoFencePendingIntent2 = PendingIntent.getService(
getContext(), 5, intent2, PendingIntent.FLAG_NO_CREATE );
This will probably always return null as you you've specified FLAG_NO_CREATE. This will only return a non-null result if a matching PendingIntent already exists (which it probably doesn't). Use FLAG_UPDATE_CURRENT instead.
The second problem is that you need to make sure that each of your 3 different PendingIntents are unique. To do this you need to provide either a unique requestCode in the call to PendingIntent.getService() OR you need to provide a unique ACTION in the Intent that you pass to PendingIntent.getService(). Otherwise, when you call PendingIntent.getService(), you will just keep getting the same PendingIntent returned (and a new one will not be created).
There are about a million questions on Stackoverflow about this and in most of them there is a detailed explanation of how PendingIntent creation and matching works.
Related
I have this code to make the actions:
Intent playIntent = new Intent(Intent.ACTION_VIEW);
playIntent.setDataAndType(uri, path.contains(".jpg") ? "image/jpeg" : "video/mp4");
PendingIntent play = PendingIntent.getActivity(context, 1, playIntent, 0);
mBuilder.addAction(R.mipmap.ic_play_arrow_black_48dp, "", play);
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
shareIntent.setType(path.contains(".jpg") ? "image/jpeg" : "video/mp4");
PendingIntent share = PendingIntent.getActivity(context, 2, shareIntent, 0);
mBuilder.addAction(R.mipmap.ic_share_white_48dp, "", share);
Intent doneIntent = new Intent(context, NotificationCloser.class);
doneIntent.putExtra("notificationId", notificationId);
PendingIntent done = PendingIntent.getBroadcast(context, 3, doneIntent, 0);
mBuilder.addAction(R.mipmap.ic_done_black_48dp, "", done);
And this is my broadcast receiver
public class NotificationCloser extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
int id = intent.getIntExtra("notificationId", 0);
Log.i("MyInfo", "NotificationCloser.onReceive(" + id + ")");
MainActivity.mNotifyManager.cancel(id);
}
}
When I click in play or share button, it does according the function, opens the default app to view images or videos but doesn't close the notification. When I click in the done button, ONLY in the first time i receive the id correctly, after the first time it gets the id sent in the first time
Can someone help me?
I solved the problem of the broadcast by using random request codes, also added the flag PendingIntent.FLAG_UPDATE_CURRENT. I used in all because sometimes the share bugged and used another image.
PendingIntent play = PendingIntent.getActivity(context, new Random().nextInt(150) * 37, playIntent, 0);
PendingIntent share = PendingIntent.getActivity(context, new Random().nextInt(150) * 37, shareIntent, 0);
PendingIntent done = PendingIntent.getBroadcast(context, new Random().nextInt(150) * 37, doneIntent, PendingIntent.FLAG_UPDATE_CURRENT);
This answer was posted as an edit to the question Notification with Multiple actions by the OP Rodrigo Butzke under CC BY-SA 3.0.
I have two alarms and a broadcastreceiver:
AlarmManager am2=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent2 = new Intent(context, MyReceiverAlarm.class);
intent2.putExtra("name", "juan");
PendingIntent pi2 = PendingIntent.getBroadcast(context, 0, intent2, 0);
am2.set(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+1000, pi2);
AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, MyReceiverAlarm.class);
intent.putExtra("name", "jose");
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
am.set(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+8000, pi);
However, I'm always receiving the first one, only. I always get "juan" and the alarm is fires after 8 seconds.
I don't understand the reason...If i have two alarms why fires one ?
My BroadcastReceiver:
Toast.makeText(context, extras.getString("nombre") + "", Toast.LENGTH_LONG).show();
String name=extras.getString("nombre");
if (extras != null && name.equals("juan") {
String callForwardString = PHONE ;
Intent intentCallForward = new Intent(Intent.ACTION_CALL);
Uri uri2 = Uri.fromParts("tel", callForwardString, "#");
intentCallForward.setData(uri2);
intentCallForward.addFlags(intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intentCallForward);
} else {
...
}
Is not possible to program two alarms?
Thanks in advance
Try to change the request code (second parameter passed to getBroadcast():
PendingIntent pi2 = PendingIntent.getBroadcast(context, 2, intent2, 0);
PendingIntent pi = PendingIntent.getBroadcast(context, 1, intent, 0);
I have following method which is saving three values into intent which is appended to created alarm.
public static Boolean setUniqueAlarm(Long alarmId, String occurenceTime, Context context) {
Boolean saveResult = null;
try {
DateTime dt = TimeHelper.getDateTimeObject(occurenceTime);
Logger.d("Year: " + dt.getYear() + ", month: " + dt.getYear() + ", day: " + dt.getDayOfMonth() + ", hour: " + dt.getHourOfDay() + ", minute: " + dt.getMinuteOfHour());
Logger.d("Occurrence time to save: "+occurenceTime);
AlarmManager alarmManager = (AlarmManager) context.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
Intent alarmIntent = new Intent(context, AlarmBroadcastReceiver.class);
// Pass the intent type and other additional values into bundle
Bundle bundle = new Bundle();
bundle.putString(Constants.Global.ALARM_TYPE, Constants.Global.ALARM_TYPE_UNIQUE);
bundle.putString(Constants.Global.ALARM_OCCURRENCE_TIME, "123456");
bundle.putLong(Constants.Global.ALARM_UNIQUE_ID, alarmId);
alarmIntent.putExtras(bundle);
PendingIntent pendingAlarmIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, dt.getMillis(), pendingAlarmIntent);
saveResult = true;
} catch (Exception e) {
Logger.e(e.getMessage());
saveResult = false;
}
return saveResult;
}
In receiver i have following code:
#Override
public void onReceive(Context context, Intent intent) {
try {
Logger.d("ALARM RECEIVED!!!");
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
// Device battery life will be significantly affected by the use of this API.
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TAG");
// Acquire the lock
wl.acquire();
//Release the lock
wl.release();
// Get the intent type (or stored variables)
Bundle extras = intent.getExtras();
mAlarmType = extras.getString(Constants.Global.ALARM_TYPE);
mAlarmId = extras.getLong(Constants.Global.ALARM_UNIQUE_ID, 0);
mOccurenceTime = extras.getString(Constants.Global.ALARM_OCCURRENCE_TIME, "nothing");
triggerActionBasedOnTheAlarmType(mAlarmType, mAlarmId, mOccurenceTime, context);
} catch (Exception e) {
TrackingEventLogHelper.logException(e, Constants.Global.EXCEPTION,
Constants.ExceptionMessage.EXC_CANNOT_PROCESS_RECEIVED_ALARM, true);
}
}
Problem is that variable mOccurenceTime is always null, rsp. "nothing".
I tried to get values from intent and from Bundle but still without the success. Is not bundle count of items limited?
How can i get value mOccurenceTime in the right way?
Many thanks for any advice.
This is the right way to do it - specify a flag !
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, uniqueRequestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Instead of the:
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, uniqueRequestCode, intent, 0);
Because the 0 for the flags is what will cause you a headache
This is probably such a popular problem because Google's sample code neglected to include Extra's in an Alarm.
Solved here:
Android cannot pass intent extras though AlarmManager
I have the following code:
public void sendNewNotification (Booking updateBooking) {
String msg;
if (updateBooking.getJobStatus () == Booking.eeJob_OnRoute) {
msg = "Your driver has been dispatched.";
} else if (updateBooking.getJobStatus () == Booking.eeJob_POB) {
msg = "Your driver has arrived.";
} else if (updateBooking.getJobStatus () == Booking.eeJob_Complete) {
Variables.driverrated = false;
msg = "Your booking has been completed. Thank you for using " + Variables.setting.getCompanysName () + ".";
} else if (updateBooking.getJobStatus () == Booking.eeJob_NoShow) {
msg = "Unfortunately your driver was unable locate you. Please call the office on " + Variables.setting.getCompanytelephone () + ".";
} else if (updateBooking.getJobStatus () == Booking.eeJob_Cancelled) {
msg = "Your booking has been cancelled. Please call the office on " + Variables.setting.getCompanytelephone () + " if this is incorrect.";
} else {
return;
}
PendingIntent detailsIntent = PendingIntent.getActivity (this, 0, new Intent (this, HomeActivity.class)
.putExtra ("booking", updateBooking)
.putExtra ("track", false),
PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent trackingIntent = PendingIntent.getActivity (this, 0, new Intent (this, HomeActivity.class)
.putExtra ("booking", updateBooking)
.putExtra ("track", true),
PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder (this);
builder.setAutoCancel (true);
builder.setDefaults (Notification.DEFAULT_ALL);
builder.setWhen (System.currentTimeMillis ());
builder.setContentTitle (Variables.setting.getCompanysName () + " - booking update");
builder.setSmallIcon (R.drawable.notification);
builder.setTicker (Variables.setting.getCompanysName () + " - booking update");
builder.setPriority (NotificationCompat.PRIORITY_HIGH);
builder.setContentText (msg);
builder.setContentIntent (trackingIntent);
builder.addAction (R.drawable.documents_32px, "DETAILS", detailsIntent);
if (updateBooking.getJobStatus () != Booking.eeJob_Complete) {
builder.addAction (R.drawable.notification, "TRACK", trackingIntent);
} else {
builder.addAction (R.drawable.profile_32px, "RATE", detailsIntent);
}
NotificationManager manager = (NotificationManager) getSystemService (NOTIFICATION_SERVICE);
manager.notify (getTaskId (), builder.build ());
}
My issue is in my onCreate function I have these two lines:
m_updateBooking = (Booking) getIntent ().getSerializableExtra ("booking");
m_TrackDriver = (Boolean) getIntent ().getSerializableExtra ("track");
m_updateBooking works flawlessly. But m_TrackDriver is ALWAYS true. No matter what button I press. Can anyone explain why this is?
Thanks in advance for all your help.
Since your Intent has the same action for both the PendingIntent, you need to specify a different requestCode otherwise with FLAG_UPDATE_CURRENT the extras in the PendingIntent will be replaced by the new extras in the Intent. For this reason you have always true, because it is in the last PendingIntent requested.
This StackOveflow answer explains in details how PendingIntent works.
To resolve your issue change your code like this:
PendingIntent detailsIntent = PendingIntent.getActivity (this, 0, new Intent (this, HomeActivity.class)
.putExtra ("booking", updateBooking)
.putExtra ("track", false),
PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent trackingIntent = PendingIntent.getActivity (this, 1, new Intent (this, HomeActivity.class)
.putExtra ("booking", updateBooking)
.putExtra ("track", true),
PendingIntent.FLAG_UPDATE_CURRENT);
I have a Widget i am working on, that allows the user to have more then one instance of the widget on his screen. Each Widget id maintains its own configuration file. However for some odd reason my code that is responsible for setting up the buttons individually for each widget id is not working, only the first widget id is linked to each individual widget. below is the code that is responsible. Can anyone see where the problem is?
private void TieClicks(Context context){
RemoteViews rViews;
PendingIntent editPendingIntent= null;
// Intent updateintent = new Intent(context,SyncNoteWidget.class);
// updateintent.setAction(SyncNote_Action_Widget_Update);
// PendingIntent pendingupdateintent = PendingIntent.getBroadcast(context, 0, updateintent, 0);
// rViews.setOnClickPendingIntent(R.id.widgettextview , pendingupdateintent);
//
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int[] ids = appWidgetManager.getAppWidgetIds(new ComponentName(context, SyncNoteWidget.class));
for (int i =0;i< ids.length;i=i+1){
int wId = ids[i];
rViews = new RemoteViews(context.getPackageName(),R.layout.widget);
editPendingIntent = makeControlPendingIntentActivity(context, wId);
Log.v("syncnote", "tieing " + String.valueOf(wId));
rViews.setOnClickPendingIntent(R.id.widgeteditbutton , editPendingIntent);
appWidgetManager.updateAppWidget(wId, rViews);
editPendingIntent= null;
}
}
private PendingIntent makeControlPendingIntentActivity(Context context,int appWidgetId) {
Intent active = new Intent(context, EditNote.class);
active.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
active.setAction(com.ntu.way2fungames.syncnote.SyncNoteWidget.SyncNote_Action_Edit);
active.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
return(PendingIntent.getActivity(context, 0, active, 0 ));
}
The problem was that for some reason "PendingIntent.getActivity" was re-using the first PendingIntent.. God knows why. The fix is below, simply add some random data to the call.
private PendingIntent makeControlPendingIntentActivity(Context context,int appWidgetId) {
Intent active = null;
active = new Intent(context, EditNote.class);
active.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
active.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK );
active.setAction(com.ntu.way2fungames.syncnote.SyncNoteWidget.SyncNote_Action_Edit);
active.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
PendingIntent pi =PendingIntent.getActivity(context,(int)(Math.random()*10000), active, 0 );
Log.v("syncnote", "PI: "+pi.toString());
return(pi);
}
It would help if you included the log entries you're creating with:
Log.v("syncnote", "tieing " + String.valueOf(wId));
That could answer the important question:
How many values are in: int[] ids ?
What is in R.layout.widget ?
A picture of your widgets would help too. A picture is worth a thousand words...