当应用程序被杀时,地理围栏并不起作用

时间:2016-08-08 19:28:15

标签: android android-broadcastreceiver android-geofence

我知道这个问题已经被问到,但是我尝试了很多建议的解决方案,但它没有用。

我的地理围栏代码在应用程序运行时有效,但一旦应用程序被终止,即使BroadcastReceiver

,通知也不会再出现

你可以在这里找到与活动相关的代码,btn_reservation是开始添加地理围栏的按钮。

public class DetailsActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        ResultCallback<Status> {

public static final long GEOFENCE_EXPIRATION_IN_MILLISECONDS = 12 * 60 * 60 * 1000;
public static final float GEOFENCE_RADIUS_IN_METERS = 500
private List<Geofence> mGeofenceList;
private GoogleApiClient mGoogleApiClient;
private Button btn_reservation;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_details);

    btn_reservation = (Button) findViewById(R.id.reserver);

    mGeofenceList = new ArrayList<Geofence>();

    mGeofenceList.add(new Geofence.Builder()

            .setRequestId("1")

            .setCircularRegion(
                    MapsActivity.getLatitude(),
                    MapsActivity.getLongitude(),
                    GEOFENCE_RADIUS_IN_METERS
            )
            .setExpirationDuration(GEOFENCE_EXPIRATION_IN_MILLISECONDS)
            .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER)
            .build());


    // Create an instance of GoogleAPIClient.
    if (mGoogleApiClient == null) {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }


    btn_reservation.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
                if (!mGoogleApiClient.isConnected()) {
                    Toast.makeText(getApplicationContext(), "Google API Client not connected!", Toast.LENGTH_SHORT).show();
                    return;
                }

                try {
                    LocationServices.GeofencingApi.addGeofences(
                            mGoogleApiClient,
                            getGeofencingRequest(),
                            getGeofencePendingIntent()
                    ).setResultCallback(DetailsActivity.this); // Result processed in onResult().
                } catch (SecurityException securityException) {
                    // Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
                    Toast.makeText(getApplicationContext(), "ACCESS_FINE_LOCATION permission unused ", Toast.LENGTH_SHORT).show();
                }
            }
    });

}

private GeofencingRequest getGeofencingRequest() {
    GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
    builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
    builder.addGeofences(mGeofenceList);
    return builder.build();
}

private PendingIntent getGeofencePendingIntent() {

    Intent intent = new Intent("ACTION_RECEIVE_GEOFENCE");

    return PendingIntent.getBroadcast(
            getApplicationContext(),
            0,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT);
}

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

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

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {

}

@Override
public void onConnected(Bundle bundle) {

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // TODO: Consider calling
        //    ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
        //                                          int[] grantResults)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.
        return;
    }
    Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
            mGoogleApiClient);
    if (mLastLocation != null) {
        System.out.println("My lat " +String.valueOf(mLastLocation.getLatitude()));
        System.out.println("My lon " +String.valueOf(mLastLocation.getLongitude()));
    }
}

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

@Override
public void onResult(Status status) {
    if (status.isSuccess()) {
        System.out.println("Geofences Added");
    } else {
        System.out.println(status.getStatusCode());
    }
}

这是我的GeofenceReceiver.java

public class GeofenceReceiver extends BroadcastReceiver {
Context context;

Intent broadcastIntent = new Intent();

@Override
public void onReceive(Context context, Intent intent) {
    this.context = context;

    broadcastIntent.addCategory(GeofenceUtils.CATEGORY_LOCATION_SERVICES);

    GeofencingEvent event = GeofencingEvent.fromIntent(intent);
    if (event.hasError()) {
        handleError(intent);
    } else {
        handleEnterExit(intent);
    }

}

private void handleError(Intent intent){
    GeofencingEvent event = GeofencingEvent.fromIntent(intent);
    // Get the error code
    int errorCode = event.getErrorCode();

    // Get the error message
    String errorMessage = LocationServiceErrorMessages.getErrorString(
            context, errorCode);

    // Log the error
    Log.e(GeofenceUtils.APPTAG,
           "geofence_transition_error_detail"+
                    errorMessage);

    // Set the action and error message for the broadcast intent
    broadcastIntent
            .setAction(GeofenceUtils.ACTION_GEOFENCE_ERROR)
            .putExtra(GeofenceUtils.EXTRA_GEOFENCE_STATUS, errorMessage);

    // Broadcast the error *locally* to other components in this app
    LocalBroadcastManager.getInstance(context).sendBroadcast(
            broadcastIntent);
}


private void handleEnterExit(Intent intent) {

    GeofencingEvent event = GeofencingEvent.fromIntent(intent);
    int transition = event.getGeofenceTransition();

    // Test that a valid transition was reported
    if ((transition == Geofence.GEOFENCE_TRANSITION_ENTER)
            || (transition == Geofence.GEOFENCE_TRANSITION_EXIT)) {

        // Post a notification
        List<Geofence> geofences = event
                .getTriggeringGeofences();
        String[] geofenceIds = new String[geofences.size()];
        String ids = TextUtils.join(GeofenceUtils.GEOFENCE_ID_DELIMITER,
                geofenceIds);
        int tran = Geofence.GEOFENCE_TRANSITION_ENTER;
        String transitionType = String.valueOf(tran);

        // Create an Intent to broadcast to the app
        broadcastIntent
                .setAction(GeofenceUtils.ACTION_GEOFENCE_TRANSITION)
                .addCategory(GeofenceUtils.CATEGORY_LOCATION_SERVICES);

        LocalBroadcastManager.getInstance(context)
                .sendBroadcast(broadcastIntent);

        // Log the transition type and a message
        Log.d(GeofenceUtils.APPTAG, transitionType + ": " + ids);
        Log.d(GeofenceUtils.APPTAG,
                context.getString(R.string.geofence_transition_notification_text));

        // In debug mode, log the result
        Log.d(GeofenceUtils.APPTAG, "transition");

        // An invalid transition was reported
    } else {
        // Always log as an error
        Log.e(GeofenceUtils.APPTAG,
                "geofence_transition_invalid_type"
                       + transition);
    }

    sendNotification(String.valueOf(Geofence.GEOFENCE_TRANSITION_ENTER), "here");
}

private void sendNotification(String transitionType, String locationName) {

    // Create an explicit content Intent that starts the main Activity
    Intent notificationIntent = new Intent(context, TicketActivity.class);

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

    // Adds the main Activity to the task stack as the parent
    stackBuilder.addParentStack(TicketActivity.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(
            context);

    // Set the notification contents
    builder.setSmallIcon(R.drawable.cast_ic_notification_0)
            .setContentTitle(transitionType + ": " + locationName)
            .setContentText(
                    context.getString(R.string.geofence_transition_notification_text))
            .setContentIntent(notificationPendingIntent);

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

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

    System.out.println("in radius");
  }
}

这是清单中的接收者

 <receiver android:name="tn.odc.noq.receiver.GeofenceReceiver" android:exported="false">
    <intent-filter >
      <action android:name="tn.odc.noq.receiver.ACTION_RECEIVE_GEOFENCE"/>
      <category android:name="tn.odc.noq.receiver" />
    </intent-filter>
  </receiver>

1 个答案:

答案 0 :(得分:0)

从头开始使用地理围栏真的很难,我一直都在尝试这样做,但我没有得到一个好的存根。所以我采用了一些libs

这里有一些很棒的库:

Smart-location-lib

例如:

GeofenceModel mestalla = new GeofenceModel.Builder("id_mestalla")
    .setTransition(Geofence.GEOFENCE_TRANSITION_ENTER)
    .setLatitude(39.47453120000001)
    .setLongitude(-0.358065799999963)
    .setRadius(500)
    .build();

Android-rxgeofence

 RxGeoFence.with(this) //context
        .dbUrl(GEO_FIRE_DB) //String
        .geoFenceSource(...) // rx.Observable<List<Place>>
        .locationSource(...) // rx.Observable<LatLng>
        .build()
        .subscribe(geoFenceEvent -> {
         // do what you wanna do with the event
     });

Android-ReactiveLocation

 Geofence geofence = new Geofence.Builder()
                    .setRequestId("GEOFENCE")
                    .setCircularRegion(latitude, longitude, radius)
                    .setExpirationDuration(Geofence.NEVER_EXPIRE)
                    .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
                    .build();

我实际上指出使用libs,因为有大量的开发人员正在努力解决所有问题,并且协商异常。