您需要使用Geofences,请按照以下步骤操作,您一定会得到您想要的结果。
让我们看看它是如何工作的。
地理围栏将用户当前位置的感知与用户与可能感兴趣的位置的接近度的感知结合起来。要标记感兴趣的位置,请指定其纬度和经度。要调整该位置的接近度,请添加一个半径。 纬度、经度和半径定义地理围栏,在感兴趣的位置周围创建一个圆形区域或围栏。
您可以有多个活动的地理围栏,每个设备用户最多 100 个。
现在,让我们看看我们如何在应用程序中使用它,
设置地理围栏监控
请求地理围栏监控的第一步是请求必要的许可。要使用地理围栏,您的应用必须请求 ACCESS_FINE_LOCATION。要请求此权限,请将以下元素添加为应用清单中 <manifest> 元素的子元素:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
如果您想使用IntentService 来监听地理围栏转换,请添加一个指定服务名称的元素。此元素必须是 <application> 元素的子元素:
<application
android:allowBackup="true">
...
<service android:name=".GeofenceTransitionsIntentService"/>
<application/>
要访问位置 API,您需要创建地理围栏客户端的实例。要了解如何连接您的客户端:
private GeofencingClient mGeofencingClient;
// ...
mGeofencingClient = LocationServices.getGeofencingClient(this);
创建和添加地理围栏
注意:在单用户设备上,每个地理围栏限制为 100 个
应用程序。对于多用户设备,每个应用程序的限制为 100 个地理围栏
设备用户。
首先,使用Geofence.Builder 创建地理围栏,为地理围栏设置所需的半径、持续时间和过渡类型。例如,要填充名为 mGeofenceList 的列表对象:
mGeofenceList.add(new Geofence.Builder()
// Set the request ID of the geofence. This is a string to identify this
// geofence.
.setRequestId(entry.getKey())
.setCircularRegion(
entry.getValue().latitude,
entry.getValue().longitude,
Constants.GEOFENCE_RADIUS_IN_METERS
)
.setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
Geofence.GEOFENCE_TRANSITION_EXIT)
.build());
指定地理围栏和初始触发器
以下 sn-p 使用 GeofencingRequest 类及其嵌套的 GeofencingRequestBuilder 类来指定要监控的地理围栏并设置相关地理围栏事件的触发方式:
private GeofencingRequest getGeofencingRequest() {
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
builder.addGeofences(mGeofenceList);
return builder.build();
}
定义地理围栏转换的意图
从定位服务发送的Intent 可以在您的应用中触发各种操作,但您不应该让它启动一个活动或片段,因为组件应该只在响应用户操作时才可见。在许多情况下,IntentService 是处理意图的好方法。 IntentService 可以发布通知、执行长时间运行的后台工作、向其他服务发送意图或发送广播意图。下面的 sn-p 展示了如何定义一个以IntentService 开头的PendingIntent:
public class MainActivity extends AppCompatActivity {
// ...
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().
mGeofencePendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.
FLAG_UPDATE_CURRENT);
return mGeofencePendingIntent;
}
添加地理围栏
要添加地理围栏,请使用GeofencingClient.addGeofences() 方法。提供GeofencingRequest 对象和PendingIntent。下面的 sn -p 演示了处理结果:
mGeofencingClient.addGeofences(getGeofencingRequest(), getGeofencePendingIntent())
.addOnSuccessListener(this, new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
// Geofences added
// ...
}
})
.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
// Failed to add geofences
// ...
}
});
处理地理围栏过渡
注意:在 Android 8.0(API 级别 26)及更高版本上,如果应用在后台运行并监控地理围栏,则设备
每几分钟响应一次地理围栏事件。学习如何
使您的应用适应这些响应限制,请参阅后台位置
限制。
public class GeofenceTransitionsIntentService extends IntentService {
// ...
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
String errorMessage = GeofenceErrorMessages.getErrorString(this,
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(
this,
geofenceTransition,
triggeringGeofences
);
// Send notification and log the transition details.
sendNotification(geofenceTransitionDetails);
Log.i(TAG, geofenceTransitionDetails);
} else {
// Log the error.
Log.e(TAG, getString(R.string.geofence_transition_invalid_type,
geofenceTransition));
}
}
停止地理围栏监控
mGeofencingClient.removeGeofences(getGeofencePendingIntent())
.addOnSuccessListener(this, new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
// Geofences removed
// ...
}
})
.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
// Failed to remove geofences
// ...
}
});