【发布时间】:2017-08-11 11:07:35
【问题描述】:
我正在尝试使用最新版本的 GooglePlayServices 在 Android 上实施地理围栏。
我决定使用地理围栏,因为我只需要在用户移动时知道用户的位置,而且我需要非常低功耗的东西,因为我的应用程序在后台 24/7 运行。
在我的代码中,如果我没有实现 LocationServices 的“requestLocationUpdates”,则不会触发地理围栏。这真的很奇怪,因为我读到通常我们不需要使用它,而且它不再是低功耗了。
是否有人使用最新的 GooglePlayService 实施地理围栏,但未实施“requestLocationUpdates”?
我的代码:
清单:
<service
android:name=".gps.GeofencingService"
android:enabled="true"
android:exported="true" />
<receiver
android:name=".gps.GeofenceReceiver"
android:exported="true"
>
<intent-filter>
<action android:name="android.location.MODE_CHANGED" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
<action android:name="android.location.PROVIDERS_CHANGED" />
</intent-filter>
</receiver>
服务:
public class GeofencingService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
//My singleton
private static GeofencingService mInstant;
public static GeofencingService getInstant(){
return mInstant;
}
@Override
public void onCreate() {
super.onCreate();
mInstant = this;
mFusedLocationClient = getFusedLocationProviderClient(this);
mGeofencingClient = LocationServices.getGeofencingClient(this);
buildGoogleApiClient();
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
public void addGeofence() {
if (mGoogleApiClient.isConnected()) {
LocationRequest mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(100); // Update location every second
//use to initiate the geofence region on my position
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (location != null) {
mGeofenceList = new ArrayList();
mGeofenceList.add(new Geofence.Builder()
// Set the request ID of the geofence. This is a string to identify this
// geofence.
.setRequestId(idGeofence)
.setCircularRegion(
location.getLatitude(),
location.getLongitude(),
Constantes.GEOFENCE_RADIUS_IN_METERS
)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_EXIT)
.build());
mGeofencingClient.addGeofences(getGeofencingRequest(), getGeofencePendingIntent())
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "Geofence added");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
// Failed to add geofences
Log.d(TAG, "Failed to add geofences");
e.printStackTrace();
}
});
//if this line is removed, geofence is not triggered anymore
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//super.onStartCommand(intent, flags, startId);
mGoogleApiClient.connect();
return START_STICKY;
}
@Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "GoogleApiClient connected");
addGeofence();
}
@Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "GoogleApiClient connection has been suspend");
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.i(TAG, "GoogleApiClient connection has failed");
}
public void getCurrentLocation() {
//mFusedLocationClient.getLastLocation().addOnSuccessListener(new OnSuccessListener<Location>() {
FusedLocationProviderClient locationClient = getFusedLocationProviderClient(this);
locationClient.getLastLocation().addOnSuccessListener(new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
// Got last known location. In some rare situations this can be null.
if (location != null) {
Log.d(TAG, location.getLatitude() + "/" + location.getLongitude());
} else {
}
}
});
}
private PendingIntent getGeofencePendingIntent() {
// Reuse the PendingIntent if we already have it.
if (mGeofencePendingIntent != null) {
return mGeofencePendingIntent;
}
//Call a BroadcastReceiver
mGeofencePendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, GeofenceReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT);
return mGeofencePendingIntent;
}
private GeofencingRequest getGeofencingRequest() {
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_EXIT);
builder.addGeofences(mGeofenceList);
return builder.build();
}
@Override
public void onLocationChanged(Location location) {
Log.d(TAG, "Location Changed : " + location.getLatitude() + "/" + location.getLongitude());
}
}
接收者:
public class GeofenceReceiver extends BroadcastReceiver {
protected static final String TAG = "GeofenceReceiver";
protected Context applicationContext;
@Override
public void onReceive(final Context context, final Intent intent) {
applicationContext = context;
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
String errorMessage = GeofenceErrorMessages.getErrorString(context, geofencingEvent.getErrorCode());
Log.e(TAG, errorMessage);
return;
}
// Get the transition type.
int geofenceTransition = geofencingEvent.getGeofenceTransition();
// Test that the reported transition was of interest.
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
// Get the geofences that were triggered. A single event can trigger
// multiple geofences.
List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
// Get the transition details as a String.
String geofenceTransitionDetails = getGeofenceTransitionDetails(geofenceTransition, triggeringGeofences);
Log.d(TAG, geofenceTransitionDetails);
Toast.makeText(context, geofenceTransitionDetails, Toast.LENGTH_LONG).show();
// Send notification and log the transition details.
sendNotification(geofenceTransitionDetails);
Log.i(TAG, geofenceTransitionDetails);
} else {
// Log the error.
Log.e(TAG, context.getString(R.string.geofence_transition_invalid_type,
geofenceTransition));
}
}
}
感谢您的帮助
【问题讨论】:
-
您是否考虑过使用 Awareness api 来完成此类任务?
-
不,这是我第一次听说这个 api!好像很给力!我会进去看看我是否可以使用它...谢谢蒂姆!
标签: android google-play-services geofencing