高德地图实战:后台持续定位实现

最近有个项目需求,要求应用只要打开后,就要每隔一段时间发送一次自身的位置,即便是应用退出了,也同样要在后台持续该功能。
在开始的时候,我准备用后台服务Service机制来实现这一功能,但是想到Service在后台运行久了,可能会被系统杀死,于是否定了这个方案。后面查阅资料,发现AlarmManager定时任务机制比较适合本次需求。因为AlarmManager是系统级的服务机制,即便是我们的应用进程被kill掉了,系统也可以再次唤醒它,同时AlarmManager定时比较准确,误差相对较少。
下面是实现的步骤:
1、首先在自定义的MyApplication里面去开始AlarmManager定时闹钟服务

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        startAlarm();
    }


    public void startAlarm(){
        /**
        首先获得系统服务
        */
        AlarmManager am = (AlarmManager) 
        getSystemService(Context.ALARM_SERVICE);

        /** 设置闹钟的意图,我这里是去调用一个服务,该服务功能就是获取位置并且上传*/
        Intent intent = new Intent(this, LocationService.class);
        PendingIntent pendSender = PendingIntent.getService(this, 0, intent, 0);
        am.cancel(pendSender);

        /**AlarmManager.RTC_WAKEUP 这个参数表示系统会唤醒进程;我设置的间隔时间是10分钟 */
        am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 10*60*1000, pendSender);
    }
}

下面是我处理定位的服务:

public class LocationService extends Service {

    private static final String TAG = "LocationService";


    //声明AMapLocationClient类对象
    AMapLocationClient mLocationClient = null;
    //声明AMapLocationClientOption对象
    public AMapLocationClientOption mLocationOption = null;


    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "start LocationService!");
        netThread.start();
        //初始化定位
        mLocationClient = new AMapLocationClient(getApplicationContext());
        //设置定位回调监听
        mLocationClient.setLocationListener(mLocationListener);
        //初始化AMapLocationClientOption对象
        mLocationOption = new AMapLocationClientOption();
        //设置定位模式为AMapLocationMode.Hight_Accuracy,高精度模式。
        mLocationOption.setLocationMode(AMapLocationMode.Hight_Accuracy);
        //获取一次定位结果:
        //该方法默认为false。
        mLocationOption.setOnceLocation(true);
        mLocationOption.setOnceLocationLatest(true);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "StartCommand LocationService!");
        getPosition();
        return super.onStartCommand(intent, flags, startId);

    }

    Handler netHandler = null;

    /**
     * 收发网络数据的线程
     */
    Thread netThread = new Thread(){
        @Override
        public void run() {
            Looper.prepare();
            netHandler = new Handler(){
                public void dispatchMessage(Message msg) {
                    Bundle data = msg.getData();
                    switch(msg.what){
                    case 0x1: //发送位置
                        String macstr = getMac();
                        String longitude = data.getString("longitude");
                        String latitude = data.getString("latitude");
                        String timestr = data.getString("timestr");
                        upDatePosition(macstr,longitude+","+latitude,timestr,timestr);
                        break;

                    }
                };
            };
            Looper.loop();
        }
    };

    public void getPosition(){
        //给定位客户端对象设置定位参数
        mLocationClient.setLocationOption(mLocationOption);
        //启动定位
        mLocationClient.startLocation();
    }
    //声明定位回调监听器
    public AMapLocationListener mLocationListener = new AMapLocationListener(){

        @Override
        public void onLocationChanged(AMapLocation amapLocation) {
                    if(amapLocation==null){
                        Log.i(TAG, "amapLocation is null!");
                        return;
                    }
                    if(amapLocation.getErrorCode()!=0){
                        Log.i(TAG, "amapLocation has exception errorCode:"+amapLocation.getErrorCode());
                        return;
                    }

                    Double longitude = amapLocation.getLongitude();//获取经度
                    Double latitude = amapLocation.getLatitude();//获取纬度
                    String longitudestr = String.valueOf(longitude);
                    String latitudestr = String.valueOf(latitude);
                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    Date date = new Date(amapLocation.getTime());
                    String timestr = df.format(date);
                    Log.i(TAG, "longitude,latitude:"+longitude+","+latitude);
                    Log.i(TAG, "time:"+timestr);
                    Message msg = new Message();
                    Bundle data = new Bundle();
                    data.putString("longitude", longitudestr);
                    data.putString("latitude", latitudestr);
                    data.putString("timestr", timestr);
                    msg.setData(data);
                    msg.what = 0x1;
                    netHandler.sendMessage(msg);
        }

    };



    private String getMac() {
        String macSerial = null;
        String str = "";

        try {
            Process pp = Runtime.getRuntime().exec("cat /sys/class/net/wlan0/address ");
            InputStreamReader ir = new InputStreamReader(pp.getInputStream());
            LineNumberReader input = new LineNumberReader(ir);

            for (; null != str;) {
                str = input.readLine();
                if (str != null) {
                    macSerial = str.trim();// 去空格
                    break;
                }
            }
        } catch (IOException ex) {
            // 赋予默认值
            ex.printStackTrace();
        }
        return macSerial;
    }



    public void upDatePosition(String mac, String position, String recordTime, String reportTime) {
        Log.i(TAG, mac+";"+position+";"+recordTime);
        // 命名空间
        String nameSpace = "http://nfswit.cc/";

        // 调用的方法名称
        String methodName = "UpdateDevicePosition";

        // EndPoint
        String endPoint = "http://182.247.238.98:82/WebService1.asmx";

        // SOAP Action
        String soapAction = "http://nfswit.cc/UpdateDevicePosition";

        // 指定WebService的命名空间和调用的方法名
        SoapObject rpc = new SoapObject(nameSpace, methodName);

        // 指定参数
        rpc.addProperty("strDeviceMAC", mac);
        rpc.addProperty("strDevicePosition", position);
        rpc.addProperty("strDeviceRecordTime", recordTime);
        rpc.addProperty("strDeviceReportTime", reportTime);

        // 生成调用WebService方法的SOAP请求信息,并指定SOAP的版本
        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        envelope.implicitTypes = true;
        envelope.bodyOut = rpc;
        // 设置是否调用的是dotNet开发的WebService
        envelope.dotNet = true;
        // 等价于envelope.bodyOut = rpc;
        envelope.setOutputSoapObject(rpc);

        HttpTransportSE transport = new HttpTransportSE(endPoint);
        try {
            // 调用WebService
            transport.call(soapAction, envelope);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 获取返回的数据
        Object object = envelope.bodyIn;
        // SoapFault object = (SoapFault) envelope.bodyIn;

        if (object == null) {
            Log.i(TAG, "return object is null!");
            return;
        }
        if (object instanceof SoapFault) {
            Log.i(TAG, "SoapFault refult is :" + object.toString());
            return;
        } else if (object instanceof SoapObject) {
            // 获取返回的结果
            Log.i(TAG, "SoapObject refult is :" + object.toString());

            try {
                SoapObject result = (SoapObject) object;
                PropertyInfo info = new PropertyInfo();
                result.getPropertyInfo(0, info);
                String str = result.getProperty(0).toString();
                Log.i(TAG, str);
                JSONObject jsonobj = (JSONObject) JSONValue.parse(str);
                String code = (String) jsonobj.get("code");
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }   

}

总体流程就是在服务回调onStartCommand(Intent intent, int flags, int startId)函数的时候,应用先利用高德地图的定位SDk发起一次获取定位的请求,然后在定位结果返回的监听回调方法中,去获得定位结果的位置,同时通过Handler机制把这个位置信息放到子线程中,在子线程里面我们通过调用服务器上的webService接口,把位置传上去。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值