hajas
hajas

Reputation: 133

How to display a notification when my application is in background?

​I am trying to build an Android application that has -

a First Activity (Launcher activity)

and a Second Activity

What I am trying to achieve :

First Actvity takes an input from user , fetches data from web using an AsyncTaskLoader . In the onLoadFinished it checks if input is valid and if it is starts an Intent to Second Activity to sh​​ow more details . The input is also passed along with the Intent .

Since the network operation can take time so I decided to show a notification using IntentService just before Second Activity is created i.e. the notification is being called in onLoadFinished just before the Intent . The notification should directly start the Second Activity if it isn't already started .

What is working fine :

Both activities and the loader are working fine . The notification is also being displayed and everything is working as expected provided user keeps the app running .

What isn't :

When the user navigates away from First Activity while data is being loaded the notification is not shown because onPause is executed . I tried searching for it and got to know about BroadcastReceiver , JobScheduler and FirebaseJobDispatcher but I can't really understand them and how they help .

So , am I on the right track ? And how can I achieve the same functionality even if app goes into background ?

P.S. The code is much more vast than the problem suggests so I didn't include it . That's why if explanation seems incomplete or messy I will try my best to clarify your doubts .

Upvotes: 2

Views: 584

Answers (4)

hajas
hajas

Reputation: 133

I finally made it work without using a BroadcastReciever or Service so those of you who are unfamiliar with them can take reference from this but use it your it at your own discretion as Services and Recivers are the recommended way to do it .

@Override
public void deliverResult(Data data) {
    super.deliverResult(data);
    showNotification(input);
}

This is a method in AsyncTaskLoader which is triggered after data is obtained . Override it and alter the method of your notification that responds to notification click .

private PendingIntent onClick(Context context) {
     return PendingIntent.getActivity(context, 0, new Intent(context, ExtraActivity.class).
putExtra(Intent.EXTRA_TEXT,input),PendingIntent.FLAG_UPDATE_CURRENT);
}

The ExtraActivity is similar to this . It allows your notification to respond even if activity has been closed but the notification hasn't .

Again this is only a workaround for this specific situation which leads to me to pass around the input variable in many places and so it may not be as efficient performance-wise as other options .

Upvotes: 0

Luís Henriques
Luís Henriques

Reputation: 634

Yes. You are on the right track.

Here is a sample from a map downloader I made. I hope you don't mind, but since you gave no context, I had to find a suitable example.

/**
* @param entry the map entry to be downloaded
* @return returns a receiver that unzips the map file after downloading
*/
private BroadcastReceiver createMapReceiver(MapEntry entry) {
     return new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             unregisterReceiver(this); // we unregister this receiver after the download is complete
             receiveDownloadedFile(entry); // once we receive the map file, we run this function, but you can do whatever you want. This is the part of the code youn were asking for
         }
     };
}


void downloadMap() {

    // preparing the download
    BroadcastReceiver receiver = createMapReceiver(entry); // see function above

  DownloadManager manager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
  registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));

  String downloadURL = fileListURL + entry.getFileName() + fileExtension; // building the url for the map
  DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downloadURL));

  if (manager != null) {
      manager.enqueue(request
              .setDestinationUri(Uri.fromFile(new File(areaFolder, entry.getFolderName())))
                    .setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI|DownloadManager.Request.NETWORK_MOBILE)
                    .setAllowedOverRoaming(false)
                    .setTitle("Some title, preferably taken from Strings.xml")
                    .setDescription("Some Description")
                    .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
            );
        } else {
            // if we couldn't find the DownloadManager
            onFailure(entry); // we simply run some onFailure function
        }

    }

Don't forget the permissions.

Upvotes: 1

asm
asm

Reputation: 21

how can I achieve the same functionality even if app goes into background

use bound services or intent services. intent service allow you to perform actions asynchronously. bound services can provide interface using aidl. as long as the service is bound, it will be less likely destroyed. there are various ways to bind service using flags.

imho, activity is just a way of displaying UI. if you need any background work, use services. when working with bound services via aidl, you will have to extend service connection. it will receive the interface from service after binding.

Upvotes: 0

manish poddar
manish poddar

Reputation: 484

Register a Broadcast receiver through LocalBroadcastManager, and define filters. Now depending on filters you can play with UI elements or intents.

IntentFilter filter = new IntentFilter();
    filter.addAction("A");
    filter.addAction("B");
    filter.addAction("C");
    LocalBroadcastManager.getInstance(getContext()).registerReceiver(dummyReceiver, filter);



private BroadcastReceiver dummyReceiver = new BroadcastReceiver() {
@Override
    public void onReceive(final Context context, final Intent intent) {
          //Do your work**
 }}

Try this. I have implemented this and it works.

Upvotes: 1

Related Questions