Reputation: 21
My app should launch a notification in predefined times. The app works well in the emulator.
When I test it in my Note 3 ( work in Lollipop 5.0 ), the notification is not showing at all..!!.
I don't know what the problem is, because its work fine in the emulator.
Here is my method to build and fire a notification:
private static String customTime = "13:08:00"; // ( Temp ) for test app
private final static String[] NOTIY_TIMES = {customTime,"10:00:00","11:00:00","12:00:00","13:00:00","14:00:00","15:00:00","16:00:00","17:00:00","18:00:00","19:00:00","20:00:00","21:00:00","22:00:00"};
// This Method will build , fire notification then increase the notify counter;
public static void showNotification( Context context) {
// Notification Builder
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setColor(context.getResources().getColor(R.color.colorPrimary))
.setSmallIcon(R.drawable.ic_water_cup)
.setLargeIcon(largeIcon(context))
.setStyle(new NotificationCompat.BigTextStyle().bigText("Its Nice Time To Drink Cup Of Water Now.."))
.setContentTitle("Drinking Water = Healthey Life")
.setContentText("Its Nice Time To Drink Cup Of Water Now..")
.setContentIntent(openAppWhenClick(context))
.setDefaults(NotificationCompat.DEFAULT_SOUND | NotificationCompat.DEFAULT_VIBRATE)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
.addAction(acceptToDrinkAction(context))
.addAction(cancelNotificationAction(context));
// Fire Notification
NotificationManager notificationManager = (NotificationManager)context.getSystemService(context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.notify(NOTIFY_ID , mBuilder.build());
}
And here is my method to fire notification in predefined times above :
// This Method lunch Notification in certain time of the day public static void fireNotificationOnCertainTime(final Context context){
// Get Current Dynamic Time uses Handler
final Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss", Locale.US);
String timeNow = sdf.format(new Date());
handler.postDelayed(this ,1000);
// Fire notification in this specific times
if (Arrays.asList(NOTIY_TIMES).contains(timeNow)) {
showNotification(context);
}
}
},10);
}
Here my manifest file :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.islam.waterdrinkreminder">
<uses-permission android:name="android.permission.VIBRATE"/>
<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"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".Services.Reciver"/>
<service android:name=".Services.WaterReminderJopDispatcher"
android:exported="false">
<intent-filter>
<action
android:name="com.firebase.jobdispatcher.ACTION_EXECUTE">
</action>
</intent-filter>
</service>
</application>
</manifest>
Edit :
I think i found what cause the problem but still not find solve for it, problem in the Pattern of Time in my code i use pattern "HH:mm:ss" this pattern work in emulator but my real phone not recognize it..!! i try to use Pattern "HH:mm" its work on both but keep sending notification multiple times (sending notification for hole minute cause i remove seconds) hope that be helpfully to find solution ..thanks guys.
Upvotes: 1
Views: 727
Reputation: 8038
I'm assuming this is happening because your emulator is running Android O (which changes how notifications are managed). For in-depth coverage of how to add support for Android O, I'd suggest checking out this documentation.
But the short of it is that you need to add a channel for all of your notifications now. Below is the code excerpt from the documentation:
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// The id of the channel.
String id = "my_channel_01";
// The user-visible name of the channel.
CharSequence name = getString(R.string.channel_name);
// The user-visible description of the channel.
String description = getString(R.string.channel_description);
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel mChannel = new NotificationChannel(id, name, importance);
// Configure the notification channel.
mChannel.setDescription(description);
mChannel.enableLights(true);
// Sets the notification light color for notifications posted to this
// channel, if the device supports this feature.
mChannel.setLightColor(Color.RED);
mChannel.enableVibration(true);
mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
mNotificationManager.createNotificationChannel(mChannel);
[EDIT]
I see that you mentioned the SimpleDateFormat isn't working and I'm actually not sure why that is. But on a separate note, I wouldn't recommend timing your notifications as you are (with an array of valid times and a handler that delays ever 10ms).
In Android you have access to the AlarmManager
. The documentation for how to implement a repeating alarm can be found here.
With the AlarmManager
you can have alarms go off based on elapsed time, or you can have the alarm wake up at very specific times. The links above should show you how that works. Below is a little code sample showing one possible solution that would have an alarm that triggers a service ever hour.
alarmMgr.setInexactRepeating(
// Wake the device based on elapsed time
AlarmManager.ELAPSED_REALTIME_WAKEUP,
// Trigger 30 minutes after this call
SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR,
// Keep triggering every hour
AlarmManager.INTERVAL_HOUR,
// The intent to trigger - likely waking some Service to do a job
alarmIntent);
Other uses of the AlarmManager
let you set the specific time to start. For more options of Android components used for scheduling, you can check out this page of the documentation.
If you really want to continue using the Handler
, you could have your array of times actually be a map of times which correspond to a boolean value which represents if a notification has been sent yet. This map can then get reset at the end of the day (or once the last time has been hit). Or there are a ton of other ways to optimize the Handler
/Array
approach - that's just one idea that requires minimal changes. Regardless, I suggest using an AlarmManager
since it'll be less resource intensive and more exact in the long run.
Upvotes: 1