I want to run a service whenever the user opens the app and then make it run as long as the app is installed for every 1 minute. The service will check if there are new orders by making an API call and if there are then it'll show a notification.
I have done some research and found JobIntentService and Broadcast Reciever are what I need to use for my problem but I am not able to put them together to make it work. I'll really appreciate if someone can give a detailed solution. I also want to know if there is something better than this for my problem? Below is the code I managed to write.
Background Service
public class BackgroundService extends JobIntentService {
private static final String TAG = BackgroundService.class.getName();
private static final int JOB_ID = 1;
private NotificationManager notificationManager;
public static void enqueueWork(Context context, Intent intent) {
enqueueWork(context, BackgroundService.class, JOB_ID, intent);
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, getClass().getSimpleName() + "#onCreate");
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "Running in background!");
sendBroadcast(new Intent(getApplicationContext(), BackgroundService.class));
}
@Override
protected void onHandleWork(@NonNull Intent intent) {
Log.d(TAG, getClass().getSimpleName() + "#onHandleWork!");
APIInterface service = RetrofitClientInstance.getRetrofitInstance().create(APIInterface.class);
Call<List<OrdersModel>> call = service.getAllOrders(Services.CONSUMER_KEY,Services.CONSUMER_SECRET);
call.enqueue(new Callback<List<OrdersModel>>() {
@Override
public void onResponse(@NonNull Call<List<OrdersModel>> call,@NonNull Response<List<OrdersModel>> response) {
if (response.body() != null) {
for (OrdersModel orders : response.body()){
if (orders.getStatus().equals("processing")){
sendNotification("#" + orders.getNumber());
}
}
}
}
@Override
public void onFailure(@NonNull Call<List<OrdersModel>> call,@NonNull Throwable t) {
Log.d(TAG, getClass().getSimpleName() + "Network Error!");
}
});
}
private void sendNotification(String title) {
Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Intent intent = new Intent(this, GetOrdersActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
Notification.Builder notificationBuilder = new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle(title)
.setAutoCancel(true)
.setSound(defaultSound)
.setContentText("New Order")
.setContentIntent(pendingIntent)
.setWhen(System.currentTimeMillis())
.setPriority(Notification.PRIORITY_HIGH)
.setCategory(Notification.CATEGORY_MESSAGE);
notificationManager.notify(0, notificationBuilder.build());
Log.d("GoParty", "Notification sent ----- ");
}
}
BroadcastReciever
public class NotificationReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent notificationIntent = new Intent(context, BackgroundService.class);
BackgroundService.enqueueWork(context, notificationIntent);
}
}
That's not how it should work. The app on the mobile device must preserve battery life. Polling doesn't do that well. What you want is a push notification, where the server is playing the active part. You can achieve that with Firebase Cloud Messaging, for example.
Have a look: https://firebase.google.com/docs/cloud-messaging/android/client?authuser=0
The server is responsible for knowing when a new order is available and can act in the exact right moment to send a push notification to the client app.