I am building an app which creates a service that triggers an alarm when people have birthdays ( At 12.00AM ). The app is based on firebase realtime database.The problem I am facing here is:
The service doesn't work first time when the app is launched i.e: I get toast "Service Started" but the service is absent from running services when the app is cleared.
2.When the app is opened second time the service works well (Also alarms)
3.I have tried to implement Work manager but it doesn't seem to work at Android Nougat and above.(Where as it should work!)
4.Notifications trigger when the app is opened and also there are 2 or more notifications when the app is in Background.
So, what's wrong here?
Here are my classses:
NotificationHelper.java
public class NotificationHelper extends ContextWrapper {
public NotificationHelper(Context base, int peopleCount) {
super(base);
this.peopleCount = peopleCount;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelID, channelName, NotificationManager.IMPORTANCE_HIGH);
getManager().createNotificationChannel(channel);
}
}
private int peopleCount;
public static final String channelID = "channel_145";
public static final String channelName = "Birthday Notification";
private NotificationManager mManager;
public NotificationManager getManager() {
if (mManager == null) {
mManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
return mManager;
}
public NotificationCompat.Builder getChannelNotification() {
return new NotificationCompat.Builder(getApplicationContext(), channelID)
.setContentTitle("Birthday Reminder!")
.setContentText( peopleCount + " people have birthday today!")
.setSmallIcon(R.drawable.ic_stat_notify)
.setColor(Color.GREEN)
.setAutoCancel(true)
.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, Birthday.class), PendingIntent.FLAG_UPDATE_CURRENT));
}
}
Myservice.java
public class MyService extends Service {
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
Toast.makeText(getApplicationContext(),"Service Started",Toast.LENGTH_LONG).show();
//StartWorker();
StartAlarm();
return Service.START_REDELIVER_INTENT;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
public void StartWorker()
{
Calendar currentDate = Calendar.getInstance();
Calendar dueDate = Calendar.getInstance();
dueDate.set(Calendar.HOUR_OF_DAY, 0);
dueDate.set(Calendar.MINUTE, 0);
dueDate.set(Calendar.SECOND, 0);
if (dueDate.before(currentDate)) {
dueDate.add(Calendar.HOUR_OF_DAY, 24);
}
long timeDiff = ((dueDate.getTimeInMillis())-(currentDate.getTimeInMillis()));
final OneTimeWorkRequest oneTimeWorkRequest = new
OneTimeWorkRequest.Builder(Myworker.class)
.setInitialDelay(timeDiff, TimeUnit.MILLISECONDS)
.build();
WorkManager.getInstance(getApplicationContext()).enqueue(oneTimeWorkRequest);
}
public void StartAlarm()
{
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE,0);
calendar.set(Calendar.SECOND,1);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
alarmIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 1456, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pendingIntent);
}
@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(getApplicationContext(),"Service Destroyed",Toast.LENGTH_LONG).show();
Intent intent = new Intent(this, MyService.class);
startService(intent);
}
}
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
private DatabaseReference myRef;
private ArrayList<String> allPeoples;
private int numberOfPeoples;
private Context ctx;
@Override
public void onReceive(Context context, Intent intent) {
ctx = context;
FirebaseDatabase database = FirebaseDatabase.getInstance();
myRef = database.getReference("Users");
myRef.keepSynced(true);
initPeoples();
}
public String getCurrentDate() {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat mdformat = new SimpleDateFormat("d MMMM");
String strDate = mdformat.format(calendar.getTime());
return strDate;
}
private void initPeoples() {
FirebaseDatabase database = FirebaseDatabase.getInstance();
myRef = database.getReference("Users");
myRef.keepSynced(true);
myRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
allPeoples = new ArrayList<>();
for(DataSnapshot snapshot : dataSnapshot.getChildren()){
if(snapshot.getKey().equals("Teacher") || snapshot.getKey().equals("Staff")){
for(DataSnapshot faculty : snapshot.child("peoples").getChildren()){
String birthday = (String) faculty.child("DOB").getValue();
if(birthday.equals(getCurrentDate())) {
String member = birthday;
allPeoples.add(member);
}
}
}else{
for(DataSnapshot student : snapshot.child("peoples").getChildren()){
String birthday = (String) student.child("DOB").getValue();
if(birthday.equals(getCurrentDate())) {
String member = birthday;
allPeoples.add(member);
}
}
}
}
numberOfPeoples = allPeoples.size();
NotificationHelper notificationHelper = new NotificationHelper(ctx, numberOfPeoples);
NotificationCompat.Builder nb = notificationHelper.getChannelNotification();
notificationHelper.getManager().notify(1, nb.build());
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
}
AutoStart.java
public class AutoStart extends BroadcastReceiver
{
public void onReceive(Context context, Intent arg1)
{
Intent intent = new Intent(context, MyService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(intent);
} else {
context.startService(intent);
}
Log.i("Autostart", "started");
}
}
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="......">
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:name="......"
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"
tools:ignore="GoogleAppIndexingWarning"
android:usesCleartextTraffic="true"
>
<activity android:name=".Activities.Birthday"></activity>
<activity android:name=".Activities.Contributors" />
<activity
android:name=".Activities.SearchDetails"
android:theme="@style/AppTheme.Fullscreen" />
<activity android:name=".Activities.Search" />
<activity android:name=".Activities.Students" />
<activity android:name=".Activities.Settings" />
<activity
android:name=".Activities.FacultySlider"
android:theme="@style/AppTheme.Fullscreen" />
<activity
android:name=".Activities.StudentSlider"
android:theme="@style/AppTheme.Fullscreen" />
<activity android:name=".Activities.PeopleList" />
<activity android:name=".Activities.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".AlarmReceiver"/>
<service android:name=".MyService"
android:label="Birthday Notification Service"
android:enabled="true"/>
<receiver android:name=".AutoStart"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.CALL_PHONE"
tools:ignore="ManifestOrder" />
</manifest>
Edit: I am starting myservice with this on MainActivity's onCreate Method:
Intent intent = new Intent(this, MyService.class);
startService(intent);
Edit 2: On Android Oreo a notification is automatically triggered when the app is opened