0

I am working on an app which is used to place product requests. More of like a shopping app. The user will get offers when the admin posts one. I used firebase and created a root called offers and the offers are added as child under the offers node. Database structure of offers node

i have created a firebasebackground listener service and added onChildEventListener. When ever a new offer is posted the user is notified with the offer.

Firebasebackgroundservice.java:
public class FirebaseBackgroundService extends Service {

    private DatabaseReference f;
    NotificationManager manager;
    Notification myNotication;
    private TinyDB database;

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent,int flags,int startId) {
        super.onCreate();
        manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        database=new TinyDB(getApplicationContext());
        FirebaseApp.initializeApp(getApplicationContext());
        f= FirebaseDatabase.getInstance().getReference();
        final DatabaseReference foff=f.child("offers");

        foff.limitToLast(1).addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                ArrayList<String>offarray=new ArrayList<String>();
                offarray=database.getListString("offdata");
                if(!offarray.contains(dataSnapshot.getKey())){
                    offarray.add(dataSnapshot.getKey());
                    database.putListString("offdata",offarray);
                    Map<String, Object> newPost = (Map<String, Object>) dataSnapshot.getValue();
                    String title=newPost.get("title").toString();
                    String code=newPost.get("code").toString();
                    postNotif(title,code);
                }

            }

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String s) {

            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {

            }

            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String s) {

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });

        //Order updates
        String uname=database.getString("uname");
        final DatabaseReference fupd=f.child("users").child(uname).child("notif");
        fupd.limitToLast(1).addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                ArrayList<String>offarray=new ArrayList<String>();
                offarray=database.getListString("updata");
                if(!offarray.contains(dataSnapshot.getKey())){
                    offarray.add(dataSnapshot.getKey());
                    database.putListString("updata",offarray);
                    Map<String, Object> newPost = (Map<String, Object>) dataSnapshot.getValue();
                    String title=newPost.get("title").toString();
                    String code=newPost.get("code").toString();
                    updateNotif(title,code);
                }

            }

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String s) {

            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {

            }

            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String s) {

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });

        return START_STICKY;
    }

    private void postNotif(String title,String descp) {
        Context context=getApplicationContext();
        Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        Bitmap icon = BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher);
        try {
            int smallIcon = R.drawable.ic_card;
            long when = System.currentTimeMillis();
            CharSequence contentTitle = title;
            CharSequence contentText = descp;
            Intent notificationIntent = new Intent(context,OfferActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
            NotificationManager notificationManager =(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
            NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context)
                    .setWhen(when)
                    .setContentText(contentText)
                    .setContentTitle(contentTitle)
                    .setSmallIcon(smallIcon)
                    .setAutoCancel(true)
                    .setTicker(contentTitle)
                    .setLargeIcon(icon)
                    .setContentIntent(pendingIntent)
                    .setSound(alarmSound);
            notificationManager.notify((int) when, notificationBuilder.build());
        } catch (Exception e) {
            Log.e("Notification Exception", e.getMessage());
        }
    }
    private void updateNotif(String title,String descp) {
        Context context=getApplicationContext();
        Bitmap icon = BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher);
        Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        try {
            int smallIcon = R.drawable.ic_file_upload;
            long when = System.currentTimeMillis();
            CharSequence contentTitle = title;
            CharSequence contentText = descp;
            Intent notificationIntent = new Intent(context,Notifications.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
            NotificationManager notificationManager =(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
            NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context)
                    .setWhen(when)
                    .setContentText(contentText)
                    .setContentTitle(contentTitle)
                    .setSmallIcon(smallIcon)
                    .setAutoCancel(true)
                    .setTicker(contentTitle)
                    .setLargeIcon(icon)
                    .setContentIntent(pendingIntent)
                    .setSound(alarmSound);
            notificationManager.notify((int) when, notificationBuilder.build());
        } catch (Exception e) {
            Log.e("Notification Exception", e.getMessage());
        }
    }
    @Override
    public void onDestroy(){
        super.onDestroy();
        startService(new Intent(this,FirebaseBackgroundService.class));
    }

}

The app is working fine but I am facing two issues here: 1. When the service is started initially the notifications are shown. But at times the service is being killed by the OS. And when the service is restarted the notifications are not shown. The service is being killed and is not restarted for a long time. 2. The childAddedListener is not called after the service resumes and hence the notifications are also not shown

The app works perfectly fine on first start of service. once the service is killed the notifications are not shown and the childaddedlistener is not working

Please help me with this. I searched a lot for firebasebackgroundservice but ended up with this. Thank you.

  • By "notified" do you mean a push notification when the app is in the background? – Rohan Stark Jul 02 '17 at 12:27
  • Yes. When the child is added under offers the background service should show notification. – mavilla vishnu vardhan Jul 02 '17 at 12:45
  • 1
    Have you considered using Firebase Cloud Messaging (FCM) for your push notifications? – Rohan Stark Jul 02 '17 at 12:50
  • It is indeed expected behavior that database changes are only synchronized to the client when the service is active. In order to prolong battery life, the OS may kill such long-running services. The solution is (as Rohan said) to use a service like FCM to either deliver background data or (more involved, but more scalable) to wake up the service when it needs to synchronize data. See [my previous answer here](https://stackoverflow.com/questions/42210186/handling-keepsynced-while-on-background-on-android-and-with-fcm/42210878#42210878). – Frank van Puffelen Jul 02 '17 at 14:11

0 Answers0