I have application, which makes event in alarm manager, and at specific time its called.
Code looks like this
Intent intent = new Intent(this, AlarmActivity.class);
pendingIntent = PendingIntent.getActivity(this,req_code, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager)getSystemService(Activity.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),AlarmManager.INTERVAL_DAY*7,
pendingIntent);
Intent calls this activity.
public class AlarmActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void onStart(){
super.onStart();
//Change ringer mode
//Add notification in status bar
//Other booring stuff here...
Toast.makeText(this,"Finishing",2000).show();
finish();
}
}
in booring stuffthere are is code which should run in background (change ringermode)
Everything works for me, except one thing. Whenever the alarm manager calls my activity - the application comes to foreground.
When it only should change ringer mode in background, and add notification in status bar.
Any way to not allow application come to foreground?
You should do all of this in a BroadCastReceiver. There is no UI, and there is a Context variable passed on to the Receiver's onReceive() method which allows you to basically do anything the Activity does, without having an actual UI. This means that you can set the ringer, show the status bar notification, etc.
Your BroadcastReceiver class should look something like:
public class AlarmBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Change ringer mode
//Add notification in status bar
//Other boring stuff here...
Toast.makeText(context,"Finishing",2000).show();
}
}
Note that for your Toast, the variable named context is used.
And your AlarmManager code should look something like this:
Intent intent = new Intent(this, AlarmBroadcastReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this,req_code, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager)getSystemService(Activity.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),AlarmManager.INTERVAL_DAY*7,
pendingIntent);
Your manifest should have this:
<receiver android:name=".AlarmBroadcastReceiver" >
</receiver>
Add this line to the Activity in your AndroidManifest
android:theme="#android:style/Theme.NoDisplay"
and you have an Activity with nothing to display. Since you are already calling finish(); in your code, it will look like it is running in background.
Related
Having quite a bit of trouble getting my foreground service to simply dismiss on swipe or by the clear all notifications button. I know there are several questions like this, but I have read them and will list some of what I've already tried. I tried this method, where you pass a simple intent with an extra into a pending intent, then add that pending intent to setDeleteIntent(). That didn't work, it never gets called.
I also tried this (second highest answer, "fully fleshed out" version), with the same results. Which ties in to the "answer" of this question as well. With how many apps have notifications that are dismissible with a swipe or clear all button, I must be missing something very obvious and I can't figure out what.
What my current code looks like (all of this inside of my service class).
BroadcastReceiver class
public class NotificationDismissedReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// this is never called
stopSelf();
}
}
// in the manifest for that BroadcastReceiver, have also tried it with these values false
android:exported="true"
android:enabled="true"
Pending intent
private PendingIntent createOnDismissedIntent(Context context, int notificationId) {
Intent intent = new Intent(context.getApplicationContext(), NotificationDismissedReceiver.class);
PendingIntent pendingIntent =
PendingIntent.getBroadcast(context.getApplicationContext(),
notificationId, intent, 0);
return pendingIntent;
}
In the notification builder (101 is what I startForeground with)
.setDeleteIntent(createOnDismissedIntent(this, 101))
Edit:
Separate file receiver used instead of the inner class version.
public class NotificationDismissedReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
int notificationId = intent.getExtras().getInt("notificationId");
/* Your code to handle the event here */
if(notificationId == 101){
Intent stopIntent = new Intent(context, AssistorServiceClass.class);
context.stopService(stopIntent);
}
}
}
Edit2
To be clear, I'm not trying to stop the foreground notification and keep the service alive. I want them both just gone, as if I called stopSelf within the service class.
I want my android app to pop-up an alert dialog box at specific time of each day. Of what I have understood is that we need to use Alarm manager to set the time of the day on repeating, and then send a broadcast to display the alert dialog box. The alert box should be displayed at the specified time even if the app is closed. I have tried the following code but it does not do anything at the specified time. Please suggest what needs to be done. I am new to android development and this is my very first implementation.
Main_Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR,Calendar.MONTH,Calendar.DAY_OF_MONTH,6, 10);
setAlarm(calendar.getTimeInMillis());
}
private void setAlarm(long timeInMillis) {
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlertBox.class);
PendingIntent penIntent = PendingIntent.getBroadcast(this,0,intent,0);
am.setRepeating(AlarmManager.RTC_WAKEUP,timeInMillis,AlarmManager.INTERVAL_DAY,penIntent);
//Toast.makeText(this,"Alarm is set",Toast.LENGTH_SHORT).show();
}
AlertBox
#Override
public void onReceive(Context context, Intent intent) {
DisplayAlertBox(context, "Tip of the Day");
}
private void DisplayAlertBox(Context context, String msg) {
Toast.makeText(context, "Dialog Box should display Now", Toast.LENGTH_LONG).show();
PendingIntent alertBox = PendingIntent.getActivity(context,0, new Intent(context,MainActivity.class),0);
AlertDialog.Builder aBuilder = new AlertDialog.Builder(context);
aBuilder.setTitle("Message");
aBuilder.setMessage(msg);
aBuilder.setPositiveButton("Accept",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int whichButton)
{
}});
aBuilder.create();
aBuilder.show();
}
The reason why nothing is happening is because you don't have a clear understanding of BroadcastReceiver.
BroadcastReceivers, once registered, will sit there waiting for a broadcast that it can receive. Registering a BroadcastReceiver can be done in both your Manifest file or through your code. The broadcast that it can wait to receive can be either an implicit or explicit broadcast. But in your case, it's an explicit broadcast. So you would declare it in your Manifest like so:
<receiver android:name="com.package.AlertBox">
<intent-filter>
<action android:name="can.be.any.name.like.tip.of.the.day"
</intent-filter>
</receiver>
You may also register the BroadcastReceiver through code if you don't want to do so through the Manifest.
Your problem is that the intent that you're sending to your AlarmManager is Intent intent = new Intent(this, AlertBox.class). What this does is that it's only going to start your BroadcastReceiver, which isn't necessary once it's already registered. It's onReceive() is never called this way.
Your AlertBox will only show the AlertDialog when onReceive() is called, but onReceive is never called because a BroadcastReceiver's onReceive is only called when it receives the broadcast it's registered to receive.
So your setAlarm() method should be written like this:
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent("can.be.any.name.like.tip.of.the.day");
PendingIntent penIntent = PendingIntent.getBroadcast(this,0,intent,0);
am.setRepeating(AlarmManager.RTC_WAKEUP, timeInMillis, AlarmManager.INTERVAL_DAY, penIntent);
Keep in mind that the String that's used as the action of the Intent must match the String that your Broadcast Receiver is listening to. This way, the onReceive() method will be able to trigger.
However, I should also mention that the BroadcastReceiver should not be where you run your AlertDialog. BroadcastReceivers are meant for short execution of codes and are not meant to persist for a lengthy amount of time. For that, an Activity or Service would be a better option.
You should consider having the AlarmManager launch a transparent Activity that hosts a DialogFragment instead.
I want to know is there a way for the NotificationListenerService to know if a Notification has been clicked or it has been dismissed. I can see that the Inner class NotificationListenerWrapper in NotificationListenerService has a onNotificationClick() method , but since the NotificationListenerWrapper is hidden with #hide annotation I'm not able to use that.
My question is Can I write a Listener which basically keeps track of whether a notification has been clicked or dismissed.
Basically I want to track if the notifications of my App is being dismissed or they are clicked without any intrusive code in each and every Notification.
P.S. NotificationListenerService provides only onNotificationPosted() and onNotificationRemoved(), but my requirement is to know if notifications are clicked or Removed.
Thanks
When you create and show a notification, you provide a PendingIntent for when it is clicked (using .setContentIntent). You can also define a PendingIntent for when it gets dismissed(using .setDeleteIntent(PendingIntent).
If you want to be able to track your Notifications, you need to pass a PendingIntent (like a BroadcastReceiver or IntentService) and pass a few parameters like notificationId and isDismissed and do your work in the BroadcastReceiver.
You can see the complete code in this answer.
I don't think there is a listener for this. But you can implement this logic in another way using PendingIntent and BroadcastReceiver
For OnClick
add a ContentIntent and BroadcastReceiver. So you will know that your notification is clicked or not in the BroadcastReceiver
Intent onClickIntent = new Intent(this, OnClickBroadcastReceiver.class);
PendingIntent onClickPendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0, onClickIntent, 0);
mBuilder.setContentIntent(onClickPendingIntent);
And inside the BroadcastReceiver you can write your logic
public class OnClickBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Open your activity here
Intent mainIntent = new Intent(context, YourActivity.class);
context.startActivity(mainIntent);
// Do your onClick related logic here
}
}
For onDismiss
For this you need to add a DeleteIntent into your notification builder
Intent onCancelIntent = new Intent(this, OnCancelBroadcastReceiver.class);
PendingIntent onDismissPendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0, onCancelIntent, 0);
mBuilder.setDeleteIntent(onDismissPendingIntent);
and BroadcastReceiver for this is
public class OnCancelBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Do your logic here
}
}
Don't forget to register these BroadcastReceiver to AndroidManifest
I've poured through a dozen tutorials and forum answers about this problem, but still haven't been able to get some working code together. I'll try to keep the question straightforward:
How do you use AlarmManager (in the Android API) to start an Activity at a given time? Any solution to this problem will do.
My latest attempt to achieve this is below.
(Imports omitted. I expect MyActivity to start 3 seconds after the program is opened, which it doesn't. There are no error messages to speak of.)
public class AndroidTest2Activity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Context context = this;//.getApplicationContext();
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); // CORRECT
Intent intent = new Intent(context, myReceiver.class); // CORRECT
PendingIntent pending = PendingIntent.getBroadcast( context, 0, intent, 0 ); // CORRECT
manager.set( AlarmManager.RTC, System.currentTimeMillis() + 3000, pending ); // CORRECT
setContentView(R.layout.main);
}
}
public class myReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Intent i=new Intent(context, myActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
public class myActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("", "Elusive success");
setContentView(R.layout.main);
}
}
Any advice would be appreciated.
Please note: I've got myReceiver in the manifest already
In case someone else stumbles upon this - here's some working code (Tested on 2.3.3 emulator):
public final void setAlarm(int seconds) {
// create the pending intent
Intent intent = new Intent(MainActivity.this, AlarmReceiver.class);
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0,
intent, 0);
// get the alarm manager, and scedule an alarm that calls the receiver
((AlarmManager) getSystemService(ALARM_SERVICE)).set(
AlarmManager.RTC, System.currentTimeMillis() + seconds
* 1000, pendingIntent);
Toast.makeText(MainActivity.this, "Timer set to " + seconds + " seconds.",
Toast.LENGTH_SHORT).show();
}
public static class AlarmReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Log.d("-", "Receiver3");
}
}
AndroidManifest.xml:
<receiver android:name="com.example.test.MainActivity$AlarmReceiver" >
</receiver>
Issues with BenLambell's code :
EITHER:
Move the receiver to it's own .java file or
make the inner class static - so it can be accessed from outside
Receiver is not declared correctly in the manifest:
if it's an inner class in MainActivity use:
<receiver android:name="package.name.MainActivity$AlarmReceiver" ></receiver>
if it's in a separate file:
<receiver android:name="package.name.AlarmReceiver" ></receiver>
If your intention is to display a dialog in the receiver's onReceive (like me): that's not allowed - only activities can start dialogs. This can be achieved with a dialog activity.
You can directly call an activity with the AlarmManager:
Intent intent = new Intent(MainActivity.this, TriggeredActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
((AlarmManager) getSystemService(ALARM_SERVICE)).set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + seconds * 1000, pendingIntent);
How do you use AlarmManager (in the Android API) to start an Activity at a given time?
Supply a PendingIntent to the set() call that identifies the activity to start up. Or, do what you're doing, which should work just fine.
This sample project is a bit elaborate, because it's 19 tutorials deep into one of my books, but if you look at classes like EditPreferences, OnBootReceiver, and OnAlarmReceiver, you will see the same basic recipe that you're using above. In this case, I could have just used a getActivity() PendingIntent, but the tutorial after this one gives the user a choice of launching an activity or displaying a Notification, so a BroadcastReceiver makes more sense.
Look for warnings in addition to errors in LogCat. Most likely, your receiver or activity is not in your manifest.
Note that popping up an activity out of the middle of nowhere is generally not a good idea. Quoting myself from the book in question:
Displaying the lunchtime alarm via a full-screen activity certainly works,
and if the user is looking at the screen, it will get their attention. However,
it is also rather disruptive if they happen to be using the phone right that
instant. For example, if they are typing a text message while driving, your
alarm activity popping up out of nowhere might distract them enough to
cause an accident. So, in the interest of public safety, we should give the user an option to
have a more subtle way to remind them to have lunch.
add this in your android mainifest file and it will hopefully work
<activity android:name=".MyReceiver" />
<receiver android:name=".MyReceiver"> </receiver>
In my experience you can achieve this without broadcast receiver, just use PendingIntent.getActivity() instead of getbroadcast()
private void setReminder(){
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Calendar startTime = Calendar.getInstance();
startTime.add(Calendar.MINUTE, 1);
Intent intent = new Intent(ReminderActivity.this, ReminderActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(ReminderActivity.this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC, startTime.getTimeInMillis(), pendingIntent);
}
I've tested this code on android O but I'm not sure about other android versions please inform me if this doesn't work on any other android version.
Main Problem : if you close completely you're app and expect to start you're activity after 3 seconds, you wrong. because when you close you're app , you're app cant receive broadcast, for solve this problem use services instead of broadcasts.
Point: when you're service would ran ,you cant start your activity if your app wouldn't in foreground.
Solution: I think when your service started you can again set Alarmmanager to start your activity with PendingIntent for just now.
Remember :
When you create your intent for pass it to pendingIntent add the FLAG_ACTIVITY_NEW_TASK to it.
For this PendingIntent use PendingIntent.getActivity() method and for the first PendingIntent use PendingIntent.getService() method.
I hope this help you.
I had this problem too long ago to know which answer is correct, but thank you to everyone for their responses. I'm self-answering so the question isn't still open.
According to Java convention class name begin with Capital letter.So change your
"myReceiver" to "MyReceiver" and "myActivity" to "MyActivity".
Then add your receiver in the manifest file like the below.
<application
------------
<receiver android:name="MyReceiver"></receiver>
---------------------
</application>
you are not sending any broadcast for the receiver to receiver and further more it lokks like u want a splash screen or something like that for that purpose u can start a new thread wait for some sec then start ur activity in that and for that time period u can do what ever u want on the UI thread ...
This is my code:
public class Alarm extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
intent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (10 * 1000), pendingIntent);
Toast.makeText(this, "Alarm set", Toast.LENGTH_LONG).show();
}
}
and
public final class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Alarm worked.", Toast.LENGTH_LONG).show();
}
}
By the above code i am able to get the Toast. Instead of Toast I want the Dialog to be appear after the alarm is set. Also I want to play the sound.
Any one help me please?
You cannot display a Dialog from a BroadcastReceiver or Service. You will be better served using an Activity (perhaps one using Theme.Dialog) and calling startActivity().
Bear in mind, though, that users tend to really dislike it when background stuff pops up activities unannounced. For some apps -- alarm clocks, VOIP clients, etc. -- the user may be OK with it.
There is a cool trick to do that.
Here are the steps to do it:
Place the BroadcastReceiver inside your Activity as an inner class.
Instead of adding the BroadcastReceiver in the manifest, you register yourself in the onStart() method of your Activity.
You unregister in the onPause() method of your Activity.
Inside the BroadcastReceiver you can call an Activity's method that do exactly what you ask for.