当用户离开区域时在地理围栏中实施停留

Implementing Dwell in Geofence when user exits the region

MainActivity.java

    import android.Manifest;
    import android.app.PendingIntent;
    import android.content.Intent;
    import android.content.pm.PackageManager;
    import android.location.Location;
    import android.location.LocationManager;
    import android.os.Bundle;
    import android.support.v4.app.ActivityCompat;
    import android.support.v7.app.AppCompatActivity;
    import android.support.v7.widget.Toolbar;
    import android.util.Log;

    import com.google.android.gms.common.ConnectionResult;
    import com.google.android.gms.common.GooglePlayServicesUtil;
    import com.google.android.gms.common.api.GoogleApiClient;
    import com.google.android.gms.common.api.ResultCallback;
    import com.google.android.gms.common.api.Status;
    import com.google.android.gms.location.Geofence;
    import com.google.android.gms.location.GeofencingRequest;
    import com.google.android.gms.location.LocationListener;
    import com.google.android.gms.location.LocationRequest;
    import com.google.android.gms.location.LocationServices;

    import java.util.ArrayList;
    import java.util.List;
    import java.util.UUID;

    public class MainActivity extends AppCompatActivity implements LocationListener {

        PendingIntent mGeofencePendingIntent;
        public static final int CONNECTION_FAILURE_RESOLUTION_REQUEST = 100;
        private List<Geofence> mGeofenceList;
        private GoogleApiClient mGoogleApiClient;
        public static final String TAG = "Activity";
        LocationRequest mLocationRequest;
        double currentLatitude =12.9141 , currentLongitude = 77.6233;
        Boolean locationFound;
        protected LocationManager locationManager;
        protected LocationListener locationListener;

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

            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);

            if (savedInstanceState == null) {

                mGeofenceList = new ArrayList<Geofence>();

                int resp = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
                if (resp == ConnectionResult.SUCCESS) {

                    initGoogleAPIClient();

                    createGeofences(currentLatitude, currentLongitude);

                } else {
                    Log.e(TAG, "Your Device doesn't support Google Play Services.");
                }

                // Create the LocationRequest object
                mLocationRequest = LocationRequest.create()
                        .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                        .setInterval(1 * 1000)        // 10 seconds, in milliseconds
                        .setFastestInterval(1 * 1000); // 1 second, in milliseconds

            }

        }

        public void initGoogleAPIClient() {
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addApi(LocationServices.API)
                    .addConnectionCallbacks(connectionAddListener)
                    .addOnConnectionFailedListener(connectionFailedListener)
                    .build();
            mGoogleApiClient.connect();
        }

        private GoogleApiClient.ConnectionCallbacks connectionAddListener =
                new GoogleApiClient.ConnectionCallbacks() {
                    @Override
                    public void onConnected(Bundle bundle) {
                        Log.i(TAG, "onConnected");

                        Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);

                        if (location == null) {
                            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, MainActivity.this);

                        } else {
                            //If everything went fine lets get latitude and longitude
                            currentLatitude = location.getLatitude();
                            currentLongitude = location.getLongitude();

                            Log.i(TAG, currentLatitude + " WORKS " + currentLongitude);

                            //createGeofences(currentLatitude, currentLongitude);
                            //registerGeofences(mGeofenceList);
                        }

                        try{
                            LocationServices.GeofencingApi.addGeofences(
                                    mGoogleApiClient,
                                    getGeofencingRequest(),
                                    getGeofencePendingIntent()
                            ).setResultCallback(new ResultCallback<Status>() {

                                @Override
                                public void onResult(Status status) {
                                    if (status.isSuccess()) {
                                        Log.i(TAG, "Saving Geofence");

                                    } else {
                                        Log.e(TAG, "Registering geofence failed: " + status.getStatusMessage() +
                                                " : " + status.getStatusCode());
                                    }
                                }
                            });

                        } catch (SecurityException securityException) {
                            // Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
                            Log.e(TAG, "Error");
                        }
                    }

                    @Override
                    public void onConnectionSuspended(int i) {

                        Log.e(TAG, "onConnectionSuspended");

                    }
                };

        private GoogleApiClient.OnConnectionFailedListener connectionFailedListener =
                new GoogleApiClient.OnConnectionFailedListener() {
                    @Override
                    public void onConnectionFailed(ConnectionResult connectionResult) {
                        Log.e(TAG, "onConnectionFailed");
                    }
                };

        /**
         * Create a Geofence list
         */
        public void createGeofences(double latitude, double longitude) {
            String id = UUID.randomUUID().toString();
            Geofence fence = new Geofence.Builder()
                    .setRequestId(id)
                    .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
                    .setCircularRegion(latitude, longitude, 200)
                    .setExpirationDuration(Geofence.NEVER_EXPIRE)
                    .build();
            mGeofenceList.add(fence);
        }

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

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

        @Override
        public void onLocationChanged(Location location) {
            currentLatitude = location.getLatitude();
            currentLongitude = location.getLongitude();
            Log.i(TAG, "onLocationChanged");
        }

    }

GeoTransitionsIntentservices.java

    import android.app.IntentService;
    import android.app.Notification;
    import android.app.NotificationManager;
    import android.app.PendingIntent;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Build;
    import android.support.v4.app.NotificationCompat;
    import android.util.Log;

    import com.google.android.gms.location.Geofence;
    import com.google.android.gms.location.GeofencingEvent;

    public class GeofenceTransitionsIntentService extends IntentService {

        private static final String TAG = "GeofenceTransitions";

        public GeofenceTransitionsIntentService() {
            super("GeofenceTransitionsIntentService");
        }

        @Override
        protected void onHandleIntent(Intent intent) {

            Log.i(TAG, "onHandleIntent");

            GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
            if (geofencingEvent.hasError()) {
                //String errorMessage = GeofenceErrorMessages.getErrorString(this,
                //      geofencingEvent.getErrorCode());
                Log.e(TAG, "Goefencing Error " + geofencingEvent.getErrorCode());
                return;
            }

            // Get the transition type.
            int geofenceTransition = geofencingEvent.getGeofenceTransition();

            Log.i(TAG, "geofenceTransition = " + geofenceTransition + " Enter : " + Geofence.GEOFENCE_TRANSITION_ENTER + "Exit : " + Geofence.GEOFENCE_TRANSITION_EXIT);
            if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER || geofenceTransition == Geofence.GEOFENCE_TRANSITION_DWELL){

                showNotification("Entered the location", "Entered the Location");
            }
            else if(geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
                Log.i(TAG, "Showing Notification...");

                showNotification("Exited", "Exited the Location");
            } else {
                // Log the error.
                showNotification("Error", "Error");
                Log.e(TAG, "Error ");
            }
        }

        public void showNotification(String text, String bigText) {

            // 1. Create a NotificationManager
            NotificationManager notificationManager =
                    (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);

            // 2. Create a PendingIntent for AllGeofencesActivity
            Intent intent = new Intent(this, MainActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            PendingIntent pendingNotificationIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

            // 3. Create and send a notification
            Notification notification = new NotificationCompat.Builder(this)
                    .setSmallIcon(R.mipmap.ic_launcher)

                    .setContentTitle("Geofence Monitor")

                    .setContentText(text)
                    .setContentIntent(pendingNotificationIntent)
                    .setStyle(new NotificationCompat.BigTextStyle().bigText(bigText))
                    .setPriority(NotificationCompat.PRIORITY_HIGH)
                    .setAutoCancel(true)
                    .build();
            notificationManager.notify(0, notification);

            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                new NotificationCompat.Builder(this).setSmallIcon(R.mipmap.ic_launcher);
            } else {
                new NotificationCompat.Builder(this) .setSmallIcon(R.mipmap.ic_launcher);
            }

        }
    }

我想在用户退出该区域时实现停留。我已经开发了当用户退出和进入该区域时的地理围栏通知,现在我想实现它必须在一段时间内和退出后进行监控。

它应该生成 toast 消息,如果我执行,我会收到错误消息。

在你的IntentService中这样使用toaster,不会报错

 private void sendNotification(String notificationDetails) {

        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(getApplicationContext(), "here is your toast msg", Toast.LENGTH_LONG).show();
            }
        });
        // 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.drawable.ic_launcher)
                // In a real app, you may want to use a library like Volley
                // to decode the Bitmap.
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),
                        R.drawable.ic_launcher))
                .setColor(Color.RED)
                .setContentTitle(notificationDetails)
                .setContentText(getString(R.string.geofence_transition_notification_text))
                .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());
    } 

并且在

      @Override
    protected void onHandleIntent(Intent intent) {
 // Get the transition type.
        int geofenceTransition = geofencingEvent.getGeofenceTransition();

        // Test that the reported transition was of interest.
        if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT){
             sendNotification("your notification details");
             sendAPICall("some token","body","my call");
        } 
}

//// Api 呼叫

public void sendAPICall(final String reg_token, final  String body, final String title) {
        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                try {
                    OkHttpClient client = new OkHttpClient();
                    JSONObject json = new JSONObject();
                    JSONObject dataJson = new JSONObject();
                    dataJson.put("body", body);
                    dataJson.put("title", title);
                    json.put("notification", dataJson);
                    json.put("to", reg_token);
                    RequestBody body = RequestBody.create(JSON, json.toString());
                    Request request = new Request.Builder()
                            .header("Authorization", "key=" + Constants.GCM_AUTH_KEY)
                            .url("http://learnologic.com/send")
                            .post(body)
                            .build();
                    okhttp3.Response response = client.newCall(request).execute();
                    String finalResponse = response.body().string();
                    Logger.showDebugLog(finalResponse);
                } catch (Exception e) {
                    Logger.showErrorLog(e.toString());
                }
                return null;
            }
        }.execute();

    }

// 停止监控地理围栏

public void stopMonitoringGeofences() {
        if (!mGoogleApiClient.isConnected()) {
            Toast.makeText(this, getString(R.string.not_connected), Toast.LENGTH_SHORT).show();
            return;
        }
        try {
            // Remove geofences.
            LocationServices.GeofencingApi.removeGeofences(
                    mGoogleApiClient,
                    // This is the same pending intent that was used in addGeofences().
                    getGeofencePendingIntent()
            ).setResultCallback(this); // Result processed in onResult().
        } catch (SecurityException securityException) {
            // Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
            logSecurityException(securityException);
        }
    }

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