I am developing an android app and I want to send "We Miss You" notification to user if he/she is inactive for more than 3 days.
This means if the user does not open our app for 3 days I want to send them a notification of "We Miss you"
Like Deer Hunter and Temple Run sends
Thank you :)
You want to set an alarm that starts a short-running service once per day. All that service does is to check something like a shared preference for the last-used-time. If that time is more than 3 days old, then the service sends a notification. Either way, the service then exits.
Alternatively, your app could submit an alarm, each time it runs, that is defined to fire in 3 days and defined to replace any pre-existing alarm with the same ID. That alarm would be defined to open a short-running service that sends a notification.
Here's some sample code that demonstrates the second approach. As written, it only updates the run time upon start-up. If your app is long-running, you'll want to call recordRunTime() periodically. The deprecated method getNotification() could be replaced with build() if the Notification.Builder object was replaced with a NotificationCompat.Builder. You can use the commented out line for delay to test with a shorter delay time.
MainActivity.java:
package com.example.comeback;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
public class MainActivity extends Activity {
private final static String TAG = "MainActivity";
public final static String PREFS = "PrefsFile";
private SharedPreferences settings = null;
private SharedPreferences.Editor editor = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
// Save time of run:
settings = getSharedPreferences(PREFS, MODE_PRIVATE);
editor = settings.edit();
// First time running app?
if (!settings.contains("lastRun"))
enableNotification(null);
else
recordRunTime();
Log.v(TAG, "Starting CheckRecentRun service...");
startService(new Intent(this, CheckRecentRun.class));
}
public void recordRunTime() {
editor.putLong("lastRun", System.currentTimeMillis());
editor.commit();
}
public void enableNotification(View v) {
editor.putLong("lastRun", System.currentTimeMillis());
editor.putBoolean("enabled", true);
editor.commit();
Log.v(TAG, "Notifications enabled");
}
public void disableNotification(View v) {
editor.putBoolean("enabled", false);
editor.commit();
Log.v(TAG, "Notifications disabled");
}
}
CheckRecentRun.java:
package com.example.comeback;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.IBinder;
import android.util.Log;
public class CheckRecentRun extends Service {
private final static String TAG = "CheckRecentPlay";
private static Long MILLISECS_PER_DAY = 86400000L;
private static Long MILLISECS_PER_MIN = 60000L;
// private static long delay = MILLISECS_PER_MIN * 3; // 3 minutes (for testing)
private static long delay = MILLISECS_PER_DAY * 3; // 3 days
#Override
public void onCreate() {
super.onCreate();
Log.v(TAG, "Service started");
SharedPreferences settings = getSharedPreferences(MainActivity.PREFS, MODE_PRIVATE);
// Are notifications enabled?
if (settings.getBoolean("enabled", true)) {
// Is it time for a notification?
if (settings.getLong("lastRun", Long.MAX_VALUE) < System.currentTimeMillis() - delay)
sendNotification();
} else {
Log.i(TAG, "Notifications are disabled");
}
// Set an alarm for the next time this service should run:
setAlarm();
Log.v(TAG, "Service stopped");
stopSelf();
}
public void setAlarm() {
Intent serviceIntent = new Intent(this, CheckRecentRun.class);
PendingIntent pi = PendingIntent.getService(this, 131313, serviceIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delay, pi);
Log.v(TAG, "Alarm set");
}
public void sendNotification() {
Intent mainIntent = new Intent(this, MainActivity.class);
#SuppressWarnings("deprecation")
Notification noti = new Notification.Builder(this)
.setAutoCancel(true)
.setContentIntent(PendingIntent.getActivity(this, 131314, mainIntent,
PendingIntent.FLAG_UPDATE_CURRENT))
.setContentTitle("We Miss You!")
.setContentText("Please play our game again soon.")
.setDefaults(Notification.DEFAULT_ALL)
.setSmallIcon(R.drawable.ic_launcher)
.setTicker("We Miss You! Please come back and play our game again soon.")
.setWhen(System.currentTimeMillis())
.getNotification();
NotificationManager notificationManager
= (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(131315, noti);
Log.v(TAG, "Notification sent");
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
main_activity_layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="enableNotification"
android:text="#string/enable" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="disableNotification"
android:text="#string/disable" />
</LinearLayout>
strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Come Back</string>
<string name="enable">Enable Notifications</string>
<string name="disable">Disable Notifications</string>
</resources>
AndroidManifest.com:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.comeback"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.comeback.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>
<service
android:name="com.example.comeback.CheckRecentRun" >
</service>
</application>
</manifest>
You could have something like:
When a user opens the app, you record it on a database on your website and have a cron job (or some other equivalent) to run everyday at say 3pm time and if the users last open date is over 3 days ago you send the notification.
OR
When a user opens the app, you record it on a sqlite database on your app and set an alarm manager for 3 days time. Each time the app is open the alarm is reset. After the 3 days is up you create a notification.
I tried to make this feature with broadcast. Here is the implementation:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapplication">
<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/Theme.MyApplication">
<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=".MyReceiver"
android:enabled="true"
android:exported="false" />
</application>
</manifest>
MainActivity.kt
package com.example.myapplication
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
private var sharedPreferences: SharedPreferences? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sharedPreferences = applicationContext.getSharedPreferences(MAIN_ACTIVITY_PREFS, Context.MODE_PRIVATE)
recordRunTime()
Log.i("MainActivity", "Starting com.example.myapplication.MyReceiver broadcast...")
sendBroadcast(Intent(this, MyReceiver::class.java))
}
fun recordRunTime() {
val editor = sharedPreferences?.edit()
editor?.putLong("lastRun", System.currentTimeMillis())
editor?.apply()
}
}
MyReceiver.kt
package com.example.myapplication
import android.app.*
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
class MyReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val settings = context.applicationContext.getSharedPreferences(MAIN_ACTIVITY_PREFS, Service.MODE_PRIVATE)
// Are notifications enabled?
if (settings.getBoolean(ENABLED, true)) {
// Is it time for a notification?
val channel = createChannel()
Log.i(TAG, "onReceive: ")
makeStatusNotification("Notification Message", context, channel)
Log.i(TAG, "onStartCommand: " + settings.getLong(LAST_RUN, -1))
setAlarm(context)
} else {
Log.i(TAG, "Notifications are disabled")
}
}
private fun createChannel(): NotificationChannel? {
var channel: NotificationChannel? = null
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
val name = VERBOSE_NOTIFICATION_CHANNEL_NAME
val description = VERBOSE_NOTIFICATION_CHANNEL_DESCRIPTION
val importance = NotificationManager.IMPORTANCE_HIGH
channel = NotificationChannel(CHANNEL_ID, name, importance)
channel.description = description
}
return channel
}
companion object {
fun setAlarm(context: Context) {
val broadcastIntent = Intent(context, MyReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(context.applicationContext, 121314, broadcastIntent,
PendingIntent.FLAG_CANCEL_CURRENT)
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delay, pendingIntent)
Log.i(TAG, "Alarm set")
}
const val TAG = "AlarmReceiver"
private const val MILLISECS_PER_MIN = 10000L
const val delay = MILLISECS_PER_MIN * 1// 0.5 minutes (for testing)
//private const val MILLISECS_PER_DAY = 86400000L
//private const val delay = MILLISECS_PER_DAY * 3 // 3 days
const val VERBOSE_NOTIFICATION_CHANNEL_NAME =
"Check Last Run"
const val VERBOSE_NOTIFICATION_CHANNEL_DESCRIPTION =
"Shows notifications if the user didn't open the app for 3 day"
const val NOTIFICATION_TITLE = "Notification Title"
const val CHANNEL_ID = "VERBOSE_NOTIFICATION"
const val NOTIFICATION_ID = 1021
const val ENABLED = "is_enabled"
}
}
Constants.kt
package com.example.myapplication
const val MAIN_ACTIVITY_PREFS = "mainPrefs"
const val LAST_RUN = "lastRun"
NotificationHelper.kt
package com.example.myapplication
import com.example.myapplication.MyReceiver.Companion.CHANNEL_ID
import com.example.myapplication.MyReceiver.Companion.NOTIFICATION_ID
import com.example.myapplication.MyReceiver.Companion.NOTIFICATION_TITLE
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import java.lang.NullPointerException
fun makeStatusNotification(message: String, context: Context, channel: NotificationChannel?) {
// Make a channel if necessary
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Add the channel
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (channel != null)
notificationManager.createNotificationChannel(channel)
else
throw NullPointerException("Notification Channel can't be NULL")
}
// Create the notification
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle(NOTIFICATION_TITLE)
.setContentText(message)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setVibrate(LongArray(1))
.setCategory(NotificationCompat.CATEGORY_ALARM)
// Show the notification
NotificationManagerCompat.from(context).notify(NOTIFICATION_ID, builder.build())
}
Hoping you find this helpful.
Related
While I was writing, I found a solution to my problem (my problem and solution are at the very end of the article), I want to share certain time notification function as relevant solution for API 33 in the Java language.
2023 year.
In the manifest, I created 2 new classes and the receiver
<activity
android:name=".mechanics.ReminderBroadcast"
android:exported="true">
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".mechanics.NotificationUtils"
android:exported="true">
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<receiver android:name=".mechanics.ReminderBroadcast"/>
in your xml:
<ImageView
android:id="#+id/nottificationBatton"
android:layout_width="48dp"
android:layout_height="48dp"
android:onClick="reminderNotification"
android:contentDescription="nottification Batton"
android:tooltipText="настроить отправку уведомления в заданное время на устройство пользователя"
app:srcCompat="#android:drawable/ic_menu_recent_history" />
in your main class:
public void reminderNotification(View view) {
NotificationUtils _notificationUtils = new NotificationUtils(this);
long _currentTime = System.currentTimeMillis();
long anySeconds = 1000 * 2;
long _triggerReminder = _currentTime + anySeconds; //triggers a reminder after 10 seconds.
_notificationUtils.setReminder(_triggerReminder);
}
"anySeconds" is set to +2 seconds after the current time.
dont forget import here:
import com.Me.MyProgect.mechanics.NotificationUtils;
then we create new classes:
package com.Me.MyProgect.mechanics;
import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.os.Build;
import androidx.core.app.NotificationCompat;
import com.Me.MyProgect.R;
public class NotificationUtils extends ContextWrapper {
String CHANNEL_ID = "Уведомления от Генератора Цитат";
String TIMELINE_CHANNEL_NAME = "Цитата дня";
private NotificationManager _notificationManager;
private final Context _context;
public NotificationUtils(Context base) {
super(base);
_context = base;
createChannel();
}
public NotificationCompat.Builder setNotification(String title, String body) {
return new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_poetry) // тут пояснение для тупых (как я) нужно обязательно выставлять значение в этих полях, ибо закомментировав что-то получишь фатал эрор. Ищите значок любой в своем проекте
.setContentTitle(title)
.setContentText(body)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
}
private void createChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, TIMELINE_CHANNEL_NAME, NotificationManager.IMPORTANCE_UNSPECIFIED);
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
getManager().createNotificationChannel(channel);
}
}
public NotificationManager getManager() {
if (_notificationManager == null) {
_notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
return _notificationManager;
}
public void setReminder(long timeInMillis) {
Intent _intent = new Intent(_context, ReminderBroadcast.class);
#SuppressLint("UnspecifiedImmutableFlag") PendingIntent _pendingIntent = PendingIntent.getBroadcast(_context, 0, _intent, FLAG_UPDATE_CURRENT);
AlarmManager _alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
_alarmManager.set(AlarmManager.RTC_WAKEUP, timeInMillis, _pendingIntent);
}
}
one more class:
package com.Me.MyProgect.mechanics;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import androidx.core.app.NotificationCompat;
public class ReminderBroadcast extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
NotificationUtils _notificationUtils = new NotificationUtils(context);
NotificationCompat.Builder _builder = _notificationUtils.setNotification("ГЕНЕРАТОР ЦИТАТ ГОВОРИТ:", "ААААА я что-то сделалЬ");
_notificationUtils.getManager().notify(101, _builder.build());
}
}
The code above is working.
I made a detailed description for stupid people like me.
and I had two mistakes. Firstly, I commented out the line where they select a small icon for notification, I thought it would work without it (which I didn't have at that time), but it won't, the small icon is needed.
Secondly, I caught such a message in logcat
2023-02-10 10:05:39.002 1806-1806 Layer surfaceflinger E [Surface(name=AppWindowToken(непонятная херь и описание пути к программе)] No local sync point found
The problem turned out to be that the flag was not set in Notification Utils
#SuppressLint("UnspecifiedImmutableFlag") PendingIntent _pendingIntent = PendingIntent.getBroadcast(_context, 0, _intent, FLAG_UPDATE_CURRENT);
It also needed.
I am learning programming and even the obvious things cause me difficulty.
I hope my article will help anyone to implement a similar function.
I read stackoverflow, watched logcat, the problem is solved
I am not receiving push notification for my app. I have included the manifest files, the MainActivity file, the MyFireBaseMessagingService file and the build.gradle file and the googl-services.json. I really am stumped on what the issue could be. I go to Firebase composer to write message but nothing is received. I can hard code values in strings file and I receive a notification but I wanted something more dynamic. That is why I am trying to figure out how to send push notifications from FCM but I seem to be missing something or inputting something incorrectly.
MainAcitivity file
package com.example.testaaedapp;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.InstanceIdResult;
import java.net.URI;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private ImageButton logoButton;
private ImageView blueButton, greenButton, orangeButton, yellowButton, redButton, darkBlueButton;
public Button callButton;
private final String CHANNEL_ID = "Alerts";
private final int notificationId = 001;
private static final String TAG = "MainActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
logoButton = findViewById(R.id.imageButton);
logoButton.setOnClickListener(this);
blueButton = findViewById(R.id.bluepuzzlepiece);
blueButton.setOnClickListener(this);
redButton = findViewById(R.id.redpuzzlepiece);
redButton.setOnClickListener(this);
greenButton = findViewById(R.id.greenpuzzlepiece);
greenButton.setOnClickListener(this);
orangeButton = findViewById(R.id.orangepuzzlepiece);
orangeButton.setOnClickListener(this);
yellowButton = findViewById(R.id.yellowpuzzlepiece);
yellowButton.setOnClickListener(this);
darkBlueButton = findViewById(R.id.darkbluepuzzlepiece);
darkBlueButton.setOnClickListener(this);
callButton = findViewById(R.id.button);
callButton.setOnClickListener(this);
displayNotification();
// Get token
// [START retrieve_current_token]
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
#Override
public void onComplete(#NonNull Task<InstanceIdResult> task) {
if (!task.isSuccessful()) {
Log.w(TAG, "getInstanceId failed", task.getException());
return;
}
// Get new Instance ID token
String token = task.getResult().getToken();
// Log and toast
String msg = getString(R.string.msg_token_fmt, token);
Log.d(TAG, msg);
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
}
});
// [END retrieve_current_token]
}
int requestCode = 0;
public void onClick(View view) {
if (view.getId() == R.id.button && ActivityCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
Log.d("STATE", "Call Button DOES NOT WORK");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, requestCode);
return;
} else if (view.getId() == R.id.button && ActivityCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED) {
// else if (view.getId() == R.id.button && ActivityCompat.checkSelfPermission(MainActivity.this,
// Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED) {
Log.d("STATE", "Call Button DOES WORK");
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:480-240-9255"));
startActivity(callIntent);
} else {
switch (view.getId()) {
case R.id.imageButton:
setContentView(R.layout.activity_main);
break;
case R.id.bluepuzzlepiece:
break;
case R.id.redpuzzlepiece:
Intent blogIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.aaed.org/blog"));
startActivity(blogIntent);
break;
case R.id.greenpuzzlepiece:
Intent videoIntent = new Intent(Intent.ACTION_VIEW);
videoIntent.setData(Uri.parse("https://www.youtube.com/channel/UCUwPShLvnCOTeQILvAtneOw"));
startActivity(videoIntent);
break;
case R.id.yellowpuzzlepiece:
Intent secondActivity = new Intent(this, SecondActivity.class);
startActivity(secondActivity);
break;
case R.id.orangepuzzlepiece:
Intent webIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.aaed.org"));
startActivity(webIntent);
break;
case R.id.darkbluepuzzlepiece:
Intent schoolIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.aaed.org/online-course-content"));
startActivity(schoolIntent);
}
}
}
public void displayNotification () {
createNotificationChannel();
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_puzzlepieces)
.setContentTitle("Test Message")
.setContentText("This is text")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(getString((R.string.another_string))));
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
// notificationId is a unique int for each notification that you must define
notificationManager.notify(notificationId, builder.build());
}
public void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.channel_name);
String description = getString(R.string.channel_description);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
/
/ Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == requestCode)
{
if(grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:480-240-9255"));
startActivity(callIntent);
}
}
MyFirebaseMessagingService file
package com.example.testaaedapp;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
import androidx.core.app.NotificationCompat;
import com.example.testaaedapp.MainActivity;
import com.example.testaaedapp.R;
import com.google.firebase.messaging.FirebaseMessagingService;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
// [START on_new_token]
/**
* Called if InstanceID token is updated. This may occur if the security of
* the previous token had been compromised. Note that this is called when the InstanceID token
* is initially generated so this is where you would retrieve the token.
*/
#Override
public void onNewToken(String token) {
Log.d(TAG, "Refreshed token: " + token);
// If you want to send messages to this application instance or
// manage this apps subscriptions on the server side, send the
// Instance ID token to your app server.
sendRegistrationToServer(token);
}
// [END on_new_token]
Manifest File
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testaaedapp">
<!--
The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
Google Maps Android API v2, but you must specify either coarse or fine
location permissions for the 'MyLocation' functionality.
-->
<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=".MapsActivity"
android:label="#string/title_activity_maps"></activity>
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="AAED" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/ic_puzzlepieces" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/colorAccent" />
<activity
android:name=".MainActivity"
android:label="Autism Academy"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SecondActivity"
android:label="Locations"></activity>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="#string/google_maps_key" />
<!-- [START firebase_service] -->
<service
android:name=".MyFirebaseMessagingService"
android:exported="false"
android:enabled="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<!-- [END firebase_service] -->
</application>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CALL_PHONE"></uses-permission>
</manifest>
I've had a similar issue. I've tried everything - in my opinion the main reason is that all the services are, sooner or later, being killed by the system. The only way is to make sure to deliver the notification to the system tray not to the application. To do that you need to use Data message notifications.
There are 2 types of FCM notifications: Notification message and Data message.
Data messages are delivered to system tray and are always display - even if service is not running.
Notification message looks like:
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification":{
"title":"Portugal vs. Denmark",
"body":"great match!"
}
}
}
and triggers method OnMessageReceaved() of FirebaseMessagingService. Many devices (especially Huawei and Xiaomi) try to do everything to kill background services to prevent battery drain. So the FirebaseMessagingService isn't the best way to handle notifications.
Second type is Data message:
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data":{
"Nick" : "Mario",
"body" : "great match!",
"Room" : "PortugalVSDenmark"
}
}
}
This type is handled by the system tray, so you don't need any of service running to get the notification. Its much more convenient method, but as far i know, it can't be achieved with the console.
You would probably need server API to send Data message.
Read this for more details.
I have an app that before worked fine but recently won't run.
Before it only had offline features, the most complex would be the local notification - but I need to add a GCM functionality to it. I searched for answers but it's so difficult to understand.
I tried to copy the code of a tutorial I've seen. I learned that I need a thing called GCMRegistrar but I don't know where to get it. Then I tested my app, there were errors of course because I don't have the gcmregistrar.
What I did is I enclosed the code in a comment block and ran the app again. That's when my app won't run anymore. After a few days of this mishap, I decided to create another app where I would put all the offline feature of my app. after that copying and pasting, I tried to run my the new app but it also won't run.
I've searched for ways to fix it and found a few fixes. Those fix works for other apps but won't work for my new app.
Here's my MainActivity.java, this one has the local notification
package com.example.mypower_build101;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity {
Button addDevice, showDevice, showDialog;
String[] arrContentTxt;
final Context ctx = this;
int notifCount;
int x = 0;
Handler notifLauncher, notifStopper;
String contentTxt;
Resources res = getResources();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addDevice = (Button)findViewById(R.id.btnAddDevice);
showDevice = (Button)findViewById(R.id.btnShowDevice);
showDialog = (Button)findViewById(R.id.btnShowDialog);
arrContentTxt = res.getStringArray(R.array.notifContentText);
//contentTxt = arrContentTxt[1];
showDialog.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
/*DialogFragment diag = new SwitchCheckChange();
diag.show(getFragmentManager(), "cbo Click");*/
showNotif();
}
});
useNotifLauncher();
useNotifStopper();
}
public void useNotifLauncher(){
notifLauncher = new Handler();
notifLauncher.postDelayed(runNotif, 50000);
}
public Runnable runNotif = new Runnable(){
#Override
public void run() {
showNotif();
notifLauncher.postDelayed(runNotif, 50000);
}
};
public void useNotifStopper(){
notifStopper = new Handler();
notifStopper.postDelayed(stopNotif, 40000);
}
public Runnable stopNotif = new Runnable(){
#Override
public void run() {
cancelNotification(x);
notifStopper.postDelayed(stopNotif, 40000);
}
};
public void addClick(View v){
Intent i = new Intent(this, AddDeviceForm.class);
startActivity(i);
}
public void showClick(View v){
Toast.makeText(getBaseContext(), "Please wait...", Toast.LENGTH_LONG).show();
Intent i = new Intent(this, ListViewForm.class);
startActivity(i);
}
public void showNotif(){
Uri notifSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Intent i = new Intent(MainActivity.this, NotifReceiver.class);
PendingIntent pi = PendingIntent.getActivity(MainActivity.this, 0, i, 0);
//String[] notifTitle = R.array.notifTitle;
Notification notif = new Notification.Builder(this)
.setContentTitle("MyPower Reminder")
.setContentText("Unplug unused appliances and chargers")
//.setContentText(contentTxt)
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pi)
.setSound(notifSound)
.addAction(0, "View Full Reminder", pi)
.build();
NotificationManager notifMgr = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
notifMgr.notify(0, notif);
}
public void cancelNotification(int notificationId){
if (Context.NOTIFICATION_SERVICE!=null) {
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager nMgr = (NotificationManager) getApplicationContext().getSystemService(ns);
nMgr.cancel(notificationId);
}
}
}
here's my androidmanifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mypower_build101"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="17" />
<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>
<activity
android:name=".AddDeviceForm"
android:label="#string/title_activity_add_device_form" >
</activity>
<activity
android:name=".ListViewForm"
android:label="#string/title_activity_list_view_form" >
</activity>
<activity
android:name=".NotifReceiver"
android:label="#string/title_activity_notif_receiver" >
</activity>
</application>
</manifest>
I'm not putting everything here because it would be to lengthy and I think the problems might be at the MainActivity or the android manifest.
If you could teach me how use the gcm thing that would be very, very, much appreciated.
Hi guys for some reason my post have an error so please use and look at this document. here's the document link
https://www.dropbox.com/s/tc2j2a2pan53r96/Ricky%20Manalo%20LogCat%20Log.docx?dl=0
I'm currenty devepoling an Android Application that remembers the user to a daily action.
The idea is, that the app gives a notification to the user if he did not already performed the action. The notification should appear every day at i.e. 3PM.
My Question is, how I can implement the check. I already found tutorials about how to use AlarmManager and NotificationManager, but these would remember the user even, if he already is finished.
Is there a way to start the check instead of the Notification, and if the check says there should be a notification, it is published?
You could save a shared preference that indicated the last time the user had completed the daily action. The when your alarm fires, you start a service that checks the status of the shared preference. If it was less than 1 day ago, then the user has done the daily action today.
Here's how you'd check:
SharedPreferences settings = getSharedPreferences(MainActivity.PREFS, MODE_PRIVATE);
if (System.currentTimeMillis() - settings.getLong("lastTimeActionDone", 0) < MILLISECS_PER_DAY) {
// Action done within last day
} else {
// Action not done within last day
}
Here's how you'd save the last time the action had been done:
SharedPreferences settings = getSharedPreferences(MainActivity.PREFS, MODE_PRIVATE);
SharedPreferences.Editor editor = null;
editor.putLong("lastTimeActionDone", System.currentTimeMillis());
editor.commit();
EDIT:
Here's a sample app that does most of what you want. As written, it just wakes up at the same time each day with that time being the time of day that the app was last started. So the one major piece missing is to make the alarm wake at a specific time each day. To get that part working, you'd need to a little date-time arithmetic when setting the (first) alarm time.
MainActivity.java:
package com.example.dailycheck;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
public class MainActivity extends Activity {
private final static String TAG = "MainActivity";
public final static String PREFS = "PrefsFile";
private SharedPreferences settings = null;
private SharedPreferences.Editor editor = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
// Save time of run:
settings = getSharedPreferences(PREFS, MODE_PRIVATE);
editor = settings.edit();
// First time running app?
if (!settings.contains("lastTimeActionDone"))
enableNotification(null);
Log.v(TAG, "Starting CheckRecentRun service...");
startService(new Intent(this, CheckActionDone.class));
}
public void doAction(View v) {
Log.v(TAG, "Recording time action done");
editor.putLong("lastTimeActionDone", System.currentTimeMillis());
editor.commit();
}
public void enableNotification(View v) {
editor.putBoolean("enabled", true);
editor.commit();
Log.v(TAG, "Notifications enabled");
}
public void disableNotification(View v) {
editor.putBoolean("enabled", false);
editor.commit();
Log.v(TAG, "Notifications disabled");
}
}
CheckActionDone.java:
package com.example.dailycheck;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.IBinder;
import android.util.Log;
public class CheckActionDone extends Service {
private final static String TAG = "CheckRecentPlay";
private static Long MILLISECS_PER_DAY = 86400000L;
private static long delay = 60000; // 1 minute (for testing)
// private static long delay = MILLISECS_PER_DAY; // 1 day
#Override
public void onCreate() {
super.onCreate();
Log.v(TAG, "Service started");
SharedPreferences settings = getSharedPreferences(MainActivity.PREFS, MODE_PRIVATE);
// Are notifications enabled?
if (settings.getBoolean("enabled", true)) {
// And was action not recently done?
Long lastTimeDone = settings.getLong("lastTimeActionDone", 0);
if ((System.currentTimeMillis() - lastTimeDone) >= delay) {
sendNotification();
} else {
Log.i(TAG, "Action recently done");
}
} else {
Log.i(TAG, "Notifications are disabled");
}
// Set an alarm for the next time this service should run:
setAlarm();
Log.v(TAG, "Service stopped");
stopSelf();
}
public void setAlarm() {
Intent serviceIntent = new Intent(this, CheckActionDone.class);
PendingIntent pi = PendingIntent.getService(this, 131313, serviceIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delay, pi);
Log.v(TAG, "Alarm set");
}
public void sendNotification() {
Intent mainIntent = new Intent(this, MainActivity.class);
#SuppressWarnings("deprecation")
Notification noti = new Notification.Builder(this)
.setAutoCancel(true)
.setContentIntent(PendingIntent.getActivity(this, 131314, mainIntent,
PendingIntent.FLAG_UPDATE_CURRENT))
.setContentTitle("Action Not Do")
.setContentText("You didn't do the daily action.")
.setDefaults(Notification.DEFAULT_ALL)
.setSmallIcon(R.drawable.ic_launcher)
.setTicker("You haven;t done the daily action; please do it now.")
.setWhen(System.currentTimeMillis())
.getNotification();
NotificationManager notificationManager
= (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(131315, noti);
Log.v(TAG, "Notification sent");
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
main_activity.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="doAction"
android:text="#string/do_action" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="enableNotification"
android:text="#string/enable" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="disableNotification"
android:text="#string/disable" />
</LinearLayout>
strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Come Back</string>
<string name="do_action">Do Action</string>
<string name="enable">Enable Notifications</string>
<string name="disable">Disable Notifications</string>
</resources>
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.dailycheck"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.dailycheck.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>
<service
android:name="com.example.dailycheck.CheckActionDone" >
</service>
</application>
</manifest>
I'm trying to create a reminder application that pops up a reminder in the status bar. As I understand, the Android NotificationManager is the standard tool to use to schedule notifications however a BootService is needed in order to re-schedule notifications as scheduled events do not survive across boots.
I've pieced together an application below which schedules a single reminder at boot time, and pops up a notification in the status bar. If you click the notification, it launches MainActivity which, in the future, will have options to add more reminders, delete them, or whatever.
The problem I'm having is that the reminder works correctly the first time however it seems to be re-scheduling itself and popping up again at random times for some reason. Should I be launching another activity rather than the one which installs the BootAlarmService?
UPDATE:
So I think I found some clues with logcat. Apparently the Service is crashing and being restarted which is resetting the Notification. Any ideas why this is?
UPDATE II : code changed to working model
ActivityManager I No longer want com.example.alarm_boot_test (pid 1428): hidden #16
ActivityManager W Scheduling restart of crashed service com.example.alarm_boot_test/.BootAlarmService in 5000ms
ActivityManager W Scheduling restart of crashed service com.example.alarm_boot_test/.NotificationAlarmService in 15000ms
ActivityManager I Start proc com.example.alarm_boot_test for service com.example.alarm_boot_test/.BootAlarmService: pid=2321 uid=10069 gids={}
dalvikvm D Debugger has detached; object registry had 1 entries
szipinf D Initializing inflate state
BootAlarmService D oncreate()
BootAlarmService D alarm set for Thu Jan 17 08:03:00 CST 2013
MainActivity.java
package com.example.alarm_boot_test;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity
{
#Override
protected void onCreate (Bundle savedInstanceState)
{
super.onCreate (savedInstanceState);
setContentView (R.layout.activity_main);
}
}
BootAlarmService.java
package com.example.alarm_boot_test;
import java.util.Calendar;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class BootAlarmService extends Service
{
private final String TAG = this.getClass ().getName ();
#Override
public void onCreate ()
{
Log.d (TAG, "oncreate()");
super.onCreate ();
}
#Override
public int onStartCommand (Intent intent, int flags, int startId)
{
Log.d (TAG, "alarm_test: BootAlarmService.onStartCommand() Received start id " + startId + ": " + intent);
// if intent == null, service has been killed/restarted by system
if (intent != null)
createNotificationOnBoot();
else
Toast.makeText (getBaseContext (), "Intent was null in BootAlarmService.", Toast.LENGTH_LONG).show();
return START_STICKY;
}
private void createNotificationOnBoot ()
{
Intent inotify = new Intent(this , NotificationAlarmService.class);
inotify.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
AlarmManager amgr = (AlarmManager)getSystemService(ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, inotify, 0);
// go off two mins from now
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MINUTE, calendar.get (Calendar.MINUTE) + 2);
amgr.set (AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis (), pendingIntent);
Log.d (TAG, "alarm set for " + calendar.getTime ().toString ());
}
#Override
public IBinder onBind (Intent intent)
{
return null;
}
}
BootReceiver.java
package com.example.alarm_boot_test;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class BootReceiver extends BroadcastReceiver
{
#Override
public void onReceive (final Context context, final Intent bootintent)
{
Intent i = new Intent ();
i.setAction ("com.example.alarm_boot_test.BootAlarmService");
context.startService (i);
}
}
NotificationAlarmService.java
package com.example.alarm_boot_test;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class NotificationAlarmService extends Service
{
private final String TAG = this.getClass().getName ();
#Override
public void onCreate ()
{
super.onCreate ();
}
#Override
public int onStartCommand (Intent intent, int flags, int startId)
{
Log.d (TAG, "alarm_test: NotificationAlarmService.onStartCommand()");
if (intent != null)
createNotification ();
else
Toast.makeText (getBaseContext (), "Intent was null in NotificationAlarmService.", Toast.LENGTH_LONG).show();
return super.onStartCommand (intent, flags, startId);
}
private void createNotification()
{
NotificationManager notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
Notification notification = new Notification(android.R.drawable.stat_sys_warning, "Note from AlarmService", System.currentTimeMillis());
Intent i = new Intent(this, ViewReminder.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, i, 0);
notification.setLatestEventInfo(this, "New Notification", "You have been notified by AlarmService", pendingIntent);
notificationManager.notify(10001, notification);
}
#Override
public IBinder onBind (Intent intent)
{
return null;
}
}
*activity_main.xml*
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Service started! Reboot!" />
</RelativeLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.alarm_boot_test"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="9" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<service android:name="com.example.alarm_boot_test.BootAlarmService" >
<intent-filter>
<action android:name="com.example.alarm_boot_test.BootAlarmService" >
</action>
</intent-filter>
</service>
<receiver android:name="com.example.alarm_boot_test.BootReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" >
</action>
</intent-filter>
</receiver>
<service android:name="com.example.alarm_boot_test.NotificationAlarmService" >
</service>
<activity
android:name="com.example.alarm_boot_test.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>
In case it helps someone else, I think I needed to check the passed Intent for NULL in the onStartCommand() method both in BootAlarmService.java as well as NotificationAlarmService.java. Only been testing it a couple days but it looks like the Intent is NULL if the system kills/restarts the service. Simply testing for this allowed me to create the notification only when the service is started at Boot-time (when the passed Intent is NOT null).