0

I want to send a notification to user if there is any changes in firebase database. I have tried using Broadcast-Receiver, Service, Work-Manager, Alarm-Manager. But none of them works perfectly. It only works when app is running or in background and also working in some devices[tested in android 7] when app is closed. But In android 10[tested in Samsung and Xiaomi], it's not working when app is closed. When I turn off battery saver in my app in Xiaomi, it works sometime after closing app, then stops working. Some people said, You have turn-off battery saver and turn-on auto-start mode in Xiaomi and do something in other manufacturers phone. But there are many app that shows notification even though I haven't open the app for more that 10/15 days and I have checked in app-info of those app that battery-saver in on and auto-start is off[checked in Xiaomi-android10]. What am I doing wrong? Service:

public class ServiceManager extends Service {


public ServiceManager() {}

@Override
public IBinder onBind(Intent intent) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public void onCreate() {
    getLastModifiedTime2(new HomePage.MyCallback() {
        @Override
        public void onCallback(String roll) {
            SharedPreferences spExtra = getSharedPreferences("spExtra",MODE_PRIVATE);
            if(!Objects.equals(spExtra.getString("1", "No changes"), roll)){
                SharedPreferences.Editor editor = spExtra.edit();
                editor.putString("1",roll);
                editor.apply();
                showNotification(getApplicationContext());
                //
            }
        }
    });
}

@Override
public void onDestroy() {
}
@Override
public int onStartCommand(Intent intent, int flags, int startid) {
    System.out.println("called start command");
    //
    getLastModifiedTime2(new HomePage.MyCallback() {
        @Override
        public void onCallback(String roll) {
            SharedPreferences spExtra = getSharedPreferences("spExtra",MODE_PRIVATE);
            if(!Objects.equals(spExtra.getString("1", "No changes"), roll)){
                SharedPreferences.Editor editor = spExtra.edit();
                editor.putString("1",roll);
                editor.apply();
                showNotification(getApplicationContext());
            }
        }
    });
    //
    return START_STICKY;
}

private void stopService() {
}
 //not showing the method getlastmodifiedtime2 and shownotification;
}

and starting service that below:

startService(new Intent(this, ServiceManager.class));

Work-manager:

public class UploadWorker extends Worker {

public UploadWorker(
        @NonNull Context context,
        @NonNull WorkerParameters workerParams){
    super(context, workerParams);
}

@NonNull
@Override
public Result doWork() {
    System.out.println("UploadWorker called");
    getLastModifiedTime2(new HomePage.MyCallback() {
        @Override
        public void onCallback(String roll) {
            SharedPreferences spExtra = getApplicationContext().getSharedPreferences("spExtra",MODE_PRIVATE);
            if(!Objects.equals(spExtra.getString("1", "No changes"), roll)){
                SharedPreferences.Editor editor = spExtra.edit();
                editor.putString("1",roll);
                editor.apply();
                showNotification(getApplicationContext());
                //
            }
            //startNewRequest();
        }
    });
    return Result.success();
    //return Result.Retry.retry();
}
//not showing function getlastmodifiedtime2 and shownotification
}

calling worker like below:

PeriodicWorkRequest workRequest = new PeriodicWorkRequest
                .Builder(UploadWorker.class,15,TimeUnit.MINUTES).build();
        WorkManager.getInstance(this).enqueueUniquePeriodicWork("firebaseTest",
                ExistingPeriodicWorkPolicy.KEEP,workRequest);

and alarm-manager code:

Calendar cal = Calendar.getInstance();
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.set(Calendar.HOUR_OF_DAY, 12);
    calendar.set(Calendar.MINUTE, 25);
    calendar.set(Calendar.SECOND, 30);

    Intent intent = new Intent(HomePage.this, ServiceManager.class);
    PendingIntent pintent = PendingIntent.getService(HomePage.this, 0, intent, 0);
    AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
    System.out.println("called alarm-intent");
    System.out.println("called"+cal.getTimeInMillis());
    alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 60*1000, pintent);

All of them are not working when app is closed. Some people says to use foreground services, but won't it show a notification all the time. What process should I use to do my work[notifying user when data is changed in firebase].

Abu Saeed
  • 1,020
  • 8
  • 21
  • In Android we got two type of notification in android first the data come in notification tittle,body and other staff its work good in all case even your app is closed but its not work in background case but if you want you notification work in background so you should use notification data all the data come in notifcation data and its work in background also – Amit pandey Jan 20 '21 at 07:32
  • @Amitpandey I am not understanding fully. can you provide any example or link? – Abu Saeed Jan 20 '21 at 08:43

2 Answers2

0

You need to show Notification, see this link.

Foreground service is a separate issue. In Oreo+ devices, services cannot be run when app is in background or closed unless the service is started in foreground, in which they require a notification which is shown the whole time the service is running.

CaseH
  • 40
  • 6
  • There are many app that shows notification without showing permanent notification. apps like telegram,clash royale, ..... and many. – Abu Saeed Jan 20 '21 at 08:45
  • Yes the above notification can be called off too if needed. Just [call cancel](https://stackoverflow.com/questions/3595232/android-remove-notification-from-notification-bar) in handler.postdelayed or using a BroadcastReceiver PendingIntent. – CaseH Jan 20 '21 at 12:49
  • Broadcast receiver is not being called when app is killed in Android 9 and 10. – Abu Saeed Jan 20 '21 at 13:50
  • There must be some error in your code. You can also try with explicit broadcast intent, e.g `new Intent(myContext, MyReceiver.class)`. PS: receivers wont work if app is dormant (force stopped or data cleared or never started after installation) – CaseH Jan 21 '21 at 08:22
  • all of my above code are working when I turned off battery saver for my app. Broadcast receiver is working same like others. By the way, can you provide some code of broadcast receiver that will worked when app is killed? – Abu Saeed Jan 21 '21 at 08:40
0

All of them given above aren't working when app is killed or closed. Then I tried Firebase cloud messaging and it worked[tested in android 7,10] even if app is closed or killed.

RequestQueue requestQueue;
requestQueue = Volley.newRequestQueue(this);

--

public void sendNotificationToUser() {
        JSONObject mainObj = new JSONObject();
        try {
            mainObj.put("to", "/topics/" + topic_name);//
            JSONObject notificationObj = new JSONObject();
            notificationObj.put("title", "About title");
            notificationObj.put("body", "Enter you message here");
            mainObj.put("notification", notificationObj);

            JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, value,
                    mainObj, new Response.Listener<JSONObject>() {//value="https://fcm.googleapis.com/fcm/send"
                @Override
                public void onResponse(JSONObject response) {
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {

                }
            }) {
                @Override
                public Map<String, String> getHeaders() throws AuthFailureError {

                    Map<String, String> header = new HashMap<>();
                    header.put("content-type", "application/json");
                    header.put("authorization", "key=" + server-key);
                    return header;
                }
            };
            Toast.makeText(this, "Successfully added", Toast.LENGTH_SHORT).show();
            requestQueue.add(jsonObjectRequest);
            //
    }
}

Make sure to import

implementation 'com.mcxiaoke.volley:library:1.0.19'

Don't put your server-key inside your app. You can use Firebase cloud function for this[not free]. Above code will send notification to all of the user who are subcribed to topic_name.

Abu Saeed
  • 1,020
  • 8
  • 21