i set two different alarms that should make 2 notifications
8:34:0 pm create notification 1 with title and msg..
8:34:10 pm create notification 2 with title and msg...
the problem is they both appear together at 8:34:00 pm
(at the first alarm time (both))!!!
what i did:-
1- i made a broadcast class with notification manager to build notification
2- main activity created alarmManager and calendar instance to set time for alarm.
public class MainActivity extends AppCompatActivity {
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Creating alarm method(requestcode,hours,min,seconds)
setAlarmo(1,20,34,0);
setAlarmo(2,20,34,10);
}
// the Alarm Method
public void setAlarmo(int reqcode, int hour,int minute,int second){
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY,hour);
calendar.set(Calendar.MINUTE,minute);
calendar.set(Calendar.SECOND,second);
long timeinMillis = calendar.getTimeInMillis();
Intent intent = new Intent(getApplicationContext(),AlertRec.class);
intent.putExtra("reqcode",reqcode);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(),reqcode,intent,PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.set(alarmManager.RTC_WAKEUP,timeinMillis,pendingIntent);
}
}
#
// AlertClass receiver extending broadcastReceiver
public class AlertRec extends BroadcastReceiver {
#Override
public void onReceive( final Context context, Intent intent) {
// Creating receiveAlarm method(requestCode,Context,intent,title,text for notification)
//receiving first Alarm from MainActivity.Class
recAlarmo(1, context,intent,"title 1","im msg 1");
//receiving Second Alarm from MainActivity.Class
recAlarmo(2,context,intent,"title 2","im msg 2");
}
// receiving Alarms Method and Creating Notifications
public void recAlarmo(int reqcode , Context context,Intent intent,String title,String msg){
intent = new Intent(context,MainActivity.class);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
PendingIntent pendingIntent = PendingIntent.getActivity(context.getApplicationContext(),reqcode,intent,PendingIntent.FLAG_ONE_SHOT);
builder.setContentTitle(title);
builder.setSmallIcon(android.R.drawable.star_on);
builder.setContentText(msg);
builder.setAutoCancel(true);
builder.setContentIntent(pendingIntent);
builder.setDefaults(NotificationCompat.DEFAULT_SOUND);
NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(reqcode,builder.build());
}
}
#
<uses-permission android:name="android.permission.SET_ALARM"></uses-permission>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".AlertRec"></receiver>
</application>
i solved it !
------------------------------
in MainActivity
1-create a method that takes int number
and inside the method make a pending intent and within the intent of the pending intent
pass the int number as intent.putExtra("id",number);
public void Method(int id ,int hour , int minute, int seconds){
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY,hour);
calendar.set(Calendar.MINUTE,minute);
calendar.set(Calendar.SECOND,second);
Intent alertIntent = new Intent(getApplicationContext(), AlertRec.class);
alertIntent.putExtra("id",id);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(),PendingIntent.getBroadcast(getApplicationContext(),id,alertIntent,PendingIntent.FLAG_UPDATE_CURRENT));
}
----------------------------------------------------
2- at the Receiver class
//override the OnReceive method
onReceive(Context context,Intent intent ){
int Checker =intent.getExtras.getInt("id");
if(Checker == 1 ) {
// do anything you want for the intent of the pending intent at MainActivity that have int id = 1;
//your method here
}else if(Checker == 2) {
// do anything you want for the intent of the pending intent at MainActivity that have int id = 2;
// your method here
}else{
}
}
Related
It's supposed to be a simple to do list app. You can set a list Item with a task and time. It should send you a notification at the given time.
Everything works fine when the app is running but when I close it I don't get notifications. I tried on API 23 and API R. I was looking at other posts but I couldn't find any solution.
Receiver class:
public class AlertReceiver extends BroadcastReceiver {
NotificationManagerCompat notificationManager;
#Override
public void onReceive(Context context, Intent intent) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
boolean is24HourFormat = android.text.format.DateFormat.is24HourFormat(context);
CharSequence setTime;
if (is24HourFormat) {
setTime = DateFormat.format("HH:mm", calendar);
} else {
setTime = DateFormat.format("hh:mm a", calendar);
}
String currentTime = setTime.toString();
DataBaseHelper dataBaseHelper = new DataBaseHelper(context);
Item itemForNotificationText = dataBaseHelper.GetNotificationContent(currentTime);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
Notification notification = new NotificationCompat.Builder(context,CHANNEL_1_ID)
.setSmallIcon(R.drawable.ic_baseline_notifications_active_24)
.setContentTitle(itemForNotificationText.getTask())
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setContentText(itemForNotificationText.getTime())
.build();
notificationManager.notify(dataBaseHelper.GetID(),notification);
}
}
I tired using setExactAndAllowWhileIdle but still doesn't work.
Start alarm:
public void startAlarm (Calendar c){
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlertReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, item.getNotification_id(), intent,0);
if (c.before(Calendar.getInstance())) {
c.add(Calendar.DATE, 1);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP,c.getTimeInMillis(),pendingIntent);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,c.getTimeInMillis(),pendingIntent);
}
}
Manifest file:
<application
android:name=".App"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".InsertActivity"></activity>
<activity
android:name=".ToDoList"
android:parentActivityName=".MainActivity" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".AlertReceiver"/>
</application>
APP Class(Notification channel is created here):
public class App extends Application {
public static final String CHANNEL_1_ID = "Channel 1";
#Override
public void onCreate() {
super.onCreate();
CreateNotificationChannels();
}
private void CreateNotificationChannels () {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel1 = new NotificationChannel(
CHANNEL_1_ID,
"Channel 1",
NotificationManager.IMPORTANCE_HIGH
);
channel1.setDescription("Notifies you when an event has started.");
channel1.enableVibration(true);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel1);
}
}
}
I'm working on app which test state on server every 15 min and push notification , i used Alarm Manager , broadcast receiver & Intent Service .
every thing worked fine and i get this state from server perfectly when app is running or in background , until i removed it from recent apps, every thing stops and can't get that state from server.
I searched ... and get nothing , but my friend tell me that I must register my broadcast receiver in on create of class extend from application.
I don't know how to do this .. so I need help please
Main Activity Class
public class MainActivity extends AppCompatActivity {
static TextView TvText;
Button Btn11, Btn22;
AlarmManager alarm;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
alarm = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
TvText = (TextView) findViewById(R.id.tv_Text);
Btn11 = (Button) findViewById(R.id.btn_11);
Btn22 = (Button) findViewById(R.id.btn_22);
Btn22.setEnabled(false);
}
public void Btn11OC(View view) {
scheduleAlarm();
Btn11.setEnabled(false);
Btn22.setEnabled(true);
}
public void Btn22OC(View view) {
if (alarm!= null) {
cancelAlarm();
}
Btn11.setEnabled(true);
Btn22.setEnabled(false);
}
// Setup a recurring alarm every half hour
public void scheduleAlarm() {
// Construct an intent that will execute the AlarmReceiver
Intent intent = new Intent(getApplicationContext(), broadtest.class);
intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
// Create a PendingIntent to be triggered when the alarm goes off
final PendingIntent pIntent = PendingIntent.getBroadcast(this, broadtest.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Setup periodic alarm every 5 seconds
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(),
900000L, pIntent);
}
public void cancelAlarm() {
Intent intent = new Intent(getApplicationContext(), broadtest.class);
intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
final PendingIntent pIntent = PendingIntent.getBroadcast(this, broadtest.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarm.cancel(pIntent);
}
}
Broad Cast Receiver
public class broadtest extends WakefulBroadcastReceiver {
public static final int REQUEST_CODE = 12345;
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, MyService.class);
context.startService(i);
}
}
AppController Class
public class AppController extends Application {
#Override
public void onCreate() {
super.onCreate();
}
}
MyService class
public class MyService extends IntentService {
static int NOTIFICATION_ID = 0;
public MyService() {
super("MyService");
}
#Override
protected void onHandleIntent(Intent intent) {
String url = "http://test.com/testts.php";
// Tag used to cancel the request
String tag_string_req = "string_req";
StringRequest strReq = new StringRequest(Request.Method.GET,
url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d("Volley Log", response);
Toast.makeText(MyService.this, response, Toast.LENGTH_SHORT).show();
if (response.equals("0")){
sendNotification("Titel Test 1111", "Body Test 1111");
}else if (response.equals("1")){
sendNotification("Titel Test 2222", "Body Test 2222");
}else {
sendNotification("Titel Test 3333", "Body Test 3333");
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MyService.this, error.toString(), Toast.LENGTH_SHORT).show();
VolleyLog.d("Volley Log", "Error: " + error.getMessage());
}
});
// Adding request to request queue
int socketTimeout = 30000;//30 seconds - change to what you want
RetryPolicy policy = new DefaultRetryPolicy(socketTimeout,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
strReq.setRetryPolicy(policy);
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
// Setup periodic alarm every 5 seconds
}
private void sendNotification(String title, String messageBody) {
long[] pattern = {500,500,500,500,500,500,500,500,500};
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(alarmSound)
.setLights(Color.BLUE, 500, 500)
.setVibrate(pattern);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (NOTIFICATION_ID > 1073741824) {
NOTIFICATION_ID = 0;
}
notificationManager.notify(NOTIFICATION_ID++, notificationBuilder.build());
}
}
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.gih.testmass">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:name=".AppController"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".broadtest"
android:process=":remote">
</receiver>
<service
android:name=".MyService"
android:exported="false">
</service>
</application>
You need to start the service as a foreground service. When you clear app from recents it kills the service
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.ic_notification)
.setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(),
R.mipmap.ic_launcher))
.setContentTitle("WhatsApp Reminder Service.")
.setContentText("Touch to configure.");
Intent startIntent = new Intent(getApplicationContext(), MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 965778, startIntent, 0);
builder.setContentIntent(pendingIntent);
startForeground(965778, builder.build());
return START_REDELIVER_INTENT;
}
It is necessary to build a notification when you use foreground service.
Hope it helps.
I see you have used IntentService
see answer to this question
Using startForeground() with an Intent Service
To run a process on a device when users are not particularly interacting with your application.
The steps will involve:
1.Updating your android manifest xml
2.Setting up broadcast receivers to listen to relevant events
3.Set up a background service for context when your application isn’t running
Android menifest.xml
<?xml version="1.0" encoding="utf-8"?>
<uses-permission ... />
<application
android:name=".MyApplication"
... >
<receiver android:name=".receivers.PeriodicTaskReceiver">
<intent-filter>
<action android:name="com.example.app.PERIODIC_TASK_HEART_BEAT" />
</intent-filter>
</receiver>
<service android:name=".services.BackgroundService" />
...
</application>
Now for the Broadcast receiver
public class PeriodicTaskReceiver extends BroadcastReceiver {
private static final String TAG = "PeriodicTaskReceiver";
private static final String INTENT_ACTION = "com.example.app.PERIODIC_TASK_HEART_BEAT";
#Override
public void onReceive(Context context, Intent intent) {
if (!Strings.isNullOrEmpty(intent.getAction())) {
MyApplication myApplication = (MyApplication) context.getApplicationContext();
SharedPreferences sharedPreferences = myApplication.getSharedPreferences();
if (intent.getAction().equals("android.intent.action.BATTERY_LOW")) {
sharedPreferences.edit().putBoolean(Constants.BACKGROUND_SERVICE_BATTERY_CONTROL, false).apply();
stopPeriodicTaskHeartBeat(context);
} else if (intent.getAction().equals("android.intent.action.BATTERY_OKAY")) {
sharedPreferences.edit().putBoolean(Constants.BACKGROUND_SERVICE_BATTERY_CONTROL, true).apply();
restartPeriodicTaskHeartBeat(context, myApplication);
} else if (intent.getAction().equals(INTENT_ACTION)) {
doPeriodicTask(context, myApplication);
}
}
}
private void doPeriodicTask(Context context, MyApplication myApplication) {
// Periodic task(s) go here ...
}
public void restartPeriodicTaskHeartBeat(Context context, MyApplication myApplication) {
SharedPreferences sharedPreferences = myApplication.getSharedPreferences();
boolean isBatteryOk = sharedPreferences.getBoolean(Constants.BACKGROUND_SERVICE_BATTERY_CONTROL, true);
Intent alarmIntent = new Intent(context, PeriodicTaskReceiver.class);
boolean isAlarmUp = PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_NO_CREATE) != null;
if (isBatteryOk && !isAlarmUp) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmIntent.setAction(INTENT_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), AlarmManager.INTERVAL_FIFTEEN_MINUTES, pendingIntent);
}
}
public void stopPeriodicTaskHeartBeat(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent alarmIntent = new Intent(context, PeriodicTaskReceiver.class);
alarmIntent.setAction(INTENT_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);
alarmManager.cancel(pendingIntent);
}
}
here com.example.app.PERIODIC_TASK_HEART_BEAT is application’s own broadcast, created and sent from our restartPeriodicTaskHeartBeat method.
your Alarmmanager should have this line
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(), AlarmManager.INTERVAL_FIFTEEN_MINUTES, pendingIntent);
Now for your background service class:
public class BackgroundService extends Service {
private static final String TAG = "BackgroundService";
PeriodicTaskReceiver mPeriodicTaskReceiver = new PeriodicTaskReceiver();
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
MyApplication myApplication = (MyApplication) getApplicationContext();
SharedPreferences sharedPreferences = myApplication.getSharedPreferences();
IntentFilter batteryStatusIntentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatusIntent = registerReceiver(null, batteryStatusIntentFilter);
if (batteryStatusIntent != null) {
int level = batteryStatusIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryStatusIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
float batteryPercentage = level / (float) scale;
float lowBatteryPercentageLevel = 0.14f;
try {
int lowBatteryLevel = Resources.getSystem().getInteger(Resources.getSystem().getIdentifier("config_lowBatteryWarningLevel", "integer", "android"));
lowBatteryPercentageLevel = lowBatteryLevel / (float) scale;
} catch (Resources.NotFoundException e) {
Log.e(TAG, "Missing low battery threshold resource");
}
sharedPreferences.edit().putBoolean(Constants.BACKGROUND_SERVICE_BATTERY_CONTROL, batteryPercentage >= lowBatteryPercentageLevel).apply();
} else {
sharedPreferences.edit().putBoolean(Constants.BACKGROUND_SERVICE_BATTERY_CONTROL, true).apply();
}
mPeriodicTaskReceiver.restartPeriodicTaskHeartBeat(BackgroundService.this);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
startSelf();
}
}
Here the Backgroundservice tries to find the device’s low battery threshold and set our battery control flag appropriately before it attempts to restart the Broadcast receiver.
And START_STICKY will try to re-create your service after it is killed and call onStartCommand() again with a null intent.
Finally for your Application class start the Background service:
public class MyApplication extends Application {
private static final String TAG = "MyApplication";
#Override
public void onCreate() {
super.onCreate();
// Initialize the singletons so their instances
// are bound to the application process.
...
Intent startServiceIntent = new Intent(context, BackgroundService.class);
startService(startServiceIntent);
}
}
For detail implementation see this:https://technology.jana.com/2014/10/28/periodic-background-tasks-in-android/
be sure to make you service like this in your Mainifest
<service
android:name=".service.youservice"
android:exported="true"
android:process=":ServiceProcess" />
then your service will run on other process named ServiceProcess
if you want make your service never die :
onStartCommand() return START_STICKY
onDestroy() -> call startself
if nothing works use startForeground() service..
I have a general question about setting up a daily data check from my app (giving a notification when some event occurs).
My current approach is:
From the app (onCreate) I start a service
From the service I set an alarm using AlarmManager after checking if there already is a matching PendingIntent (in which case I don't
need to set a new alarm)
The service checks the data from SharedPreferences and eventually shows a notification
For testing purposes I set the alarm to +1 minute ... but it didn't work that way. Maybe I'm doing something wrong conceptionally?
Some code
AndroidManifest.xml
<application
<activity
android:name=".OverviewActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar"
android:configChanges="orientation"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="xxxxx.CheckDaysMonths" >
</service>
</application>
Service CheckDaysMonths
public class CheckDaysMonths extends Service {
private static int ALARM_ID = 131313;
private static String DECLARED_ACTION = "xxxxx.CheckDaysMonths";
#Override
public void onCreate() {
super.onCreate();
PendingIntent alarmIntent = AlarmHelper.getPendingIntentFromAlarm(this, ALARM_ID, DECLARED_ACTION);
if(alarmIntent == null) {
if(someConditionIsMet)
sendNotification(" my notification text ");
// Set an alarm for the next time this service should run:
setAlarm();
}
stopSelf();
}
public void setAlarm() {
AlarmHelper.setAlarm(this, ALARM_ID, DECLARED_ACTION, 8);
}
public void sendNotification(String notifyText) {
Intent mainIntent = new Intent(this, OverviewActivity.class);
#SuppressWarnings("deprecation")
Notification noti = new Notification.Builder(this)
.setAutoCancel(true)
.setContentIntent(PendingIntent.getActivity(this, 131314, mainIntent,
PendingIntent.FLAG_UPDATE_CURRENT))
.setContentTitle("Gratuliere!")
.setContentText("Du bist seit " + notifyText + " rauchfrei!")
.setDefaults(Notification.DEFAULT_ALL)
.setSmallIcon(R.mipmap.ic_launcher)
.setTicker("Du bist seit " + notifyText + " rauchfrei!")
.setWhen(System.currentTimeMillis())
.getNotification();
NotificationManager notificationManager
= (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(131315, noti);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Inside the main activity (OverviewActivity.java)
EDIT: Changed service call from implicit to explicit
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_overview);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
startService(new Intent(this, CheckDaysMonths.class));
// additional stuff happening on the activity of my app goes here:
...
}
AlarmHelper.java
public class AlarmHelper {
public static PendingIntent getPendingIntentFromAlarm(Context context, int alarmId, String declaredAction) {
return (PendingIntent.getService(context, alarmId,
new Intent(declaredAction),
PendingIntent.FLAG_NO_CREATE));
}
public static void setAlarm(Context context, int alarmId, String declaredAction, int hourOfDay) {
Intent serviceIntent = new Intent(declaredAction);
PendingIntent pi = PendingIntent.getService(context, alarmId, serviceIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
// How long until tomorrow to its hourOfDay?
//DateTime tomorrow = (new DateTime()).plusDays(1);
//DateTime tomorrowAtHourOfDay = new DateTime(tomorrow.getYear(), tomorrow.getMonthOfYear(), tomorrow.getDayOfMonth(), hourOfDay, 0);
DateTime tomorrowAtHourOfDay = (new DateTime()).plusHours(3);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, tomorrowAtHourOfDay.getMillis(), pi);
}
}
I fixed it by introducing another "middle tier" service
So now I have
The app GUI starting service 1
Service 1 will check if there is already an alarm with the correct signature running. If not, it will start an alarm
The alarm will fire at 2am and start service 2
Service 2 will check the data (SharedPreferences) and eventually send a notification. Then it will start the alarm again
A BroadcastReceiver for BOOT starts Service 2
This works quite well
I'm developing an android app, and part of it involves a notification that reminds the user to do something. This notification at a specified time and repeats every 12 hours. I'm using AlarmManager to schedule the alarm and I've also included the code to start my Alarm Service when the device boots. Here are my java classes:
MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences preferences = PreferenceManager
.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = preferences.edit();
int i = preferences.getInt("numberoflaunches", 1);
if (i < 2) {
alarmMethod();
i++;
editor.putInt("numberoflaunches", i);
editor.commit();
}
}
private void alarmMethod() {
Intent intent = new Intent(this, AlarmService.class);
this.startService(intent);
Toast.makeText(MainActivity.this, "Alarm Set", Toast.LENGTH_SHORT).show();
}
}
AlarmService.java
public class AlarmService extends Service {
//used for register alarm manager
PendingIntent pendingIntent;
//used to store running alarm manager instance
AlarmManager alarmMgr;
//Callback function for alarm manager event
BroadcastReceiver mReceiver;
private static final String TAG = "MyService";
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
//Register AlarmManager Broadcast receive.
RegisterAlarmBroadcast();
}
#Override
public void onStart(Intent intent, int startid) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MINUTE, 30);
calendar.set(Calendar.HOUR_OF_DAY, 6);
alarmMgr.cancel(pendingIntent);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), 1000 * 60 * 60 * 12, pendingIntent);
}
private void showNotification() {
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("app_name")
.setContentText("something")
.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT))
.setSound(soundUri)
.setSmallIcon(R.drawable.notification_icon)
.setAutoCancel(true)
.setOnlyAlertOnce(true)
.build();
NotificationManagerCompat.from(this).notify(0, notification);
}
private void RegisterAlarmBroadcast() {
Log.i("RegisterAlarmBroadcast", "Register Intent.RegisterAlarmBroadcast");
//This is the call back function(BroadcastReceiver) which will be called when your alarm time is reached.
mReceiver = new BroadcastReceiver() {
private static final String TAG = "Alarm Example Receiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "BroadcastReceiver::OnReceive() >>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
showNotification();
}
};
//Register the alarm broadcast here
registerReceiver(mReceiver, new IntentFilter("com.example.application.myNotification"));
pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent("com.example.application.myNotification"), 0);
alarmMgr = (AlarmManager) (this.getSystemService(Context.ALARM_SERVICE));
}
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
}
}
autostart.java
public class autostart extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent arg1)
{
Intent intent = new Intent(arg0,AlarmService.class);
arg0.startService(intent);
Log.i("Autostart", "started");
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.application" >
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".autostart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name=".AlarmService"
android:enabled="true" />
</application>
However I must have done something wrong as it is not working properly. My problems are:
1. When I exit the app, the notification for some reason goes off, whatever the time is.
2. When I reboot, the notification goes off, whatever the time is.
I don't know if these problems are in any way related, maybe I have a piece of code that's messing everything up. But either way I would really appreciate any sort of help I can get. Thanks in advance.
The repeating interval should be 24 hours (1000 * 60 * 60 * 24), not 12 hours.
You are individually setting the time to 6 AM. So you can remove the line calendar.setTimeInMillis(System.currentTimeMillis());
EDIT:
I have made some of modifications to your code and finally got it working.
You problem was that you set an alarm for 6:00 AM. But you are setting this alarm at a time after 6:00 AM (say 9:00 AM). That is, you are setting an alarm for a past time. So it will go off immediately.
I made a work around for this. If the time you need to set alarm is past, set the alarm to trigger on the next day.
This is my modified code.
MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences preferences = PreferenceManager
.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = preferences.edit();
int i = preferences.getInt("numberoflaunches", 1);
if (i < 2) {
alarmMethod();
i++;
editor.putInt("numberoflaunches", i);
editor.commit();
}
}
private void alarmMethod() {
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
new Intent("com.example.application.myNotification"),
PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmMgr = (AlarmManager) (this
.getSystemService(Context.ALARM_SERVICE));
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MINUTE, 30);
calendar.set(Calendar.HOUR_OF_DAY, 6);
long mills = calendar.getTimeInMillis();
if (mills <= System.currentTimeMillis()) {
Calendar c1 = calendar;
c1.add(Calendar.DAY_OF_MONTH, 1);
mills = c1.getTimeInMillis();
} else {
mills = calendar.getTimeInMillis();
}
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, mills,
1000 * 60 * 60 * 24, pendingIntent);
Toast.makeText(MainActivity.this, "Alarm Set", Toast.LENGTH_SHORT)
.show();
}
}
Autostart.java
public class Autostart extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent arg1)
{
PendingIntent pendingIntent = PendingIntent.getBroadcast(arg0, 0, new Intent("com.example.application.myNotification"), 0);
AlarmManager alarmMgr = (AlarmManager) (arg0.getSystemService(Context.ALARM_SERVICE));
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MINUTE, 30);
calendar.set(Calendar.HOUR_OF_DAY, 6);
long mills = calendar.getTimeInMillis();
if (mills <= System.currentTimeMillis()) {
Calendar c1 = calendar;
c1.add(Calendar.DAY_OF_MONTH, 1);
mills = c1.getTimeInMillis();
} else {
mills = calendar.getTimeInMillis();
}
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, mills, 1000 * 60 * 60 * 24, pendingIntent);
Log.i("Autostart", "started");
}
}
Alarmer.java
public class Alarmer extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
showNotification(context);
}
private void showNotification(Context context) {
Random r = new Random();
int r0 = r.nextInt();
Uri soundUri = RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Notification notification = new NotificationCompat.Builder(context)
.setContentTitle("app_name")
.setContentText("something" + r0)
.setContentIntent(
PendingIntent.getActivity(context, 0, new Intent(context,
MainActivity.class),
PendingIntent.FLAG_UPDATE_CURRENT))
.setSound(soundUri).setSmallIcon(R.drawable.ic_launcher)
.setAutoCancel(true).setOnlyAlertOnce(true).build();
// NotificationManagerCompat.from(this).notify(0, notification);
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(r0, notification);
}
}
AndroiManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.alarmtest"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".autostart" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".Alarmer" android:enabled="true">
<intent-filter>
<action android:name="com.example.application.myNotification" />
</intent-filter>
</receiver>
<service
android:name=".AlarmService"
android:enabled="true" />
</application>
</manifest>
Compare it with your code and make changes.
What I am trying to do here is to raised a notification after a certain time by using BroadcastReceiver.With the following set of code i am able to achieve that also. But I want even the application is closed it will raised the notification.
MainActivity.java
public class MainActivity extends Activity {
IntentFilter ii;
TimeReciever tr;
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ii=new IntentFilter("android.intent.action.TIME_TICK");
tr=new TimeReciever();
registerReceiver(tr, ii);
}
}
=================================
TimeReciever.java
public class TimeReciever extends BroadcastReceiver{
int a=0;
public void onReceive(Context ctx, Intent in) {
System.out.println("On reciever");
a+=a;
a++;
System.out.println("value of a="+a);
if(a==31){
Toast.makeText(ctx,"Reciver Executed ", 40).show();
showNotification(ctx);
}
}
private void showNotification(Context context) {
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Log Reminder")
.setContentText("It's time to log the Breakfast !");
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(context, MainActivity.class);
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(MainActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
mBuilder.setContentIntent(resultPendingIntent);
mBuilder.setDefaults(Notification.DEFAULT_SOUND);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(1, mBuilder.build());
a=0;
}
}
===============================
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.notificationbybroadcastre"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name="com.example.notificationbybroadcastre.TimeReciever">
<intent-filter>
<action android:name="android.intent.action.TIME_TICK"/>
</intent-filter>
</receiver>
<activity
android:name="com.example.notificationbybroadcastre.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Here The Answer.I have done It Through AlaramManager.
Main Activity
===============
public class MainActivity extends Activity
{
private PendingIntent pendingIntent;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent myIntent = new Intent(MainActivity.this, MyReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent,0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 30);
// setRepeating() lets you specify a precise custom interval--in this case,
// 20 minutes.
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000 * 60 * 480, pendingIntent);
} //end onCreate
}
================================================================
MyAlarmService.java
================================
public class MyAlarmService extends Service
{
private NotificationManager mManager;
#Override
public IBinder onBind(Intent arg0)
{
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate()
{
// TODO Auto-generated method stub
super.onCreate();
}
#SuppressWarnings("static-access")
#Override
public void onStart(Intent intent, int startId)
{
showNotification(this);
}
private void showNotification(Context context) {
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Meal Log Reminder")
.setContentText("It's time to log Your Meal!");
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(context, MainActivity.class);
// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(MainActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
mBuilder.setContentIntent(resultPendingIntent);
mBuilder.setDefaults(Notification.DEFAULT_ALL);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(1, mBuilder.build());
}
#Override
public void onDestroy()
{
// TODO Auto-generated method stub
super.onDestroy();
}
}
===================================================
MyReceiver.java
=========================
public class MyReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Intent service1 = new Intent(context, MyAlarmService.class);
context.startService(service1);
}
}