Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android, Display alertDialog instead of notification when app is open

I followed this developer tutorial, and have Geofencing working within my app, as expected.

A notification is sent when a Geofence Transition occurs, from within an IntentService:

@Override
protected void onHandleIntent(Intent intent) {
    GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);

    ...        

    sendNotification(geofenceTransitionDetails);
}

private void sendNotification(String notificationDetails) {
    // Create an explicit content Intent that starts the main Activity.
    Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);

    // Construct a task stack.
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);

    // Add the main Activity to the task stack as the parent.
    stackBuilder.addParentStack(MainActivity.class);

    // Push the content Intent onto the stack.
    stackBuilder.addNextIntent(notificationIntent);

    // Get a PendingIntent containing the entire back stack.
    PendingIntent notificationPendingIntent =
            stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);

    // Get a notification builder that's compatible with platform versions >= 4
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this);

    // Define the notification settings.
    builder.setSmallIcon(R.mipmap.ic_launcher)
            // In a real app, you may want to use a library like Volley
            // to decode the Bitmap.
            .setLargeIcon(BitmapFactory.decodeResource(getResources(),
                    R.mipmap.ic_launcher))
            .setColor(Color.RED)
            .setContentTitle(notificationDetails)
            .setContentText("Return to app")
            .setContentIntent(notificationPendingIntent);

    // Dismiss notification once the user touches it.
    builder.setAutoCancel(true);

    // Get an instance of the Notification manager
    NotificationManager mNotificationManager =
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

    // Issue the notification
    mNotificationManager.notify(0, builder.build());
}

This is cookie-cutter from the tutorial. The intent is set-up in the Main activity:

private PendingIntent getGeofencePendingIntent() {
    // Reuse the PendingIntent if we already have it.
    if (mGeofencePendingIntent != null) {
        return mGeofencePendingIntent;
    }
    Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
    // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling
    // addGeofences() and removeGeofences().
    return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}

How can I add functionality that suppresses the notifications if the app is open, and instead displays an AlertDialog to the user? Ideally, I'd like to be able to execute different tasks, depending on which view the user is currently in when the Geofence Transition occurs. Can I monitor/intercept the transition from within each view, or somehow globally?

Thanks in advance.

like image 558
Birrel Avatar asked Sep 16 '15 02:09

Birrel


People also ask

How to implement an Android notification action without opening the app?

This example demonstrate about How to implement an Android notification action without opening the app. Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main.xml.

What is an alert dialog in Android?

Android - Alert Dialog. A Dialog is small window that prompts the user to a decision or enter additional information. Some times in your application, if you wanted to ask the user about taking a decision between yes or no in response of any particular action taken by the user, by remaining in the same activity and without changing the screen,...

How to implement Android alert dialog using getlistview?

getListView () − it is used to get a list view which is used inside alert dialog. This example demonstrate about how to implement android alert dialog. Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main.xml.

Why are notifications not showing up on my Android device?

Here are some of the ways to fix it when notifications are not showing up on your Android device. Check That Do Not Disturb is not enabled. It may seem obvious, but forgetting Do Not Disturb is enabled is one of the most common causes for not receiving notifications. If this setting is on (enabled), turn it off, and they will start working again.


2 Answers

Some of the answers were incomplete, and so here is the complete solution to what I was looking for.

First off, set up MyApplication class, that implements ActivityLifecycleCallbacks:

public class MyApplication extends Application implements Application.ActivityLifecycleCallbacks {

    private static boolean isActive;

    @Override
    public void onCreate() {
        super.onCreate();

        registerActivityLifecycleCallbacks(this);
    }

    public static boolean isActivityVisible(){
        return isActive;
    }

    @Override
    public void onActivityResumed(Activity activity) {
        isActive = true;
    }

    @Override
    public void onActivityPaused(Activity activity) {
        isActive = false;
    }

    ... no other methods need to be used, but there are more that 
    ... must be included for the ActivityLifecycleCallbacks
}

Be sure to name this in your manifest (only name line was added, rest is default):

<application
    android:name=".MyApplication"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme"
    android:hardwareAccelerated="true">

What was done above is used to track the lifecycle of your app. You can use this to check if your app is currently in the foreground or not.

Next is to set up a BroadcastReceiver, wherever you would like code to run (in the event that the app is open when the trigger occurs). In this case, it is in my MainActivity:

protected BroadcastReceiver mNotificationReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        ... Do whatever you want here

        Toast.makeText(...).show();
    }
};

Register the receiver in your onCreate of the same activity:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    ...

    LocalBroadcastManager.getInstance(this).registerReceiver(mNotificationReceiver, new IntentFilter("some_custom_id"));
}

And don't forget to unregister it:

@Override
protected void onDestroy() {
    LocalBroadcastManager.getInstance(this).unregisterReceiver(mNotificationReceiver);
    super.onDestroy();
}

When a broadcast is received, the code within the receiver is executed.

Now, to check if the app is in the foreground, and send a broadcast if it is. Inside of the IntentService:

@Override
protected void onHandleIntent(Intent intent) {
    GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
    if (geofencingEvent.hasError()) {
        String errorMessage = getErrorString(this,
                geofencingEvent.getErrorCode());
        return;
    }

    int geofenceTransition = geofencingEvent.getGeofenceTransition();

    // Test that the reported transition was of interest.
    if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
            geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {

        ...

        if(MyApplication.isActivityVisible()){
            Intent intnt = new Intent("some_custom_id");
            intnt.putExtra("message", geofenceTransitionDetails);
            LocalBroadcastManager.getInstance(this).sendBroadcast(intnt);
        }else{
            sendNotification(geofenceTransitionDetails);
        }

    } else {
        // Log the error.
    }
}

The important bit is the last nested if-statement:

if(MyApplication.isActivityVisible()){
    Intent intnt = new Intent("some_custom_id");
    intnt.putExtra("message", geofenceTransitionDetails);
    LocalBroadcastManager.getInstance(this).sendBroadcast(intnt);
}else{
    sendNotification(geofenceTransitionDetails);
}

Check if the app is in the foreground using MyApplication.isActivityVisible(), as defined above, and then either send the notification, or send a broadcast. Just make sure that your intent code (i.e. "some_custom_id") matches on your sender and receiver.

And that's about it. If the app is in the foreground (specifically the MainActivity), I execute some code. If the app is not in the foreground, I send a notification.

like image 194
Birrel Avatar answered Sep 27 '22 17:09

Birrel


The easiest way would be to use LocalBroadcastManager or some event bus.

So when transition happens you should send local broadcast from IntentService and catch it with some component X in between IntentService and any of your Activity's. Component X must track if any of your Activity's is in foreground and

  • if yes - pass other local broadcast up (to the foreground Activity),
  • if not - show notification.

Please note that in Android you cannot track easily if your app is in foreground or not (and if you have more than 1 Activity, you cannot do it properly in my opinion) but you can try.

like image 43
Marian Paździoch Avatar answered Sep 27 '22 16:09

Marian Paździoch