I am building a notification app, that uses alarm manager to set multiple notifications to reminde user of daily tasks, when phone is On everything is good, but when a reboot the phone, the notification is showing up but the notification data are lost (for example notification content) those data are saved into intent from my first activity
this is code bellow. (i have added permission and receive action to my manifest)please I need some help
public class add_rreminde extends AppCompatActivity implements View.OnClickListener{
private int notificationId=1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_rreminde);
//buton ok
findViewById(R.id.but).setOnClickListener(this);
findViewById(R.id.cancel).setOnClickListener(this);
}
#Override
public void onClick(View view){
EditText remide=findViewById(R.id.edit);
DatePicker date=findViewById(R.id.date);
Intent intent=new Intent(add_rreminde.this,AlarmReciver.class);
intent.putExtra("notificationId",notificationId);
intent.putExtra("todo",remide.getText().toString());
final int _id=(int)System.currentTimeMillis();
PendingIntent alarmIntent=PendingIntent.getBroadcast(add_rreminde.this,_id,intent,PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarm=(AlarmManager)getSystemService(ALARM_SERVICE);
switch (view.getId()){
case(R.id.but):
int day=date.getDayOfMonth();
int month=date.getMonth();
int year=date.getYear();
//create date
Calendar startDate=Calendar.getInstance();
startDate.set(Calendar.DAY_OF_MONTH,day);
startDate.set(Calendar.MONTH,month);
startDate.set(Calendar.YEAR,year);
Long alarmStartDate=startDate.getTimeInMillis();
//setAlarme
alarm.set(AlarmManager.RTC_WAKEUP,alarmStartDate,alarmIntent);
Toast.makeText(getApplicationContext(),"done",Toast.LENGTH_LONG).show();
break;
case (R.id.cancel):
alarm.cancel(alarmIntent);
Toast.makeText(getApplicationContext(),"canceled",Toast.LENGTH_LONG).show();
break;
}
}
}
my reciver that push notification
public class AlarmReciver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//get id from notification id intent
int notification =intent.getIntExtra("notificationId",0);
String getMessage=intent.getStringExtra("todo");
//when notification is opened open mainActivity
Intent mainIntent=new Intent(context,add_rreminde.class);
PendingIntent contentIntent=PendingIntent.getActivity(context,0,mainIntent,0);
NotificationManager mynotificationManager=(NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
//prepare notification
Notification.Builder builder=new Notification.Builder(context);
builder.setSmallIcon(R.drawable.assistant)
.setContentTitle("changer oil")
.setContentText(getMessage)
.setWhen(System.currentTimeMillis())
.setAutoCancel(true)
.setContentIntent(contentIntent)
.setPriority(Notification.PRIORITY_MAX)
.setDefaults(Notification.DEFAULT_ALL);
//notify
mynotificationManager.notify(notification,builder.build());
}
}
By default, all alarms are canceled when a device shuts down. To
prevent this from happening, you can design your application to
automatically restart a repeating alarm if the user reboots the
device.
so you could add a BroadcastReceiver to receive ACTION_BOOT_COMPLETED
firstly:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
and:
<receiver android:name=".SampleBootReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
now you set alarm again when device reboot:
public class SampleBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
// Set the alarm here.
}
}
}
Related
I know that you can launch Activities from the action buttons using PendingIntents. How do you make it so that the a method gets called when the user clicks the notification action button?
public static void createNotif(Context context){
...
drivingNotifBldr = (NotificationCompat.Builder) new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.steeringwheel)
.setContentTitle("NoTextZone")
.setContentText("Driving mode it ON!")
//Using this action button I would like to call logTest
.addAction(R.drawable.smallmanwalking, "Turn OFF driving mode", null)
.setOngoing(true);
...
}
public static void logTest(){
Log.d("Action Button", "Action Button Worked!");
}
You can't directly call methods when you click action buttons.
You have to use PendingIntent with BroadcastReceiver or Service to perform this. Here is an example of PendingIntent with BroadcastReciever.
First lets build a Notification
public static void createNotif(Context context){
...
//This is the intent of PendingIntent
Intent intentAction = new Intent(context,ActionReceiver.class);
//This is optional if you have more than one buttons and want to differentiate between two
intentAction.putExtra("action","actionName");
pIntentlogin = PendingIntent.getBroadcast(context,1,intentAction,PendingIntent.FLAG_UPDATE_CURRENT);
drivingNotifBldr = (NotificationCompat.Builder) new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.steeringwheel)
.setContentTitle("NoTextZone")
.setContentText("Driving mode it ON!")
//Using this action button I would like to call logTest
.addAction(R.drawable.smallmanwalking, "Turn OFF driving mode", pIntentlogin)
.setOngoing(true);
...
}
Now the receiver which will receive this Intent
public class ActionReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Toast.makeText(context,"recieved",Toast.LENGTH_SHORT).show();
String action=intent.getStringExtra("action");
if(action.equals("action1")){
performAction1();
}
else if(action.equals("action2")){
performAction2();
}
//This is used to close the notification tray
Intent it = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
context.sendBroadcast(it);
}
public void performAction1(){
}
public void performAction2(){
}
}
Declare Broadcast Receiver in Manifest
<receiver android:name=".ActionReceiver" />
Hope it helps.
I am new to this part of android, and here I aim to use alarm manager to run a code snippet every 2 minute which will poll a server (using the website's api) and based on the returned JSON generate notification.
After a looking up the web I thought one of the best option in my case will be using intent service and android.
Manifest of Services and Recievers
<service
android:name=".NotifyService"
android:enabled="true"
android:exported="false" >
</service>
<receiver
android:name=".TheReceiver"
android:enabled="true"
android:exported="true" >
</receiver>
<receiver
android:name=".OnOffReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
Part in the flash screen activity where I call the intent service which is responsible for polling for notification:
Intent msgIntent = new Intent(this, NotifyService.class);
startService(msgIntent);
The receiver to start the alarm on device start:
public class OnOffReceiver extends BroadcastReceiver
{
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
public OnOffReceiver(){}
#Override
public void onReceive(Context context, Intent intent)
{
Intent service = new Intent(context, NotifyService.class);
service.setAction(NotifyService.CREATE);
context.startService(service);
}
}
The IntentService Class
public class NotifyService extends IntentService
{
public NotifyService()
{
super("NotifyService");
}
public static final int STATUS_RUNNING = 0;
public static final int STATUS_FINISHED = 1;
public static final int STATUS_ERROR = 2;
#Override
protected void onHandleIntent(Intent intent)
{
if (intent != null)
{
final String action = intent.getAction();
}
StartStuff();
}
public void StartStuff()
{
Intent intent = new Intent(this, TheReceiver.class);
PendingIntent pend_intent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,1200,1200, pend_intent);
//1200ms to make it easier to test
}
}
The receiver class which sets notification, for testing pupose I am not doing any network related work here just making a simple notification to check if the app is running in all situations
public class TheReceiver extends BroadcastReceiver
{
public TheReceiver(){}
#Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context, " Success ", Toast.LENGTH_SHORT).show();
Log.d("Notification", "The Receiver Successful");
showNotification(context);
}
private void showNotification(Context context)
{
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context).setContentTitle("My notification").setContentText("Hello World!");
mBuilder.setDefaults(Notification.DEFAULT_SOUND);
mBuilder.setAutoCancel(true);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, mBuilder.build());
}
}
However the notification come only when the app is running or in the recent apps tray.
It does not start notifying when the phone reboots, nor does it notify after the app is removes from the recent apps tray.
The app needs Notify users like other apps (like gmail, whatsapp) do, even if they are swiped out of the recent apps tray.
Timeliness and punctuality are not very big issue as delay up to 5 to 10 minutes are tolerable. (I intend to poll ever 2 minutes though.)
Where am I going wrong? Also, is there a better way to go about the problem?
To keep a receiver active after closing the app is to use
android:process=":remote"
in the manifest file for the receiver that needs to be kept alive.
<receiver
android:name=".TheAlarmReceiver"
android:process=":remote">
</receiver>
in the manifest for the receiver (TheReceiver in this case) that we need to keep active after the app closes.
P.S. : I also changed the way I use IntentsService and AlarmManager for the application, as my previous(above) implementation is not a very good way to go around it.
If an App is killed from recent apps or from "force stop" it won't restart by itself. The user has to start the app again in order to make it run again. There is no way to prevent this. It's just the way android works.
However there is a way to make your app run oon boot. Check out this link.
I have just implemented Parse push notifications into my app. I want to be able to show the push notification, but i don't want the app to open when the user presses the Push notification. Instead, i just want the notification to be dismissed.
i would imagine it would be handled by the ParsePushBroadcastReciever, but i can't find anything online which fits my purpose.
Here is my subclassed ParsepushBroadcastReciever:
public class Receiver extends ParsePushBroadcastReceiver {
#Override
public void onPushOpen(Context context, Intent intent) {
Log.e("Push", "Clicked");
Intent i = new Intent(context, HomeScreen.class);
i.putExtras(intent.getExtras());
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
In order for you to programatically dismiss a notification you will need to call cancel() using a NotificationManager instance passing in the ID that was passed into notify() on the NotificationManager (since this is what actually pushes the notification into the notification pane). You can't do this using the Parse SDK alone since you will need to take control of the population of notifications yourself.
First you will need to setup a NotificationManager instance then when a notification is ready to be pushed you assign it a value that you can reference later when cancelling like this:
public class MyParsePushBroadcastReceiver extends ParsePushBroadcastReceiver {
NotificationManager mNotificationManager;
int notification_id = 0;
#Override
public void onPushOpen(Context context, Intent intent) {
Log.e("Push", "Clicked");
mNotificationManager.cancel(notification_id)
}
#Override
public void onReceive(Context context, Intent intent) {
mNotificationManager = (NotificationManager)context.getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
super.onReceive(context, intent);
...
}
#Override
protected Notification getNotification(Context context, Intent intent) {
Notification n = super.getNotification(context, intent);
notification_id = intent.getExtras().getInt("NOTIFICATION_TYPE");
mNotificationManager.notify(notification_id, n);
return null;
}
}
So you see by taking control of the NotificationManager (instead of passing it off to the Parse SDK to assign some unknown value) we can know exactly which values to use when calling cancel. I am letting the system build my Notification object (and I get it using super.getNotification()) but you are free to also use a Notification builder to create the notification yourself as well.
I have a subclassed BroadCastReceiver inside my main activity in an android application to deal with changing the GUI when a GCM comes in. All of this works fine.
The one thing that doesn't work is that if this gets called then the user has my app open on his device, and as such I want to clear the notification I entered into the notification center for this incoming GCM. If I put the cancelAll() and cancel(int) lines into my GCMIntentService, then it dismisses the notifications, but I cannot keep it there since I only want to dismiss this notification if the user has my app open. I used both the cancel() and cancelAll() to make sure that I wasn't somehow passing the wrong notification id from the IntentService (I have verified it is correct).
The problem is that there is no error and the notification in the notification center simply won't go away. I have verified that this method is getting called since I get the log entries in logcat.
I referenced this prior answer, but it doesn't work in my implementation for some reason: Starting and stopping a notification from broadcast receiver
My code inside my main activity:
private class NotificationBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.v("Push", "Received Push Notification!");
//Now that the user has opened the app, cancel the notification in the notification center if it is still there
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
final int NOTIFICATION_ID = intent.getIntExtra("notificationId",0);
Log.v("NOTIFICATION_ID",Integer.toString(NOTIFICATION_ID));
mNotificationManager.cancel(NOTIFICATION_ID);
mNotificationManager.cancelAll();
Log.v("Canceled Notifs","Canceled");
}
}
Any ideas why?
A potentially better option is, instead of posting the notification while the app is open, to first detect if the app is visible and, if it is, don't display the notification. You can do this using Intent broadcasts or an event bus like EventBus or Otto.
Example:
public class GCMReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// this is your receiver after gcm has been received
Intent appOpenCheck = new Intent("com.example.IS_APP_OPEN");
// put extras about your notification here...
context.sendOrderedBroadcast(appOpenCheck);
}
}
public class AppNotOpenReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// this is your receiver that will be hit if the app isn't open
// post your notification to the NotificationManager
}
}
Then, in AndroidManifext.xml:
<receiver
android:name=".AppNotOpenReceiver">
<intent-filter>
<action android:name="com.example.IS_APP_OPEN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
Finally, in your Activity:
BroadcastReceiver appOpenAlert = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
abortBroadcast(); // prevents notification from going further
// this is your receiver that will be hit if the app is open
// update your ui
}
}
#Override
public void onStart() {
super.onStart();
IntentFilter notificationReceived = new IntentFilter();
notificationReceived.addAction("com.example.IS_APP_OPEN");
notificationReceived.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
registerReceiver(appOpenAlert, notificationReceived);
}
#Override
public void onStop() {
unregisterReceiver(appOpenAlert);
super.onStop();
}
I've just started with Android development. I've created an App Engine connected Android Project in Eclipse by following this guide: Creating an App Engine Connected Android Project.
The app works, but when the task goes to background and then is activated again by receiving a GCM message, intents invoked by the GCMIntentService class do not reach the corresponding activity. What might be the problem?
public class GCMIntentService extends GCMBaseIntentService {
[...]
#Override
public void onMessage(Context context, Intent intent) {
sendNotificationIntent(context, "Message received via Google Cloud Messaging:\n\n" + intent.getStringExtra("message"), true, false);
}
[...]
private void sendNotificationIntent(Context context, String message, boolean isError, boolean isRegistrationMessage) {
Intent notificationIntent = new Intent(context, RegisterActivity.class);
notificationIntent.putExtra("gcmIntentServiceMessage", true);
notificationIntent.putExtra("registrationMessage", isRegistrationMessage);
notificationIntent.putExtra("error", isError);
notificationIntent.putExtra("message", message);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(notificationIntent);
}
[...]
}
Thanks in advance!
// add permission <uses-permission android:name="android.permission.WAKE_LOCK" />
#Override
public void onMessage(Context context, Intent intent) {
sendNotificationIntent(context, "Message received via Google Cloud Messaging:\n\n" + intent.getStringExtra("message"), true, false);
context.sendBroadcast(intent) ;
}
private void sendNotificationIntent(Context context, String message, boolean isError, boolean isRegistrationMessage) {
Intent notificationIntent = new Intent(context, RegisterActivity.class);
notificationIntent.putExtra("gcmIntentServiceMessage", true);
notificationIntent.putExtra("registrationMessage", isRegistrationMessage);
notificationIntent.putExtra("error", isError);
notificationIntent.putExtra("message", message);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
NotificationManager notificationManager =
(NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = neNotification(R.drawable.ic_launcher,"Title",System.currentTimeMillis());
PendingIntent intents = PendingIntent.getActivity(context, 0, notificationIntent, Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
notification.setLatestEventInfo(context , context.getString(R.string.app_name), tickerText , intents );
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(100, notification);
}
public class AppBroadcastReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if(intent.getAction() == "AppReceiver") {
// this intent is gcminit intent and you can get data from this Intent
}
}
}
// in menifest file
<receiver android:name="AppBroadcastReceiver" >
<intent-filter>
<action android:name="AppReceiver" >
</action>
</intent-filter>
</receiver>
If the activity is in background then the intent is receive in onNewIntent which will be called before onResume, thus you have to override onNewIntent
#Override
protected void onNewIntent(Intent intent)
{
super.onNewIntent(intent);
boolean b = intent.getBooleanExtra("gcmIntentServiceMessage", false);
........
}
Issue almost solved... had to add:
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
There is only one problem left: onNewIntent() is still not fired when activity is brought to front by a GCM message. I put the code in onCreate() instead.