地理围栏是感兴趣的虚拟边界,可以将其设置为在进入或退出(或同时退出)时发出通知。 例如,当我们在附近散步或开车时,地理围栏应用程序可以提醒我们我们的孩子已经离开了先前指定的区域,或者向我们发送了优惠券(例如“向此短信发送可享受20%的折扣”优惠类型)电影院。 现在,借助新的Location API ,Google的位置算法已被重写为更准确,并大大减少了电池寿命。 只有足够的文档以及示例代码和可下载的示例应用程序( GeofenceDetection ),可以帮助我们开始创建地理围栏应用程序。 先决条件是:
- 下载Google Play服务 (通过Android的SDK Manager)并将其设置为库
- 获取Google Maps v2 API密钥,然后运行示例应用程序。 这份简短的快速入门指南可能会有所帮助
- 下载(再次通过SDK Manager) 支持库以适应较旧的Android版本。
出于实际目的,让我们从示例地理围栏应用程序( GeofenceDetection )停止的地方开始,并引入一些增强功能,使该应用程序变得像样,并通过新的Location API展示可能的示例。
1.变焦和相机位置
首先,稍微了解一下Google Maps API v2。 让我们选择缩放级别和相机角度:
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
//...
// inside class, for a given lat/lon
CameraPosition INIT =
new CameraPosition.Builder()
.target(new LatLng(lat, lon))
.zoom( 17.5F )
.bearing( 300F) // orientation
.tilt( 50F) // viewing angle
.build();
// use GooggleMap mMap to move camera into position
mMap.animateCamera( CameraUpdateFactory.newCameraPosition(INIT) );
上面的代码具有缩放级别,允许以3D形式查看建筑物。 Google Maps v2使用嵌入式系统OpenGL ( OpenGL ES v2)渲染2D和3D计算机图形。
2.选项菜单
即使我们不是“选项”菜单的忠实拥护者,在这种情况下也足够了,因为我们不希望使用过多的“触摸”功能来使地图混乱(很快就会有很多)。
![]() | ![]() |
我们可以在“普通”视图和卫星视图之间切换:
/**
* Toggle View Satellite-Normal
*/
public static void toggleView(){
mMap.setMapType( mMap.getMapType() ==
GoogleMap.MAP_TYPE_NORMAL ?
GoogleMap.MAP_TYPE_SATELLITE :
GoogleMap.MAP_TYPE_NORMAL);
}
我们还可以提供“飞行模式”,让相机滚动离开。 并不是很有用,但仍然很酷:
import com.google.android.gms.maps.GoogleMap.CancelableCallback;
//...
private static CancelableCallback callback = new CancelableCallback() {
@Override
public void onFinish() {
scroll();
}
@Override
public void onCancel() {}
};
public static void scroll() {
// we don't want to scroll too fast since
// loading new areas in map takes time
mMap.animateCamera( CameraUpdateFactory.scrollBy(10, -10),
callback ); // 10 pix
}
3.地理编码/反向地理编码
该示例在此处演示功能,并大量使用纬度/经度坐标。 但是我们需要提供一种更加用户友好的方式来与地图上的位置(例如街道地址)进行交互。 我们可以使用Android的Geocoder使用地理编码/反向地理编码将街道地址转换为坐标,反之亦然。
4.添加地理围栏
好,现在到地理围栏。 借助地理编码,我们可以向用户请求实际的物理地址,而不是坐标。 我们将在内部将该地址更改为纬度/经度对,以处理用户输入。 请注意,我们如何尽可能地使用透明的UI来增强某些可能称为用户体验的内容。 还要注意,我们提供了一个微调器,以便用户可以在预定义的值之间进行选择。 这为用户节省了一些键入操作,并且使我们不必每次都验证坐标值。
不过,如果我们希望变得更加用户友好,则可以让我们的用户通过长按地图上的一个点来预填充地址字段。 然后,我们将使用反向地理编码将坐标转换为要显示的物理地址(右下方的屏幕):
![]() | ![]() |
处理长按非常简单:
import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener;
//...
public class MainActivity extends FragmentActivity
implements OnMapLongClickListener {
//...
mMap.setOnMapLongClickListener(this);
//...
@Override
public void onMapLongClick(LatLng point) {
// reverse geocode point
}
}
示例应用程序中几乎涵盖了添加/删除地理围栏(由GeofenceRequester和GeofenceRemover类组成)。 要记住的是,添加/删除围栏的过程如下:
- 我们的应用要求连接到Google的位置服务。
- 一旦/如果连接可用,则使用PendingIntent完成添加/删除围栏的请求。
- 如果我们的应用发出的类似请求仍在进行中,则操作将失败。
- 尽管我们调用的方法(例如addGeofences() )立即返回,但是直到定位服务使用成功状态代码回调到我们的应用程序(例如OnAddGeofencesResultListener的onAddGeofencesResult() ),我们才知道请求是否成功。
- 最后,上述方法将使用广播意图将应用程序的其他组件成功/失败通知给我们。
不用说,我们几乎需要在每个步骤中进行防御性编码 。 现在,一旦添加了地理围栏,我们就可以添加一个标记(默认标记或自定义标记),然后在不同的形状(圆形,多边形等)之间进行选择以界定地理围栏。 例如,我们可以编写以下代码来添加默认标记,并在指定半径内圈围栅栏:
import com.google.android.gms.maps.model.Circle;
import com.google.android.gms.maps.model.CircleOptions;
import com.google.android.gms.maps.model.MarkerOptions;
//...
public static void addMarkerForFence(SimpleGeofence fence){
if(fence == null){
// display en error message and return
return;
}
mMap.addMarker( new MarkerOptions()
.position( new LatLng(fence.getLatitude(), fence.getLongitude()) )
.title("Fence " + fence.getId())
.snippet("Radius: " + fence.getRadius()) ).showInfoWindow();
//Instantiates a new CircleOptions object + center/radius
CircleOptions circleOptions = new CircleOptions()
.center( new LatLng(fence.getLatitude(), fence.getLongitude()) )
.radius( fence.getRadius() )
.fillColor(0x40ff0000)
.strokeColor(Color.TRANSPARENT)
.strokeWidth(2);
// Get back the mutable Circle
Circle circle = mMap.addCircle(circleOptions);
// more operations on the circle...
}
以下是产生的屏幕,其中包括“触摸以编辑”信息窗口后得到的屏幕:
![]() | ![]() |
一旦进入或退出上方的圆圈区域,示例应用程序便具有触发通知所需的全部功能。 请注意,我们如何设置标记的“信息”窗口以允许编辑地理围栏半径或完全删除地理围栏。 要实现可点击的自定义Info窗口,我们需要创建自己的InfoWindowAdapter和OnInfoWindowClickListener 。
至于通知本身,这是示例应用程序中的样子:
![]() | ![]() |
我们当然可以更改通知的外观和功能,并且……这将是另一篇文章的主题。 希望这一小节简要介绍了新的Location API可以实现的功能。 体验Android地理围栏。
翻译自: https://www.javacodegeeks.com/2013/09/android-geofencing-with-google-maps.html