简体   繁体   中英

How to receive continuous geofence notifications even when app is killed?

I am using the latest geofence api in my app and followed Google's sample code to build the app. But it does not work when the app is killed.I have to click the Add Geofence button again to trigger the geofence.I want the geofences to be triggered at all times. What should i do? Here is my code:

Main Activity

public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks
    , GoogleApiClient.OnConnectionFailedListener,ResultCallback<Status> {
protected GoogleApiClient googleApiClient;
protected ArrayList<Geofence> geofenceArrayList;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    button= (Button) findViewById(R.id.button);
    geofenceArrayList = new ArrayList<>();
    populateGeofenceList();
    buildGoogleApiClient();
}

protected synchronized void buildGoogleApiClient() {
    googleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
}

@Override
protected void onStart() {
    super.onStart();
    if (!googleApiClient.isConnected() || !googleApiClient.isConnecting()) {
        googleApiClient.connect();
    }
}

@Override
protected void onStop() {
    super.onStop();
    if (googleApiClient.isConnected() || googleApiClient.isConnecting()) {
        googleApiClient.disconnect();
    }
}

public void populateGeofenceList() {
    for (Map.Entry<String, LatLng> entry : Constants.MY_LANDMARKS.entrySet()) {
        geofenceArrayList.add(new Geofence.Builder()
                .setRequestId(entry.getKey())
                .setCircularRegion(entry.getValue().latitude, entry.getValue().longitude, 100)
                .setExpirationDuration(Geofence.NEVER_EXPIRE)
                .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_DWELL | Geofence.GEOFENCE_TRANSITION_EXIT)
                .setLoiteringDelay(300000)
                .build());
    }
}
private GeofencingRequest getGeofencingRequest(){
    GeofencingRequest.Builder builder=new GeofencingRequest.Builder();
    builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
            .addGeofences(geofenceArrayList);
    return builder.build();
}
private PendingIntent getGeofencePendingIntent(){
    Intent intent=new Intent(this,GeofenceTransitionService.class);
    return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
public void addGeofencesButtonHandler(View view){
    if(!googleApiClient.isConnected()){
        Toast.makeText(this,"Client not connected",Toast.LENGTH_SHORT).show();
        return;
    }
    try {
        LocationServices.GeofencingApi.addGeofences(googleApiClient,getGeofencingRequest(),getGeofencePendingIntent()).setResultCallback(this);
    }catch (SecurityException securityException){

    }
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

@Override
public void onConnected(Bundle bundle) {

}

@Override
public void onConnectionSuspended(int i) {
    googleApiClient.connect();
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {

}

@Override
public void onResult(Status status) {
    if(status.isSuccess()){
        Toast.makeText(this,"Geofence added",Toast.LENGTH_SHORT).show();
    }
    else {
        String errorMessage=GeofenceErrorMessages.getErrorString(this,status.getStatusCode());
        Log.e("MainActivity",errorMessage);
    }
}

}

Intent Service

public class GeofenceTransitionService extends IntentService {
/**
 * Creates an IntentService.  Invoked by your subclass's constructor.
 *
 * @param name Used to name the worker thread, important only for debugging.
 */
public static final String TAG="GeofenceService";

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

public GeofenceTransitionService() {
    super(TAG);
}

@Override
protected void onHandleIntent(Intent intent) {
    GeofencingEvent geofencingEvent=GeofencingEvent.fromIntent(intent);
    if(geofencingEvent.hasError()){
        String errorMsg=GeofenceErrorMessages.getErrorString(this,geofencingEvent.getErrorCode());
        Log.e(TAG,errorMsg);
        return;
    }
    int geofenceTransition=geofencingEvent.getGeofenceTransition();
    if(geofenceTransition== Geofence.GEOFENCE_TRANSITION_ENTER||geofenceTransition==Geofence.GEOFENCE_TRANSITION_DWELL
            ||geofenceTransition==Geofence.GEOFENCE_TRANSITION_EXIT){
        List<Geofence> triggeringGeofences=geofencingEvent.getTriggeringGeofences();
        String geofenceTransitionDetails=getGeofenceTransiionDetails(this,geofenceTransition,triggeringGeofences);
        sendNotification(geofenceTransitionDetails);
        Log.i(TAG,geofenceTransitionDetails);
    }
    else {
        Log.e(TAG,"Invalid Transition : "+geofenceTransition);
    }
}
private String getGeofenceTransiionDetails(Context context,int transition,List<Geofence> triggeringGeofences){
    String geofenceTransitionString=getTransitionString(transition);
    ArrayList GeofenceIdsList=new ArrayList();
    for(Geofence geofence:triggeringGeofences){
        GeofenceIdsList.add(geofence.getRequestId());
    }
    String geofencesIdsString= TextUtils.join(", ", GeofenceIdsList);
    return geofenceTransitionString+": "+geofencesIdsString;
}
private String getTransitionString(int transitionType){
    switch (transitionType){
        case Geofence.GEOFENCE_TRANSITION_ENTER:
            return "Entered the geofence";
        case Geofence.GEOFENCE_TRANSITION_DWELL:
            return "Dwelling in the geofence";
        case Geofence.GEOFENCE_TRANSITION_EXIT:
            return "Exited the geofence";
        default:return "Unknown Transition";
    }
}
private void sendNotification(String notificationDetails){
    Intent notificationIntent=new Intent(getApplicationContext(),MainActivity.class);
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
    stackBuilder.addParentStack(MainActivity.class);
    stackBuilder.addNextIntent(notificationIntent);
    PendingIntent notificationPendingIntent=stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
    NotificationCompat.Builder builder=new NotificationCompat.Builder(this);
    builder.setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle(notificationDetails)
            .setContentText("Click to return to app")
            .setContentIntent(notificationPendingIntent);
    builder.setAutoCancel(true);
    NotificationManager manager= (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    manager.notify(0,builder.build());
}

}

django, your question is already answered here.

https://stackoverflow.com/a/19521823/5320593

You should use BroadcastReceiver instead of IntentService or use them consequentially to avoid ANRs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM