百度地图- - - 鹰眼轨迹- - - 地理围栏

本文介绍了一种基于Android平台的地理围栏服务实现方案。通过点击地图选择围栏中心点,创建圆形地理围栏,并实现了服务端和客户端的围栏状态监测及报警功能。

    地理围栏是个服务,所以在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;
				}
				
			}
		};
	};

 

转载于:https://my.oschina.net/fbf8866/blog/853398

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值