5

Ich folgte this Entwickler-Tutorial, und Geofencing funktioniert wie erwartet in meiner App.Android, Display alertDialog anstelle von Benachrichtigung, wenn App geöffnet ist

eine Benachrichtigung gesendet wird, wenn ein Geofence Übergang auftritt, innerhalb einer 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()); 
} 

Dies ist Cookie-Cutter aus dem Tutorial. Die Absicht ist in der Haupttätigkeit Aufstellmaße:

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); 
} 

Wie kann ich Funktionalität hinzufügen, die die Meldungen unterdrückt, wenn die App geöffnet ist, und zeigt stattdessen eine Alertdialog für den Benutzer? Im Idealfall würde ich gerne verschiedene Aufgaben ausführen können, je nachdem, in welcher Ansicht sich der Benutzer gerade befindet, wenn der Geofence-Übergang stattfindet. Kann ich den Übergang von jeder Ansicht aus oder in irgendeiner Weise global überwachen/abfangen?

Vielen Dank im Voraus.

Antwort

5

Einige der Antworten waren unvollständig, und so hier ist die vollständige Lösung für was ich suchte.

First off, einrichten MyApplication Klasse, die ActivityLifecycleCallbacks implementiert:

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 
} 

Seien Sie sicher, dass dies in Ihrem Manifest nennen (nur Namenszeile hinzugefügt wurde, Rest ist Standard):

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

Mit dem oben beschriebenen Verfahren können Sie den Lebenszyklus Ihrer App verfolgen. Sie können damit prüfen, ob Ihre App gerade im Vordergrund ist oder nicht.

Als nächstes muss ein BroadcastReceiver eingerichtet werden, wo immer Code ausgeführt werden soll (falls die App beim Auftreten des Triggers geöffnet ist).In diesem Fall ist es in meinem MainActivity:

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

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

den Empfänger in Ihrem onCreate der gleichen Aktivität registrieren:

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

    ... 

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

Und vergessen Sie nicht, es deregistrieren:

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

Wenn eine Sendung empfangen wird, wird der Code im Empfänger ausgeführt.

Jetzt, um zu überprüfen, ob die App im Vordergrund ist, und senden Sie eine Sendung, wenn es ist. Innerhalb des 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. 
    } 
} 

Das wichtige Bit ist die letzte verschachtelte if-Anweisung:

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

Überprüfen Sie, ob die App im Vordergrund MyApplication.isActivityVisible() verwenden, wie oben definiert, und dann entweder senden die Benachrichtigung, oder senden Sie eine Sendung. Stellen Sie einfach sicher, dass Ihr Absichtscode (d. H. "some_custom_id") mit Ihrem Sender und Empfänger übereinstimmt.

Und das ist es. Wenn die App im Vordergrund ist (speziell die MainActivity), führe ich etwas Code aus. Wenn die App nicht im Vordergrund ist, sende ich eine Benachrichtigung.

+1

Ich habe mich gerade eingeloggt, um Danke zu sagen. –

0

a) Sie können Ihren Dienst über die Lebenszyklusereignisse der Aktivität informieren.

b) Sie können den aktuellen Status Ihrer UI in einem statischen Feld der Aktivität beibehalten und vor dem Anzeigen der Benachrichtigung vom Dienst überprüfen.

+0

Ich bin nicht sicher, ob ich das richtig mache, aber diese klingen, als würden sie nur die Benachrichtigungen unterdrücken. Wie kann ich diese verwenden, um alertDialogs anzuzeigen, wenn der Geofence-Übergang auftritt? Oder um die Ansicht zu aktualisieren? Bitte geben Sie einen Code mit Ihrer Antwort an. – Birrel

1

Der einfachste Weg wäre LocalBroadcastManager oder einige event bus zu verwenden.

Also, wenn Übergang geschieht, sollten Sie lokale Broadcast von IntentService senden und es mit einigen component X zwischen IntentService und jeder Ihrer Activity ‚s fangen. Component X müssen verfolgen, ob alle Ihre Activity ‚s im Vordergrund ist und

  • wenn ja - pass andere lokale Sendung auf (in den Vordergrund Activity),
  • wenn nicht - Show-Benachrichtigung.

Bitte beachten Sie, dass in Android Sie können nicht einfach verfolgen, wenn Ihre Anwendung im Vordergrund ist oder nicht (und wenn Sie mehr als 1 Aktivität haben, können Sie es richtig meiner Meinung nach nicht tun), sondern you can try.

+0

Im Moment kann ich mit dem 'LocalBroadcastManager' nur einen Empfänger in meine Aktivitäten aufnehmen. Gibt es eine Möglichkeit, alle Aktivitäten mit einem einzigen Empfänger abzudecken? Wie kann ich Benachrichtigungen im "IntentService" unterdrücken/stoppen, wenn die App geöffnet ist? – Birrel

+0

Was ich gefunden habe funktioniert am besten ist eine Kombination zwischen Ihrer Antwort, mit der ich Warnungen anzeigen und Aufgaben ausführen kann, und [this] (http://stackoverflow.com/questions/3667022/checking-if-android-application -is-running-in-the-background/13809991 # 13809991) beantworten, mit dem ich feststellen kann, ob die App läuft oder nicht. – Birrel

Verwandte Themen