地理围栏是个服务,所以在manifest中要添加
<!-- 地理围栏的服务 -->
<service
android:name="com.baidu.trackshow.MonitorService"
android:enabled="true"
android:exported="true" >
</service>
先说下大致思路:
点击button,显示出popuwindow,在这个popuwindow中有创建围栏的按钮,点击创建围栏button前,先点击地图,获取到经纬度,以点击的点为圆心,画圆形围栏,然后再把实时定位开启,点击查看被监控者状态button,根据实时定位的经纬度,来判断被监控者是在围栏内还是在围栏外
cpw = new CustomPopWindow(MainActivity.this);
case R.id.btn_geofence:
cpw.showPopupWindow(btn_geofence);
/**
* 自定义的popuwindow
* @author Administrator
*/
public class CustomPopWindow extends PopupWindow implements OnClickListener {
private static final int CHECKSTATUS = 1 ;
private Context context;
private View view;
private MyApplication mApp;
private GeoFence geoFence;
private LatLng poiLatLng;
public static Button custom_popu_btn_server_status;
private Button custom_popu_btn_customer_status;
private Timer mTimer;
private TimerTask mTimerTask;
/**
* 用于记录服务端状态的按钮是否开启
*/
public static boolean flag = false;
/**
* 上一个服务端地理围栏的坐标
*/
private LatLng last;
private Handler mHandler = new Handler(){
public void handleMessage(android.os.Message msg) {
if (null != msg) {
switch (msg.what) {
case CHECKSTATUS:
geoFence.monitoredStatus();
break;
default:
break;
}
}
};
};
public CustomPopWindow(Context context){
this.context = context;
view = LayoutInflater.from(context).inflate(R.layout.custom_view_popu,null);
setContentView(view);
mApp = (MyApplication) context.getApplicationContext();
init();
initView();
geoFence = new GeoFence(context,mApp);
}
private void init() {
// 设置SelectPicPopupWindow弹出窗体的宽
this.setWidth(LinearLayout.LayoutParams.WRAP_CONTENT);
// 设置SelectPicPopupWindow弹出窗体的高, 宽和高必须设置,否则不显示popuwindow
this.setHeight(LinearLayout.LayoutParams.WRAP_CONTENT);
// 设置popuwindow所在的窗体可以点击
this.setFocusable(false);
// 刷新状态
this.update();
// 点back键和其他地方使其消失,设置了这个才能触发OnDismisslistener ,设置其他控件变化等操作
this.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
this.setOutsideTouchable(false);
// 设置SelectPicPopupWindow弹出窗体动画效果
this.setAnimationStyle(R.style.AnimTools);
}
private void initView() {
Button custom_popu_btn_server = (Button) view.findViewById(R.id.custom_popu_btn_server);
Button custom_popu_btn_server_delete = (Button) view.findViewById(R.id.custom_popu_btn_server_delete);
custom_popu_btn_server_status = (Button) view.findViewById(R.id.custom_popu_btn_server_status);
Button custom_popu_btn_customer = (Button) view.findViewById(R.id.custom_popu_btn_customer);
custom_popu_btn_customer_status = (Button) view.findViewById(R.id.custom_popu_btn_customer_status);
custom_popu_btn_server.setOnClickListener(this);
custom_popu_btn_server_delete.setOnClickListener(this);
custom_popu_btn_server_status.setOnClickListener(this);
custom_popu_btn_customer.setOnClickListener(this);
custom_popu_btn_customer_status.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.custom_popu_btn_server: //创建服务端的button
//先获取到点击地图的poi时候的LatLng 然后传递到创建服务端围栏中
poiLatLng = MainActivity.poiLatLng;
if (GeoFence.serverFenceId>0) {
//删除上一个地理围栏
geoFence.deleteServerFence(GeoFence.serverFenceId);
}
if (null == poiLatLng || "".equals(poiLatLng) || poiLatLng == last) {
MyToastUtils.show(context, "请点击地图,选取围栏中心点");
return;
}
geoFence.creatServerFence(poiLatLng);
//为了 防止同一个坐标 一直创建围栏
last = poiLatLng;
custom_popu_btn_server_status.setVisibility(View.VISIBLE);
//这时候如果报警音乐响着, 但是又创建了个新的围栏, 就把报警关掉
closeMusic();
break;
case R.id.custom_popu_btn_server_status: //查看服务端围栏的状态
if (MainActivity.isLoca) {
if (flag) {
flag = false;
cancelTimer();
custom_popu_btn_server_status.setText("查看服务端状态");
//如果报警音乐开着, 就关闭
closeMusic();
}else{
flag = true;
startTimer();
custom_popu_btn_server_status.setText("已开启查询端状态按钮");
}
}else{
MyToastUtils.show(context, "请先开启实时定位");
}
break;
case R.id.custom_popu_btn_server_delete: //删除围栏
break;
case R.id.custom_popu_btn_customer: //客户端(本地)围栏的按钮
geoFence.createLocalCircularFence();
custom_popu_btn_customer_status.setVisibility(View.VISIBLE);
break;
case R.id.custom_popu_btn_customer_status:
Log.i("哈哈", "客户端状态查询点击");
break;
default:
break;
}
}
/**
* 如果报警音乐开着 ,关闭音乐
*/
private void closeMusic() {
if (null !=GeoFence.mPlayer) {
if (GeoFence.mPlayer.isPlaying()) {
GeoFence.mPlayer.stop();
try {
GeoFence.mPlayer.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void startTimer(){
if (null == mTimer) {
mTimer = new Timer();
}
if (null != mTimerTask) {
mTimerTask = null;
}
mTimerTask = new TimerTask() {
@Override
public void run() {
mHandler.obtainMessage(CHECKSTATUS).sendToTarget();
}
};
mTimer.schedule(mTimerTask, 100,30*1000);
}
public void cancelTimer(){
if (null != mTimer) {
mTimer.cancel();
mTimer = null;
}
if (null != mTimerTask) {
mTimerTask.cancel();
mTimerTask = null;
}
}
/**
* 显示popu
* @param parent
*/
public void showPopupWindow(View parent) {
if (!this.isShowing()) {
// 以下拉方式显示popupwindow
this.showAsDropDown(parent, parent.getLayoutParams().width , parent.getLayoutParams().height);
// this.showAsDropDown(parent);
} else {
this.dismiss();
if (!flag) {
custom_popu_btn_server_status.setVisibility(View.GONE);
}
}
}
}
public GeoFence(Context mContext,MyApplication mApp){
this.mContext = mContext;
this.mApp = mApp;
initGeoFence();
}
private void initGeoFence() {
geoListener = new OnGeoFenceListener(){
@Override
public void onRequestFailedCallback(String message) {
// TODO Auto-generated method stub
}
/**
* 创建服务端圆形围栏的回调
*/
@Override
public void onCreateCircularFenceCallback(String message) {
super.onCreateCircularFenceCallback(message);
Log.i(TAG, "创建服务端圆形围栏回调信息:"+message);
try {
JSONObject object = new JSONObject(message);
if (null != object) {
if (0 ==object.getInt("status")) {
serverFenceId = object.getInt("fence_id");
mHandler.obtainMessage(SERVERID, serverFenceId).sendToTarget();
overlayOptions = new CircleOptions()
.fillColor(Color.parseColor("#77D7D7D7"))
.center(locaPoiLatLng)
.stroke(new Stroke(10, Color.BLUE))
.radius(500);
if (null != overlayOptions) {
mHandler.obtainMessage(ADDMARKER).sendToTarget();
}
}else {
String msg = (String) object.get("message");
mHandler.obtainMessage(SHOWMESSAGE,msg).sendToTarget();
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* 创建客户端圆形围栏回调
*/
@Override
public void onCreateLocalFenceCallback(CreateLocalFenceResult message) {
super.onCreateLocalFenceCallback(message);
Log.i(TAG, message.getMessage()+"---创建客户端圆形围栏回调---"+message.toString());
}
/**
* 查询本地围栏状态的回调(客户端状态 回调)
*/
@Override
public void onQueryLocalFenceStatusCallback(String arg0) {
super.onQueryLocalFenceStatusCallback(arg0);
Log.i(TAG, "客户端状态回调---"+arg0);
}
/**
* 更新圆形围栏的回调
*/
@Override
public void onUpdateCircularFenceCallback(String message) {
super.onUpdateCircularFenceCallback(message);
}
/**
* 删除围栏的回调
*/
@Override
public void onDeleteFenceCallback(String message) {
super.onDeleteFenceCallback(message);
Log.i(TAG, "删除---"+message);
}
/**
* 查询围栏列表的回调
*/
@Override
public void onQueryFenceListCallback(String message) {
super.onQueryFenceListCallback(message);
try {
JSONObject obj = new JSONObject(message);
if (null != obj && obj.getInt("status") == 0) {
if (obj.has("size") && obj.getInt("size") != 0) {
JSONArray array = obj.getJSONArray("fences");
JSONObject object = array.getJSONObject(0);
int shape = object.getInt("shape");
if (1 == shape) {
JSONObject center = object.getJSONObject("center");
double latitude = center.getDouble("latitude");
double longitude = center.getDouble("longitude");
LatLng latLng = new LatLng(latitude, longitude);
int radius = (int) object.getDouble("radius");
overlayOptions = new CircleOptions()
.fillColor(Color.parseColor("#77D7D7D7"))
.center(latLng)
.stroke(new Stroke(10, Color.BLUE))
.radius(radius);
if (null != overlayOptions) {
mHandler.obtainMessage(ADDMARKER).sendToTarget();
}
}
}else{
Log.i(TAG,"查询无此ID");
}
}
Log.i(TAG, "查询围栏"+obj.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* 查询监控服务端对象状态的回调
*/
@Override
public void onQueryMonitoredStatusCallback(String message) {
super.onQueryMonitoredStatusCallback(message);
try {
JSONObject object = new JSONObject(message);
Log.i(TAG, "服务端状态---"+message);
String status = null;
if (null != object && object.getInt("status") == 0) {
int size = object.getInt("size");
int mStatus = 0;
for (int i = 0; i < size; i++) {
JSONArray array = object.getJSONArray("monitored_person_statuses");
JSONObject obj = array.getJSONObject(0);
String mPerson = obj.getString("monitored_person");
mStatus = obj.getInt("monitored_status");
if (1 == mStatus) {
status = "监控对象[ " + mPerson + " ]在围栏内";
Log.i(TAG, "状态---"+status);
} else if (2 == mStatus) {
status = "监控对象[ " + mPerson + " ]在围栏外";
Log.i(TAG, "状态---"+status);
} else {
status = "监控对象[ " + mPerson + " ]状态未知";
Log.i(TAG, "状态---"+status);
}
}
mHandler.obtainMessage(SHOWMESSAGE,status).sendToTarget();
mHandler.obtainMessage(PLAYMUSIC,mStatus).sendToTarget();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* 查询历史报警的回调
*/
@Override
public void onQueryHistoryAlarmCallback(String message) {
super.onQueryHistoryAlarmCallback(message);
}
};
}
/**
* 这个是创建服务端的圆形围栏,也就是监控者和被监控者是同一个人
* 用于情景 : 开车司机到到指定地方
*/
public void creatServerFence(LatLng poiLatLng){
//轨迹服务ID
int serviceID = mApp.getServiceId();
//创建者(entity标识)
String creator = mApp.getName();
//围栏名称 (最长128个字节)
String fenceName = "test";
//围栏描述 (最长1024个字节)
String fenceDesc = "test";
//被监控对象列表 (每个监控对象都是轨迹服务中的entityName,使用英文逗号”,”分割)
String monitoredPersons = mApp.getName();
// String monitoredPersons = "hgy";
//观察者列表(多个entityName,以英文逗号"," 分割)
String observers = mApp.getName();
//生效时间列表(一天中的几点几分到 几点几分生效。多个时间段使用分号”;”分隔。比如:“0820,0930;1030,1130”)
String validTimes = "0600,2300";
//生效周期 (参数validTimes是否周期性生效,可以使用如下数值:1:不重复,2:工作日循环,3:周末循环,4:每天循环,5:自定义。当为5时,需要定义validDays,标识在周几生效)
int validCycle = 4;
//围栏生效日期 (当validCycle为1时必选,例如:"20150908")
String validDate = "";
//生效日期列表 (1到7,分别表示周一到周日,格式 : "int,int…")
String validDays = "";
//坐标类型 (1:GPS经纬度,2:国测局经纬度,3:百度经纬度)
int coordType = 3;
//围栏圆心(圆心位置, 格式 : "经度,纬度")
// centers = "116.43068560351,39.929830261949";
//围栏半径(单位 : 米)
double radius = 500;
//报警条件(1:进入时触发提醒,2:离开时触发提醒,3:进入离开均触发提醒)
int alarmCondition = 3;
//如果传过来的LatLng不为空, 就赋值给要画围栏的参数中
locaPoiLatLng = poiLatLng;
double lat = poiLatLng.latitude;
double lon = poiLatLng.longitude;
String centers = lon+","+lat;
mApp.getLBSTraceClient().createCircularFence(serviceID, creator, fenceName, fenceDesc, monitoredPersons, observers, validTimes, validCycle,
validDate, validDays, coordType, centers, radius, 0, alarmCondition, geoListener);
}
/**
* 删除服务端围栏
*/
public void deleteServerFence(int fenceId) {
mApp.getLBSTraceClient().deleteFence(mApp.getServiceId(), fenceId, geoListener);
}
/**
* 监控状态(服务端围栏)
* 可以查询被监控者服务端存储的最新位置,是在围栏内或围栏外。
*/
public void monitoredStatus() {
// 围栏ID
int fenceId = GeoFence.serverFenceId;
// 监控对象列表(多个entityName,以英文逗号"," 分割)
String monitoredPersons = mApp.getName();
mApp.getLBSTraceClient().queryMonitoredStatus(mApp.getServiceId(), fenceId, monitoredPersons,
geoListener);
}
private Handler mHandler = new Handler(){
public void handleMessage(android.os.Message msg) {
if (null != msg) {
switch (msg.what) {
case ADDMARKER:
mApp.getmBaiduMap().clear();
mApp.getmBaiduMap().addOverlay(overlayOptions);
break;
case SERVERID:
int serverId = (Integer) msg.obj;
MyToastUtils.show(mContext, "创建服务端围栏编号: "+serverId);
break;
case SHOWMESSAGE:
String s = (String) msg.obj;
MyToastUtils.show(mContext, s);
break;
case PLAYMUSIC:
int status = (Integer) msg.obj;
if (1 == status) {
playMusic();
}
break;
default:
break;
}
}
};
};