Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.4k views
in Technique[技术] by (71.8m points)

android - listen for firebase event after app killed

I was trying listen for a change in firebase firestore collection, after the app is closed. For that I have written the following code:

FirebaseFirestore.getInstance().collection("demo").addSnapshotListener(new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(@Nullable QuerySnapshot value, @Nullable FirebaseFirestoreException error) {
                //show a notification to user
                ...
                ...
                Toast.makeText(MainActivity.this, "collection modified", Toast.LENGTH_SHORT).show();
            }
        });

It works when the app is in background (pressed backbutton to exit app, but app is available on recent screen) but when I clear the app from recent screen, the code stops working.

How can I listen for firebase event even after the app is killed?

Edit:

I tried to use two approaches, but as soon as the app get swiped from recents screen both of these approaches stop working:

  1. Using Alarm Manager. Following is the code for this implementation:

AlarmReceiver.java

public class AlarmReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        FirebaseFirestore.getInstance().collection("demo").addSnapshotListener(new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(@Nullable QuerySnapshot value, @Nullable FirebaseFirestoreException error) {
                Toast.makeText(context, "collection modified", Toast.LENGTH_LONG).show();
            }
        });

    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startFirebaseTesting();
            }
        });
    }

    private void startFirebaseTesting() {
        Intent in = new Intent(this, FirebaseService.class);
        in.setAction("com.example.this.app");
        in.addCategory("android.intent.category.DEFAULT");
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 4, in, PendingIntent.FLAG_ONE_SHOT|PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+1000*5, pendingIntent);
        } else
            alarmManager.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+1000*5, pendingIntent);
    }
}

AndroidManifest.xml

<application>
...
...
        <receiver
            android:name=".AlarmReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.example.this.app"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </receiver>
...
...
</application>
  1. Adnan Arshad's answer to this question

Both of these solution don't work on MotoG5s plus (Oreo) and Samsung A50 (Android 10).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Whenever you wish to run any code in the background use Services.

So in our case it will be something like this:

  1. Create a FirebaseService.java class.
public class FirebaseService extends Service {

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(getApplicationContext(), "service starting", Toast.LENGTH_SHORT).show();

        FirebaseFirestore.getInstance().collection("demo").addSnapshotListener(new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(@Nullable QuerySnapshot value, @Nullable FirebaseFirestoreException error) {
                //show a notification to user
                Toast.makeText(getApplicationContext(), "collection modified", Toast.LENGTH_SHORT).show();
            }
        });

        // If we get killed, after returning from here, restart
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        // We don't provide binding, so return null
        return null;
    }

    @Override
    public void onDestroy() {
        Toast.makeText(getApplicationContext(), "service done", Toast.LENGTH_SHORT).show();
    }

}
  1. Start the service using startService() from your Activity.
Intent intent = new Intent(this, FirebaseService.class);
startService(intent);

Note:

When a service is started, it has a lifecycle that's independent of the component that started it. The service can run in the background indefinitely, even if the component that started it is destroyed. As such, the service should stop itself when its job is complete by calling stopSelf(), or another component can stop it by calling stopService().

  1. Every Service must be declared in the Manifest.xml file.
<manifest ... >
  ...
  <application ... >
      <service android:name=".FirebaseService" />
      ...
  </application>
</manifest>

SUGGESTION

If you just want to display a pop up notification when the firebase collection is updated then it is best to implement it using Firebase Cloud Messaging as you can easily display built-in notifications without worrying about the lifecycles.

If you want to use this method then here is a complete tutorial that will help you:

https://www.youtube.com/watch?v=Y6jMKQ9zo-o


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...