I have a notification that have an action "Open Dial". I want when I click on "Open dial" action. My notification will disappear and Dial will appear.
I tried setAutocancel(true) and set notification.flags = Notification.FLAG_AUTO_CANCEL but these not working.
I know that I can't use SetAutocancel and set Flag_Auto_Cancel when I set action for my notification. If i want do that, I must use cancel(id) function of NotificationManager.
My idea to do that is sending an IntentFilter and using BroadcastReceiver to receive it When "Open Dial" is clicked.
But I don't know how I can do that because Intent.Action_Dial is an activity. If I use PendingIntent.getBroacast(), functions in onReceive() of Broadcast will work, but Dial won't show. Anyone know how I can resolve this problem ?.
This is my notication:
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle("Notification");
builder.setContentText("This is notification");
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setTicker("This is ticker");
Intent intent = new Intent(Intent.ACTION_DIAL);
PendingIntent pendingIntent = PendingIntent.getActivity(this, MSG_B, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.addAction(R.mipmap.ic_launcher, "Dial", pendingIntent);
builder.setAutoCancel(true);
Notification notification = builder.build();
notification.flags = Notification.FLAG_AUTO_CANCEL;
NotificationManager manager = (NotificationManager)this.getSystemService(NOTIFICATION_SERVICE);
manager.notify(id, notification);
this is my receiver
NotificationCompat.Builder builder;
Notification notification;
NotificationManager manager;
#Override
public void onReceive(Context context, Intent intent) {
manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if(intent.getAction().equals("download")){
Log.d("LOG","Download");
showNotify(3, context);
DownloadFileFromURL downloadFileFromURL = new DownloadFileFromURL();
downloadFileFromURL.execute("http://freebigpictures.com/wp-content/uploads/2009/09/river-edge.jpg");
}
else if(intent.getAction().equals("android.intent.action.DIAL")){
Log.d("LOG", "cacel Dial");
manager.cancel(NotificationServices.MSG_B);
}
else if(intent.getAction().equals("cancelActivity")){
Log.d("LOG","cacel Activity");
manager.cancel(NotificationServices.MSG_B);
}
else {
Log.d("LOG","Fail ABC");
}
}
This is mainifest
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".activity.MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".services.NotificationServices"
android:enabled="true"
android:exported="true">
</service>
<receiver android:name=".broadcast.BroadcastReceiverImage">
<intent-filter>
<action android:name="download"/>
<action android:name="cancelDial"/>
<action android:name="cancelActivity"/>
<action android:name="android.intent.action.DIAL"></action>
</intent-filter>
</receiver>
</application>
The solution is to start the Activity in the BroadcastReceiver, after cancelling the Notification. Here is the code for the PendingIntent:
Intent intent = new Intent();
intent.setAction("cancelDial");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, MSG_B, intent, PendingIntent.FLAG_UPDATE_CURRENT);
and the code for the BroadcastReceiver:
else if(intent.getAction().equals("cancelDial")){
Log.d("LOG", "Cancel Dial");
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
manager.cancel(NotificationServices.MSG_B);
}
Hopefully it will help someone in the future.
Related
I have download notification in my application. I've added "Cancel" button to NotificationCompat.Builder by calling addAction() method. But button not working on Android O device. When I press "Cancel" button nothing happens. But button working on Android < O.
My Notification:
NotificationCompat.Builder notification = new NotificationCompat.Builder(context, channelId)
.setContentTitle(title)
.setSmallIcon(R.drawable.network_download)
.setContentText(contentText)
.setOngoing(true)
.setContentIntent(null)
.addExtras(idBundle)
.addAction(R.drawable.cancel, context.getString(R.string.cancel), getCancelPendingIntent(context, id))
.setProgress(100, 30, true);
My PendingIntent :
private PendingIntent getCancelPendingIntent(Context context, int id){
return PendingIntent.getBroadcast(
context, id, new Intent("CANCEL_DOWNLOAD").putExtra("id", id), PendingIntent.FLAG_UPDATE_CURRENT);
}
Also I have NotificationReceiver :
public static class NotificationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ("CANCEL_DOWNLOAD".equals(action) && context != null){
int id = intent.getIntExtra("id", -1);
NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (mgr != null)
mgr.cancel(id);
FtpManager.getInstance(new AppExecutors(), CredentialsManager.getInstance().getCredentials(context))
.cancelDownloading();
}
}
}
In Manifest file I have :
<receiver
android:name="eu.warble.pjapp.util.NotificationsManager$NotificationReceiver"
android:exported="false">
<intent-filter>
<action android:name="CANCEL_DOWNLOAD" />
</intent-filter>
</receiver>
Never use an implicit Intent when an explicit Intent will do. Android O helps enforce this by banning the receipt of implicit Intent broadcasts from manifest-registered receivers.
Step #1: Remove the <intent-filter> from your <receiver> (which also means that you could get rid of android:exported="false", as that is now the default value)
Step #2: Replace new Intent("CANCEL_DOWNLOAD").putExtra("id", id) with new Intent(context, NotificationReceiver.class).putExtra("id", id)
Thank you very much CommonsWare. It works for me. This is my code
var notifyIntent = Intent(context, NotificationBroadcastReceiver::class.java)
notifyIntent.action = "ACTION_UPDATE_BADGE"//hardcode in manifest
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
// only for oreo and newer versions
notifyIntent = Intent(context, NotificationBroadcastReceiverAndroidO::class.java)
}
val pendingIntent = PendingIntent.getBroadcast(context, it, notifyIntent, PendingIntent.FLAG_ONE_SHOT)
In manifest
<receiver android:name=".firebase.NotificationBroadcastReceiver">
<intent-filter>
<action android:name="ACTION_UPDATE_BADGE" />
</intent-filter>
</receiver>
<receiver android:name=".firebase.NotificationBroadcastReceiverAndroidO">
<!--Android O not working when having this code
<intent-filter>
<action android:name="ACTION_UPDATE_BADGE" />
</intent-filter>-->
</receiver>
Create 2 classes:
open class NotificationBroadcastReceiver : BroadcastReceiver() {...}
open class NotificationBroadcastReceiverAndroidO : NotificationBroadcastReceiver() {/*do nothing*/}
I have download notification in my application. I've added "Cancel" button to NotificationCompat.Builder by calling addAction() method. But button not working on Android O device. When I press "Cancel" button nothing happens. But button working on Android < O.
My Notification:
NotificationCompat.Builder notification = new NotificationCompat.Builder(context, channelId)
.setContentTitle(title)
.setSmallIcon(R.drawable.network_download)
.setContentText(contentText)
.setOngoing(true)
.setContentIntent(null)
.addExtras(idBundle)
.addAction(R.drawable.cancel, context.getString(R.string.cancel), getCancelPendingIntent(context, id))
.setProgress(100, 30, true);
My PendingIntent :
private PendingIntent getCancelPendingIntent(Context context, int id){
return PendingIntent.getBroadcast(
context, id, new Intent("CANCEL_DOWNLOAD").putExtra("id", id), PendingIntent.FLAG_UPDATE_CURRENT);
}
Also I have NotificationReceiver :
public static class NotificationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ("CANCEL_DOWNLOAD".equals(action) && context != null){
int id = intent.getIntExtra("id", -1);
NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (mgr != null)
mgr.cancel(id);
FtpManager.getInstance(new AppExecutors(), CredentialsManager.getInstance().getCredentials(context))
.cancelDownloading();
}
}
}
In Manifest file I have :
<receiver
android:name="eu.warble.pjapp.util.NotificationsManager$NotificationReceiver"
android:exported="false">
<intent-filter>
<action android:name="CANCEL_DOWNLOAD" />
</intent-filter>
</receiver>
Never use an implicit Intent when an explicit Intent will do. Android O helps enforce this by banning the receipt of implicit Intent broadcasts from manifest-registered receivers.
Step #1: Remove the <intent-filter> from your <receiver> (which also means that you could get rid of android:exported="false", as that is now the default value)
Step #2: Replace new Intent("CANCEL_DOWNLOAD").putExtra("id", id) with new Intent(context, NotificationReceiver.class).putExtra("id", id)
Thank you very much CommonsWare. It works for me. This is my code
var notifyIntent = Intent(context, NotificationBroadcastReceiver::class.java)
notifyIntent.action = "ACTION_UPDATE_BADGE"//hardcode in manifest
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
// only for oreo and newer versions
notifyIntent = Intent(context, NotificationBroadcastReceiverAndroidO::class.java)
}
val pendingIntent = PendingIntent.getBroadcast(context, it, notifyIntent, PendingIntent.FLAG_ONE_SHOT)
In manifest
<receiver android:name=".firebase.NotificationBroadcastReceiver">
<intent-filter>
<action android:name="ACTION_UPDATE_BADGE" />
</intent-filter>
</receiver>
<receiver android:name=".firebase.NotificationBroadcastReceiverAndroidO">
<!--Android O not working when having this code
<intent-filter>
<action android:name="ACTION_UPDATE_BADGE" />
</intent-filter>-->
</receiver>
Create 2 classes:
open class NotificationBroadcastReceiver : BroadcastReceiver() {...}
open class NotificationBroadcastReceiverAndroidO : NotificationBroadcastReceiver() {/*do nothing*/}
I am trying to create a simple notification with a button (action) defined to it. I have managed to display it properly and create a PendingIntent for my action. I have also created a BroadcastReceiver which is supposed to be called when my action is clicked. But it's onReceive() method does not get called. I have no idea why. I also registered BroadcastReceiver in AndroidManifest.xml
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button notify = (Button) findViewById(R.id.notify);
notify.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent dismissIntent = new Intent("action1");
dismissIntent.setAction("action1");
PendingIntent action1intent = PendingIntent.getBroadcast(MainActivity.this, (int) System.currentTimeMillis(), dismissIntent, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(MainActivity.this)
.setSmallIcon(R.drawable.ic_menu)
.setContentTitle("My notification")
.setContentText("Hello World!")
.addAction(R.drawable.ic_menu, "action 1", action1intent);
Intent resultIntent = new Intent(MainActivity.this, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(MainActivity.this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
}
});
}
public class Receiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("log", "Receiving somthn");
String whichAction = intent.getAction();
if (whichAction.equals("action1")) {
MainActivity.makeToast("This is action 1", context);
}
}
}
public static void makeToast(String string, Context context) {
Toast.makeText(context, string, Toast.LENGTH_SHORT).show();
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.orglce.notification">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<receiver android:name=".MainActivity$Receiver">
<intent-filter>
<action android:name="com.example.orglce.notification.BROADCAST" />
</intent-filter>
</receiver>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
First, if you are going to use .MainActivity$Receiver, then Receiver needs to be a static class.
Second, dismissIntent is (redundantly) using action1 as the action string, but the <intent-filter> uses com.example.orglce.notification.BROADCAST. These do not match. I recommend getting rid of the <intent-filter>, getting rid of the action1, and using new Intent(this, Receiver.class) to create an explicit Intent to identify your BroadcastReceiver.
Your manifest has problem.
You add action to your notification intent with this name "action 1"
you should edit your action name in MainActivity like this:
Intent dismissIntent = new Intent("com.example.orglce.action1");
Edit your receiver like this:
<receiver android:name=".MainActivity$Receiver">
<intent-filter>
<action android:name="com.example.orglce.action1" />
</intent-filter>
</receiver>
Finally edit your if in broadcast receiver like this:
if (whichAction.equals("com.example.orglce.action")) {
MainActivity.makeToast("This is action 1", context);
}
After a Push Notification is received, I want to open an Àctivity when the Notification is pressed.
Here are my Services:
public class GCMIntentService extends GcmListenerService {
#Override
public void onMessageReceived(String from, Bundle data) {
String title = data.getString("title");
String message = data.getString("message");
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(message)
.setStyle(new NotificationCompat.BigTextStyle().bigText(message))
.setTicker(message)
.setAutoCancel(true);
mBuilder.setDefaults(Notification.DEFAULT_LIGHTS);
mBuilder.setDefaults(Notification.DEFAULT_SOUND);
mBuilder.setDefaults(Notification.DEFAULT_VIBRATE);
Intent myIntent = new Intent(this, MyActivity.class);
PendingIntent intent2 = PendingIntent.getBroadcast(this, 1, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(intent2);
notificationManager.notify(1, mBuilder.build());
}
public class GCMIDListenerService extends InstanceIDListenerService {
#Override
public void onTokenRefresh() {
InstanceID instanceID = InstanceID.getInstance(this);
String token;
try {
token = instanceID.getToken(Resources.getSystem().getString(R.string.gcm_defaultSenderId), GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
} catch (IOException e) {
e.printStackTrace();
}
//TODO:send token to the server
}
}
I just did everything following the Google documentation. I implemented that feature for another project sometime ago but it was a bit different, I used my own 'BroadcastReceiver' instead of the 'com.google.android.gms.gcm.GcmReceiver' provides by Google.
Here is my Manifest:
<application>
...
<!-- GCM Push Notifications Config -->
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="gcm" />
</intent-filter>
</receiver>
<service
android:name=".push.GCMIntentService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<service
android:name=".push.GCMIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
</application>
Any ideas? Am I missing something?
Here some documentation I have follow:
Google official documentation
CGM tutorial By Dustin Rothwell
And of course I have researched a lot here at stackoverflow.
Thanks!
You have done one minor mistake. You are writing this code for opening activity.
PendingIntent intent2 = PendingIntent.getBroadcast(this, 1, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(intent2);
As you want to open activity you need to create pending intent using getActivity method instead of getBroadcast method.
Hope this will help.
The following is my code that configures notification bar.
PendingIntent pi = PendingIntent.getActivity(
getApplicationContext(),
0,
new Intent(getApplicationContext(), AudioActivity.class),
PendingIntent.FLAG_UPDATE_CURRENT
);
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_action_star)
.setContentTitle("My app")
.setContentText("works")
.setContentIntent(pi);
mNotificationManager = (NotificationManager) getSystemService(
Context.NOTIFICATION_SERVICE
);
mNotificationManager.notify(NOTIFICATION_ID, builder.build());
At runtime, I first show AudioActivity at front-ground, then I open the notification bar that shows a message like "My app works". Clicking on the message opens AudioActivity again.
But it seems that the system calls the onCreate method of AudioActivity when I click notification bar. And before that it does not call the onDestroy of the existing AudioActivity. I was wondering if I have two AudioActivity instances running, and how I can manage them. What I expected is it should have worked as how activities are switched and onStart is used rather onCreate.
Thanks.
The best solution for you is to make it call onNewIntent and reuse the existing activity
In the called activity:
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if ("action.action.myactionstring".equals(intent.getAction())) {
finish();
}
}
In the called activities mainfest entry
<activity android:name=".MyNotifiedActivity" >
<intent-filter>
<action android:name="action.action.myactionstring" />
...
</intent-filter>
</activity>
When creating the pending intent
Intent myIntent = new Intent("action string");
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pi = PendingIntent.getActivity(
getApplicationContext(),
0,
myIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
The Intent.FLAG_ACTIVITY_SINGLE_TOP flag tells android to reuse the existing instance of the activity (if it exists). onNewIntent is called instead of onCreate, if it isnt already running, the it calls onCreate as usual
#Nick Cardoso: Here is the changed code. I think it works in the way that it does not call onCreate. I was only wondering why it does not call onNewIntent as you expected. Thanks.
PendingIntent pi = PendingIntent.getActivity(
getApplicationContext(),
0,
new Intent("com.example.myapp.ACTION_NOTIFICATION"),
PendingIntent.FLAG_UPDATE_CURRENT
);
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_action_star)
.setContentTitle("My app")
.setContentText("works")
.setContentIntent(pi);
mNotificationManager = (NotificationManager) getSystemService(
Context.NOTIFICATION_SERVICE
);
mNotificationManager.notify(NOTIFICATION_ID, builder.build());
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.ourradio.AudioActivity"
android:label="#string/title_activity_audio"
android:parentActivityName="com.example.ourradio.FeedActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.ourradio.FeedActivity" />
<intent-filter>
<action
android:name="com.example.myapp.ACTION_NOTIFICATION" />
</intent-filter>
</activity>
<service
android:name="com.example.ourradio.AudioService"
android:label="#string/label_service_audio" >
</service>
</application>
#Joe C , a simpler solution maybe add the SINGLE_TOP flag in the androidManifest as a launchMode in the activity like this:
<activity
android:name="com.example.ourradio.AudioActivity"
android:label="#string/title_activity_audio"
android:parentActivityName="com.example.ourradio.FeedActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
you can see this link for more information: http://www.intridea.com/blog/2011/6/16/android-understanding-activity-launchmode