5

Ho seguito il tutorial this per gli sviluppatori e ho Geofencing che funziona all'interno della mia app, come previsto.Android, Display alertDialog invece di notifica quando l'app è aperta

Una notifica viene inviata quando si verifica un Geofence transizione, all'interno di un 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()); 
} 

Questo è cookie-cutter dal tutorial. L'intento è set-up nel Principale attività:

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

Come posso aggiungere funzionalità che sopprime le notifiche se l'applicazione è aperta, e invece visualizza un AlertDialog per l'utente? Idealmente, mi piacerebbe essere in grado di eseguire diverse attività, a seconda della vista in cui l'utente è attualmente inserito quando si verifica la transizione Geofence. Posso monitorare/intercettare la transizione da ciascuna vista o in qualche modo a livello globale?

Grazie in anticipo.

risposta

5

Alcune delle risposte erano incomplete, e quindi ecco la soluzione completa per quello che stavo cercando.

Prima di tutto, impostare MyApplication di classe, che implementa 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 
} 

Assicurarsi di chiamare questo nella vostra manifesta (unica linea nome è stato aggiunto, il resto è di 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"> 

Quanto sopra è usato per tracciare il ciclo di vita della tua app. Puoi usarlo per verificare se la tua app è attualmente in primo piano o meno.

Il prossimo è impostare un BroadcastReceiver, ovunque si desideri eseguire il codice (nel caso in cui l'app sia aperta quando si verifica l'attivazione).In questo caso, è nel mio MainActivity:

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

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

registrare il ricevitore nella vostra onCreate della stessa attività:

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

    ... 

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

E non dimenticate di annullare la registrazione è:

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

Quando si riceve una trasmissione, viene eseguito il codice all'interno del ricevitore.

Ora, per verificare se l'app è in primo piano e inviare una trasmissione se lo è. All'interno della 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. 
    } 
} 

Il bit importante è l'ultima se-dichiarazione nidificato:

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

Verificare se l'applicazione è in primo piano con MyApplication.isActivityVisible(), come sopra definito, e quindi inviare il notifica, o inviare una trasmissione. Assicurati che il tuo codice di intenti (ad esempio "some_custom_id") corrisponda al mittente e al destinatario.

E questo è tutto. Se l'app è in primo piano (in particolare MainActivity), eseguo del codice. Se l'app non è in primo piano, invio una notifica.

+1

Ho appena effettuato l'accesso per ringraziare. –

0

a) È possibile notificare al servizio gli eventi del ciclo di vita dell'attività.

b) È possibile mantenere lo stato corrente dell'interfaccia utente in un campo statico dell'attività e controllarlo dal servizio prima di mostrare la notifica.

+0

Non sono sicuro di aver capito bene, ma sembra che eliminerebbero solo le notifiche. Come posso usare quelli per visualizzare alertDialogs quando si verifica la transizione geofence? O per aggiornare la vista? Si prega di fornire un codice con la tua risposta. – Birrel

1

Il modo più semplice sarebbe utilizzare LocalBroadcastManager o alcuni event bus.

Così, quando accade di transizione è necessario inviare trasmissione locale da IntentService e prendere con una certa component X tra IntentService e le tue Activity 's. Component X devono traccia se uno dei tuoi Activity 's è in primo piano e

  • se sì - approvare altre trasmissione locale fino (in primo piano Activity),
  • se non - spettacolo di notifica.

Si prega di notare che in Android non è possibile tenere traccia facilmente se la vostra applicazione è in primo piano oppure no (e se si dispone di più di 1 attività, non si può fare come si deve a mio parere), ma you can try.

+0

In questo momento, il meglio che posso pensare con 'LocalBroadcastManager' è quello di includere un destinatario in ciascuna delle mie attività. C'è un modo per coprire tutte le attività con un singolo ricevitore? Inoltre, come posso sopprimere/interrompere le notifiche dall'interno di 'IntentService' quando l'app è aperta? – Birrel

+0

Quello che ho trovato funziona meglio è una combinazione tra la tua risposta, che mi permette di mostrare avvisi ed eseguire attività, e [questo] (http://stackoverflow.com/questions/3667022/checking-if-an-android-application -is-running-in-the-background/13809991 # 13809991) risposta, che mi consente di determinare se l'app è in esecuzione o meno. – Birrel

Problemi correlati