Android widget intents - java

I have a widget class and a service class updating the widget.
I have added in the widget class in onUpdate() the following code:
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.countdownwidget);
Intent Intent1 = new Intent(Intent.ACTION_MAIN);
Intent1.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent pendingIntent1 = PendingIntent.getActivity(context, 0, Intent1, 0);
views.setOnClickPendingIntent(R.id.button1, pendingIntent);
Intent Intent2 = new Intent(Intent.ACTION_MAIN);
Intent2.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent pendingIntent2 = PendingIntent.getActivity(context, 0, Intent2, 0);
views.setOnClickPendingIntent(R.id.button2, pendingIntent2);
And I have also added the following code in the widget service in the onStart()
Intent Intent1 = new Intent(Intent.ACTION_MAIN);
Intent1.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent pendingIntent1 = PendingIntent.getActivity(getApplicationContext(), 0, Intent1, 0);
remoteView.setOnClickPendingIntent(R.id.button1, pendingIntent1);
Intent Intent2 = new Intent(Intent.ACTION_MAIN);
Intent2.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent pendingIntent2 = PendingIntent.getActivity(getApplicationContext(), 0, Intent2, 0);
remoteView.setOnClickPendingIntent(R.id.button2, pendingIntent1);
The problem I am having is that once the implicit intent registers the app to launch on button1, the button2 is identical to button1. How can i make the 2 intents behave differently? i.e register and launch different apps.Its working with one button, but the other button launches the same thing of the first button.I have have been looking to get this to work for the last week, reading things all over but with no result.
I would appreciate your help.
Thanks.

The problem I am having is that once the implicit intent registers the app to launch on button1, the button2
is identical to button1.
Well, of course. All four of your Intents are identical: ACTION_MAIN, CATEGORY_LAUNCHER, with nothing else specified. I am surprised this Intent even works.
So, the first step to having the buttons do different things is to actually have different Intents.
Also, please do not use getApplicationContext(). Just use this, as a Service is a Context.

Related

Notification doesn't show all action buttons

I'm trying to create a simple notification for a music player that has 3 buttons, Pause, Previous and Next. My code only shows one of them which is Next. Any suggestions where I did a mistake?
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
Intent playNextIntent = new Intent(this, BroadcastReceiver.class);
playNextIntent.setAction("NEXT_ACTION");
PendingIntent nextPendingIntent = PendingIntent.getBroadcast(this, 1, playNextIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent pauseIntent = new Intent(this, BroadcastReceiver.class);
pauseIntent.setAction("PAUSE_ACTION");
PendingIntent pausePendingIntent = PendingIntent.getBroadcast(this, 2, pauseIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent playPreviousIntent = new Intent(this, BroadcastReceiver.class);
playPreviousIntent.setAction("PREVIOUS_ACTION");
PendingIntent prevPendingIntent = PendingIntent.getBroadcast(this, 3, playPreviousIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, "D")
.setSmallIcon(R.drawable.ic_launcher_background) //notification icon
.setContentTitle("Simple Music Player")
.setContentText("Currently playing: " + mediaPlayerHolder.getSongsList().get(songIterator).getSongName())
.setPriority(NotificationCompat.PRIORITY_MAX)
.setWhen(0)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setOngoing(true) //user can't remove notification
.addAction(R.drawable.ic_previous, "Previous", prevPendingIntent) // #0
.addAction(R.drawable.ic_pause, "Pause", pausePendingIntent) // #1
.addAction(R.drawable.ic_next, "Next", nextPendingIntent) // #2
.setStyle(new NotificationCompat.BigTextStyle())
.setContentIntent(pendingIntent); //on click go to app intent
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
// notificationId is a unique int for each notification that you must define
notificationManager.notify(1, mBuilder.build()); //show notification
There's nothing wrong with your code. If you run your code in an emulator on stock android the actions show up as expected.
On Android displaying notifications is done by the launcher. Like any other app launchers can contain bugs. In this case there is a bug in the launcher you're using to display multiple actions in a notification.
I recommend you to try a google sample Universal Music player Here is a GitHub link . It includes all of you want in notifications and it has a latest notification Android Oreo features just try out it .

How to reference a view in a customized notification

In the below posted code i am create a notification with a customized layout. the layout of the notification contains three action buttons.
the problem i have now is, i can not reference any of the buttons in the code so that I can navigate to another activity based on the action button clicked.what i am trying to do is when Action button 1
is clicked then Activity 1 shows up, when Action button 2 is clicked then Activity 2 shows up and so on.
Please let me know how to reference the views in customized layout of the notification?
code:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Using RemoteViews to bind custom layouts into Notification
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.layout_notification);
String notification_title = "Notification_Title";
String notification_text = "Notification_Text";
// Open NotificationView Class on Notification Click
Intent intent = new Intent(this, NotificationReply.class);
// Send data to NotificationView Class
intent.putExtra("title", notification_title);
intent.putExtra("text", notification_text);
// Open NotificationView.java Activity
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
// Set Icon
.setSmallIcon(R.mipmap.ic_launcher)
// Set Ticker Message
.setTicker("Ticker")
// Dismiss Notification
.setAutoCancel(true)
// Set PendingIntent into Notification
.setContentIntent(pIntent)
// Set RemoteViews into Notification
.setContent(remoteViews);
Intent intentAction1 = new Intent(this, ActAction1.class);
PendingIntent pendingIntentActAction1 = PendingIntent.getBroadcast(this, 1,intentAction1, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.btn_action1, pendingIntentActAction1);
Intent intentAction2 = new Intent(this, ActAction2.class);
PendingIntent pendingIntentActAction2 = PendingIntent.getBroadcast(this, 2,intentAction2, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.btn_action2, pendingIntentActAction2);
Intent intentAction3 = new Intent(this, ActAction3.class);
PendingIntent pendingIntentActAction3 = PendingIntent.getBroadcast(this, 3,intentAction3, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setPendingIntentTemplate(R.id.btn_action3, pendingIntentActAction3);
// Create Notification Manager
NotificationManager notificationmanager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Build Notification with Notification Manager
notificationmanager.notify(0, builder.build());
}
}
The key success for navigation is to use proper pending intent and use different values for your requestCode.
You could receive the event in broadcastReceiver building the pending intent (e,g, with params) that way:
private PendingIntent buildPendingIntent(String someurl) {
Intent intent= new Intent(mContext, SomeReceiver.class);
final Uri uri = Uri.parse(someurl);
intent.setData(uri);
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(KEY, VALUE)
return PendingIntent.getBroadcast(mContext.getApplicationContext(),
CONSTANT_FOR_THIS_INTENT_TYPE, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
}
Or you could navigate to activity just by pending intent:
private PendingIntent buildPendingIntent2() {
Intent intent = new Intent(mContext, SomeActivity.class);
intent.putExtra(KEY, VALUE);
settingsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
return PendingIntent.getActivity(mContext.getApplicationContext(),
OTHER_CONSTANT_FOR_OTHER_ACTION,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
Please notice that CONSTANT_FOR_THIS_INTENT_TYPE and OTHER_CONSTANT_FOR_OTHER_ACTION must have different values
And after you have this pending intents you should attach them to your views:
view.setOnClickPendingIntent(com.app.btn1, buildPendingIntent1());
view.setOnClickPendingIntent(com.app.btn2, buildPendingIntent2());
You have to use RemoteViews#setOnClickPendingIntent() API:
Equivalent to calling setOnClickListener(android.view.View.OnClickListener) to launch the provided PendingIntent.
Intent firstIntent = new Intent(context, FirstActivity.class);
PendingIntent firstPendingIntent = PendingIntent.getBroadcast(this, 0, firstIntent, 0);
RemoteViews notificationView = ...
notificationView.setOnClickPendingIntent(R.id.first_button, firstPendingIntent);
You have to use RemoteViews#setOnClickPendingIntent() API:
I get your mistake you are trying to launch an activity with PendingIntent.getBroadcast() which only send a broadcast message, so ideally a broadcast receiver should be registered with the same intent filter action. In your case it should ideally be PendingIntent.getActivity
Now you can launch with the following pending intent the flag value was incorrect I can assume for everyone else, hence pending intent wasn't fired.
Intent firstIntent = new Intent(context, FirstActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(appContext, 101, firstIntent,
PendingIntent.FLAG_UPDATE_CURRENT); // For opening activity ideally this should work
If this doesn't work you can try sending a broadcast and listen for it to verify that broadcast is also sent or not:-
PendingIntent pendingIntent = PendingIntent.getBroadcast(appContext, 0, firstIntent, PendingIntent.FLAG_ONE_SHOT); // for sending broadcast and listens in broadcast reciever

How to make a button in a notification 'do something'

I am trying to make a simple stopwatch app that will display the time in a notification and give you a couple buttons that will allow you to start and stop the stopwatch.
How do I add a button to a notification? And how do I 'point' that button to a certain function?
Heres a picture of what I was thinking:
actionIntent = new Intent(this, MainActivity.class);
actionPendingIntent = PendingIntent.getService(this, 0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT);
timerNotification.addAction(android.R.drawable.ic_media_pause, "Start", actionPendingIntent);
This is what I currently have. Where in the intent would I put the function I want to execute?
Add Action to the notification and assign a pendingintent
If you want to custom your notification layout,you can use setContent() function with a RemoteViews of your custom layout.
Remote View mRemoteView = new RemoteViews(getPackageName(), R.layout.notification_general);
Notification.Builder mBuilder = new Notification.Builder(context);
mBuilder.setSmallIcon(R.mipmap.ic_battery)
.setContent(mRemoteView)
.setContentIntent(notificationPendingIntent);
mNotificationManager.notify(1, mBuilder.build());
To handle an notification button onClick event, you need to use separate PendingIntents(made from Intents with differecnt actions) for every button. Later in onReceive() you just check action of incoming Intent & execute different code depending on that. Remember to assign your Listener on manifest.
Intent generalIntent = new Intent(context, GeneralReceiver.class);
generalIntent.putExtra(REQUEST_CODE, ACTION_GENERAL);
PendingIntent generalPendingIntent =
PendingIntent.getBroadcast(context, 1, generalIntent, 0);
mRemoteView.setOnClickPendingIntent(R.id.btnNotificationGeneral, generalPendingIntent);
public static class GeneralReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Your code here
}
}

Notification PendingIntent hard bug (or really simple one)

I'm trying to debug this for ages now and I just can't seem to find the problem:
I have a broadcast receiver, which receives the broadcast successfully.
The notification has two actions ("buttons"):
firstIntent = null;
secondIntent = null;
firstPendingIntent = null; //first "button" to join with the first intent
secondPendingIntent = null; //second "button" to join with the second intent
if(boolean){
//relevant
firstIntent = new Intent(getBaseContext(), NotificationFunctions.class).putExtra("action", "do_this");
secondIntent = new Intent(getBaseContext(), NotificationFunctions.class).putExtra("action", "do_that");
}else{
firstIntent = new Intent(getBaseContext(), NotificationFunctions.class).putExtra("action", "do_another_this");
secondIntent = new Intent(getBaseContext(), NotificationFunctions.class).putExtra("action", "do_another_that");
}
firstPendingIntent = PendingIntent.getBroadcast(getBaseContext(), 0, firstIntent, PendingIntent.FLAG_UPDATE_CURRENT);
secondPendingIntent = PendingIntent.getBroadcast(getBaseContext(), 0, secondIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notification = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle(notification_title)
.setContentText(notification_text)
.setTicker("Notification!")
.setWhen(System.currentTimeMillis())
.setDefaults(Notification.DEFAULT_SOUND)
.addAction(R.drawable.abc_cab_background_top_holo_light, first_option, firstPendingIntent)
.addAction(R.drawable.abc_cab_background_top_holo_dark, second_option, secondPendingIntent)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_stat_name)
.build();
Whenever I debug in the broadcastReceiver, for some reason, action from extras always logs "do_that", even if I click the first or second button of the notification. Any reason for this? I cant really seem to understand why.
public class NotificationFunctions extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
boolean feedback;
String action = intent.getExtras().getString("action");
Log.wtf("...", action); //logs do_that
}}
Any reason for this?
Because firstPendingIntent == secondPendingIntent.
If there already is a PendingIntent matching your request, getBroadcast() returns the existing PendingIntent. FLAG_UPDATE_CURRENT says to replace the extras in the Intent wrapped inside the PendingIntent.
In one of your two getBroadcast() calls, replace 0 with some other number, to get distinct PendingIntent objects.
Also, I recommend that you replace getBaseContext() and getApplicationContext() with this. Only use getBaseContext() and getApplicationContext() when you know precisely why you are using them.

Recreate Activity when pressing the notification - how to?

I have a clickable notification, that opens my application when clicked. Howewer, old activity isn't deleted, so, when I close app, there's the same activity under previous...hope you understand.
So, how can I delete old activity?
The code below is situated in service. And I need to destroy Main activity.
void sendNotif() {
Intent in = new Intent(this, MainActivity.class);
PendingIntent pin = PendingIntent.getActivity(this, 0, in, 0);
Notification notif = new Notification.Builder(this)
.setContentTitle("App launched")
.setContentText("Press to open app")
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pin)
.build();
notif.flags |= Notification.FLAG_NO_CLEAR;
nm.notify(1, notif);
}
Kotlin:
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
val pendingIntent = PendingIntent.getActivity(applicationContext, 0,
intent, PendingIntent.FLAG_CANCEL_CURRENT)
Why don't you just add a flag to your Intent when you create your PendingIntent like this:
Intent in = new Intent(this, getClass()).addFlags(Intent.FLAG_CANCEL_CURRENT));
PendingIntent pin = PendingIntent.getActivity(this, 0, in, 0);
Try adding these flags to your intent.
in.setFlags(FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_NEW_TASK);
See this for explanation.
onPause()
{
MainActivity.this.finish();
}

Categories