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);
}
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 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 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.
I cannot use registerReceiver in BroadcastReceiver. I read that I cannot do that then how should I confirm that my SMS has been sent?
BroadCastReceiver
public class MyReceiver extends BroadcastReceiver {
String SENT="sent";
String DELIVERED="delivered";
public final String tag="com.example.pritesh.smstimer";
public MyReceiver() {
}
//#Override
public void onReceive(Context context, Intent intent) {
Log.i(tag,"Sending");
final NotificationManager notificationManager= (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent1=new Intent(context,Time_Picker.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context,0,intent1,0);
//Notification for sent msg
final Notification.Builder notification_sent=new Notification.Builder(context)
.setContentTitle("SMS SENT")
.setContentText("Your SMS has Been Sent")
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.favicon);
//Notification for msg not sent
final Notification.Builder notification_notsent=new Notification.Builder(context)
.setContentTitle("SMS SENT")
.setContentText("Your SMS was not sent due to no network service")
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.favicon);
//Intent for sending confirmation
Intent sent=new Intent(SENT);
//PendingIntent for sending confirmation
PendingIntent sentIntent=PendingIntent.getBroadcast(context,0,sent,PendingIntent.FLAG_UPDATE_CURRENT);
//Receiver for sent confirmation
Intent deliveryIntent = new Intent(DELIVERED);
PendingIntent deliverPI = PendingIntent.getBroadcast(
context, 0, deliveryIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
context.registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String result = "";
switch (getResultCode()) {
case Activity.RESULT_OK:
result = "Transmission successful";
notificationManager.notify(0,notification_sent.build());
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
result = "No service";
notificationManager.notify(0,notification_notsent.build());
break;
}
}
},new IntentFilter(SENT));
context.registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Deliverd",
Toast.LENGTH_LONG).show();
}
}, new IntentFilter(DELIVERED));
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(Time_Picker.Phone,null, Time_Picker.Message, sentIntent
,deliverPI);
Toast.makeText(context, "Sms Sent", Toast.LENGTH_LONG).show();
}
}
How should I send the sentIntent to confirm whether sms sent or not
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.pritesh.smstimer" >
<uses-permission android:name="android.permission.SEND_SMS" />
<application
android:allowBackup="true"
android:icon="#drawable/favicon"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme" >
<activity
android:name=".Time_Picker"
android:theme="#style/AppTheme.NoActionBar" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:excludeFromRecents="true"
android:exported="true"
android:launchMode="singleTask"
android:taskAffinity="" />
<receiver
android:name=".NotificationReciever"
android:enabled="true"
android:exported="true" >
</receiver>
</application>
</manifest>
You cannot register dynamic BroadcastReceivers inside of another BroadcastReceiver. This is because the system enforces that a BroadcastReceiver finishes it's work within a short period of time (I think it's either 5 or 10 seconds).
You can create another BroadcastReceiver that is registered in your AndroidManifest. The <intent-filter> should include <action> elements that match the custom action strings you use in your code.