地理围栏通知不适用于过渡

时间:2017-07-08 17:20:27

标签: android notifications geofencing

我正在尝试实施Geofencing通知,但它们无法正常工作,请帮我确定原因: 这是我的代码:

这是我的MainActivity:

public class MainActivity extends AppCompatActivity
        implements
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        LocationListener,
        OnMapReadyCallback,
        GoogleMap.OnMapClickListener,
        GoogleMap.OnMarkerClickListener,
        ResultCallback<Status> {

private static final String TAG = MainActivity.class.getSimpleName();

private GoogleMap map;
private GoogleApiClient googleApiClient;
private Location lastLocation;

private TextView textLat, textLong;

private MapFragment mapFragment;

private static final String NOTIFICATION_MSG = "NOTIFICATION MSG";
// Create a Intent send by the notification
public static Intent makeNotificationIntent(Context context, String msg) {
    Intent intent = new Intent( context, MainActivity.class );
    intent.putExtra( NOTIFICATION_MSG, msg );
    return intent;
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textLat = (TextView) findViewById(R.id.lat);
    textLong = (TextView) findViewById(R.id.lon);

    // initialize GoogleMaps
    initGMaps();

    // create GoogleApiClient
    createGoogleApi();
}

// Create GoogleApiClient instance
private void createGoogleApi() {
    Log.d(TAG, "createGoogleApi()");
    if ( googleApiClient == null ) {
        googleApiClient = new GoogleApiClient.Builder( this )
                .addConnectionCallbacks( this )
                .addOnConnectionFailedListener( this )
                .addApi( LocationServices.API )
                .build();
    }
}

@Override
protected void onStart() {
    super.onStart();

    // Call GoogleApiClient connection when starting the Activity
    googleApiClient.connect();
}

@Override
protected void onStop() {
    super.onStop();

    // Disconnect GoogleApiClient when stopping Activity
    googleApiClient.disconnect();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate( R.menu.main_menu, menu );
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch ( item.getItemId() ) {
        case R.id.geofence: {
            startGeofence();
            return true;
        }
        case R.id.clear: {
            clearGeofence();
            return true;
        }
    }
    return super.onOptionsItemSelected(item);
}

private final int REQ_PERMISSION = 999;

// Check for permission to access Location
private boolean checkPermission() {
    Log.d(TAG, "checkPermission()");
    // Ask for permission if it wasn't granted yet
    return (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
            == PackageManager.PERMISSION_GRANTED );
}

// Asks for permission
private void askPermission() {
    Log.d(TAG, "askPermission()");
    ActivityCompat.requestPermissions(
            this,
            new String[] { Manifest.permission.ACCESS_FINE_LOCATION },
            REQ_PERMISSION
    );
}

// Verify user's response of the permission requested
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    Log.d(TAG, "onRequestPermissionsResult()");
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch ( requestCode ) {
        case REQ_PERMISSION: {
            if ( grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED ){
                // Permission granted
                getLastKnownLocation();

            } else {
                // Permission denied
                permissionsDenied();
            }
            break;
        }
    }
}

// App cannot work without the permissions
private void permissionsDenied() {
    Log.w(TAG, "permissionsDenied()");
    // TODO close app and warn user
}

// Initialize GoogleMaps
private void initGMaps(){
    mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
}

// Callback called when Map is ready
@Override
public void onMapReady(GoogleMap googleMap) {
    Log.d(TAG, "onMapReady()");
    map = googleMap;
    map.setOnMapClickListener(this);
    map.setOnMarkerClickListener(this);
}

@Override
public void onMapClick(LatLng latLng) {
    Log.d(TAG, "onMapClick("+latLng +")");
    markerForGeofence(latLng);
}

@Override
public boolean onMarkerClick(Marker marker) {
    Log.d(TAG, "onMarkerClickListener: " + marker.getPosition() );
    return false;
}

private LocationRequest locationRequest;
// Defined in mili seconds.
// This number in extremely low, and should be used only for debug
private final int UPDATE_INTERVAL =  1000;
private final int FASTEST_INTERVAL = 900;

// Start location Updates
private void startLocationUpdates(){
    Log.i(TAG, "startLocationUpdates()");
    locationRequest = LocationRequest.create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setInterval(UPDATE_INTERVAL)
            .setFastestInterval(FASTEST_INTERVAL);

    if ( checkPermission() )
        LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}

@Override
public void onLocationChanged(Location location) {
    Log.d(TAG, "onLocationChanged ["+location+"]");
    lastLocation = location;
    writeActualLocation(location);
}

// GoogleApiClient.ConnectionCallbacks connected
@Override
public void onConnected(@Nullable Bundle bundle) {
    Log.i(TAG, "onConnected()");
    getLastKnownLocation();
    recoverGeofenceMarker();
}

// GoogleApiClient.ConnectionCallbacks suspended
@Override
public void onConnectionSuspended(int i) {
    Log.w(TAG, "onConnectionSuspended()");
}

// GoogleApiClient.OnConnectionFailedListener fail
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    Log.w(TAG, "onConnectionFailed()");
}

// Get last known location
private void getLastKnownLocation() {
    Log.d(TAG, "getLastKnownLocation()");
    if ( checkPermission() ) {
        lastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
        if ( lastLocation != null ) {
            Log.i(TAG, "LasKnown location. " +
                    "Long: " + lastLocation.getLongitude() +
                    " | Lat: " + lastLocation.getLatitude());
            writeLastLocation();
            startLocationUpdates();
        } else {
            Log.w(TAG, "No location retrieved yet");
            startLocationUpdates();
        }
    }
    else askPermission();
}

private void writeActualLocation(Location location) {
    textLat.setText( "Lat: " + location.getLatitude() );
    textLong.setText( "Long: " + location.getLongitude() );

    markerLocation(new LatLng(location.getLatitude(), location.getLongitude()));
}

private void writeLastLocation() {
    writeActualLocation(lastLocation);
}

private Marker locationMarker;
private void markerLocation(LatLng latLng) {
    Log.i(TAG, "markerLocation("+latLng+")");
    String title = latLng.latitude + ", " + latLng.longitude;
    MarkerOptions markerOptions = new MarkerOptions()
            .position(latLng)
            .title(title);
    if ( map!=null ) {
        if ( locationMarker != null )
            locationMarker.remove();
        locationMarker = map.addMarker(markerOptions);
        float zoom = 14f;
        CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, zoom);
        map.animateCamera(cameraUpdate);
    }
}


private Marker geoFenceMarker;
private void markerForGeofence(LatLng latLng) {
    Log.i(TAG, "markerForGeofence("+latLng+")");
    String title = latLng.latitude + ", " + latLng.longitude;
    // Define marker options
    MarkerOptions markerOptions = new MarkerOptions()
            .position(latLng)
            .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE))
            .title(title);
    if ( map!=null ) {
        // Remove last geoFenceMarker
        if (geoFenceMarker != null)
            geoFenceMarker.remove();

        geoFenceMarker = map.addMarker(markerOptions);

    }
}

// Start Geofence creation process
private void startGeofence() {
    Log.i(TAG, "startGeofence()");
    if( geoFenceMarker != null ) {
        Geofence geofence = createGeofence( geoFenceMarker.getPosition(), GEOFENCE_RADIUS );
        GeofencingRequest geofenceRequest = createGeofenceRequest( geofence );
        addGeofence( geofenceRequest );
    } else {
        Log.e(TAG, "Geofence marker is null");
    }
}

private static final long GEO_DURATION = 60 * 60 * 1000;
private static final String GEOFENCE_REQ_ID = "My Geofence";
private static final float GEOFENCE_RADIUS = 25.0f; // in meters

// Create a Geofence
private Geofence createGeofence( LatLng latLng, float radius ) {
    Log.d(TAG, "createGeofence");
    return new Geofence.Builder()
            .setRequestId(GEOFENCE_REQ_ID)
            .setCircularRegion( latLng.latitude, latLng.longitude, radius)
            .setExpirationDuration( GEO_DURATION )
            .setTransitionTypes( Geofence.GEOFENCE_TRANSITION_ENTER
                    | Geofence.GEOFENCE_TRANSITION_EXIT )
            .build();
}

// Create a Geofence Request
private GeofencingRequest createGeofenceRequest( Geofence geofence ) {
    Log.d(TAG, "createGeofenceRequest");
    return new GeofencingRequest.Builder()
            .setInitialTrigger( GeofencingRequest.INITIAL_TRIGGER_ENTER )
            .addGeofence( geofence )
            .build();
}

private PendingIntent geoFencePendingIntent;
private final int GEOFENCE_REQ_CODE = 0;
private PendingIntent createGeofencePendingIntent() {
    Log.d(TAG, "createGeofencePendingIntent");
    if ( geoFencePendingIntent != null )
        return geoFencePendingIntent;

    Intent intent = new Intent( this, GeofenceTransitionService.class);
    return PendingIntent.getService(
            this, GEOFENCE_REQ_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT );
}

// Add the created GeofenceRequest to the device's monitoring list
private void addGeofence(GeofencingRequest request) {
    Log.d(TAG, "addGeofence");
    if (checkPermission())
        LocationServices.GeofencingApi.addGeofences(
                googleApiClient,
                request,
                createGeofencePendingIntent()
        ).setResultCallback(this);
}

@Override
public void onResult(@NonNull Status status) {
    Log.i(TAG, "onResult: " + status);
    if ( status.isSuccess() ) {
        saveGeofence();
        drawGeofence();
    } else {
        // inform about fail
    }
}

// Draw Geofence circle on GoogleMap
private Circle geoFenceLimits;
private void drawGeofence() {
    Log.d(TAG, "drawGeofence()");

    if ( geoFenceLimits != null )
        geoFenceLimits.remove();

    CircleOptions circleOptions = new CircleOptions()
            .center( geoFenceMarker.getPosition())
            .strokeColor(Color.argb(50, 70,70,70))
            .fillColor( Color.argb(100, 150,150,150) )
            .radius( GEOFENCE_RADIUS );
    geoFenceLimits = map.addCircle( circleOptions );
}

private final String KEY_GEOFENCE_LAT = "GEOFENCE LATITUDE";
private final String KEY_GEOFENCE_LON = "GEOFENCE LONGITUDE";

// Saving GeoFence marker with prefs mng
private void saveGeofence() {
    Log.d(TAG, "saveGeofence()");
    SharedPreferences sharedPref = getPreferences( Context.MODE_PRIVATE );
    SharedPreferences.Editor editor = sharedPref.edit();

    editor.putLong( KEY_GEOFENCE_LAT, Double.doubleToRawLongBits( geoFenceMarker.getPosition().latitude ));
    editor.putLong( KEY_GEOFENCE_LON, Double.doubleToRawLongBits( geoFenceMarker.getPosition().longitude ));
    editor.apply();
}

// Recovering last Geofence marker
private void recoverGeofenceMarker() {
    Log.d(TAG, "recoverGeofenceMarker");
    SharedPreferences sharedPref = getPreferences( Context.MODE_PRIVATE );

    if ( sharedPref.contains( KEY_GEOFENCE_LAT ) && sharedPref.contains( KEY_GEOFENCE_LON )) {
        double lat = Double.longBitsToDouble( sharedPref.getLong( KEY_GEOFENCE_LAT, -1 ));
        double lon = Double.longBitsToDouble( sharedPref.getLong( KEY_GEOFENCE_LON, -1 ));
        LatLng latLng = new LatLng( lat, lon );
        markerForGeofence(latLng);
        drawGeofence();
    }
}

// Clear Geofence
private void clearGeofence() {
    Log.d(TAG, "clearGeofence()");
    LocationServices.GeofencingApi.removeGeofences(
            googleApiClient,
            createGeofencePendingIntent()
    ).setResultCallback(new ResultCallback<Status>() {
        @Override
        public void onResult(@NonNull Status status) {
            if ( status.isSuccess() ) {
                // remove drawing
                removeGeofenceDraw();
            }
        }
    });
}

private void removeGeofenceDraw() {
    Log.d(TAG, "removeGeofenceDraw()");
    if ( geoFenceMarker != null)
        geoFenceMarker.remove();
    if ( geoFenceLimits != null )
        geoFenceLimits.remove();
}

}

这是转换和通知的服务类:

public class GeofenceTransitionService extends IntentService {

private static final String TAG = GeofenceTransitionService.class.getSimpleName();

public static final int GEOFENCE_NOTIFICATION_ID = 0;

public GeofenceTransitionService() {
    super(TAG);
}



@Override
protected void onHandleIntent(Intent intent) {
    GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
    // Handling errors
    if ( geofencingEvent.hasError() ) {
        String errorMsg = getErrorString(geofencingEvent.getErrorCode() );
        Log.e( TAG, errorMsg );
        return;
    }

    int geoFenceTransition = geofencingEvent.getGeofenceTransition();
    // Check if the transition type is of interest

    Log.d(TAG,String.valueOf(geoFenceTransition));
    Toast.makeText(this, String.valueOf(geoFenceTransition), Toast.LENGTH_SHORT).show();
    if ( geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
            geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT ) {
        // Get the geofence that were triggered
        List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();

        String geofenceTransitionDetails = getGeofenceTransitionDetails(geoFenceTransition, triggeringGeofences );

        // Send notification details as a String
        sendNotification( geofenceTransitionDetails );
    }
}


private String getGeofenceTransitionDetails(int geoFenceTransition, List<Geofence> triggeringGeofences) {
    // get the ID of each geofence triggered
    ArrayList<String> triggeringGeofencesList = new ArrayList<>();
    for ( Geofence geofence : triggeringGeofences ) {
        triggeringGeofencesList.add( geofence.getRequestId() );
    }

    String status = null;
    if ( geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER )

        status = "Entering ";

    else if ( geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT )
        status = "Exiting ";
    return status + TextUtils.join( ", ", triggeringGeofencesList);
}

private void sendNotification( String msg ) {
    Toast.makeText(this, "msg", Toast.LENGTH_SHORT).show();
    Log.i(TAG, "sendNotification: " + msg );

    // Intent to start the main Activity
    Intent notificationIntent = MainActivity.makeNotificationIntent(
            getApplicationContext(), msg
    );

    TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
    stackBuilder.addParentStack(MainActivity.class);
    stackBuilder.addNextIntent(notificationIntent);
    PendingIntent notificationPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);


    // Creating and sending Notification
    NotificationManager notificatioMng =
            (NotificationManager) getSystemService( Context.NOTIFICATION_SERVICE );
    notificatioMng.notify(
            GEOFENCE_NOTIFICATION_ID,
            createNotification(msg, notificationPendingIntent));

}

// Create notification
private Notification createNotification(String msg, PendingIntent notificationPendingIntent) {
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
    notificationBuilder
            .setSmallIcon(R.drawable.ic_action_location)
            .setColor(Color.RED)
            .setContentTitle(msg)
            .setContentText("Geofence Notification!")
            .setContentIntent(notificationPendingIntent)
            .setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_SOUND)
            .setAutoCancel(true);
    return notificationBuilder.build();
}


private static String getErrorString(int errorCode) {
    switch (errorCode) {
        case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE:
            return "GeoFence not available";
        case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES:
            return "Too many GeoFences";
        case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS:
            return "Too many pending intents";
        default:
            return "Unknown error.";
    }
}
}

提前致谢。

0 个答案:

没有答案