博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于百度定位SDK的定位服务的实现
阅读量:7050 次
发布时间:2019-06-28

本文共 16648 字,大约阅读时间需要 55 分钟。

 

转载请标明出处:

一、定位模块的需求:我们想知道使用我们应用的用户的大概位置,每隔五分钟上传一次用户当前所在地的经纬度值到服务器端。

二、需求分析

     A、UML流程图如下:

    B、定位服务,功能具体分析:

      启动方式:手动、开机自启动。

      关闭方式:用户在设置里强制停止应用、关闭手机。(用户使用其他软件杀死掉我们的服务,用户重新启动应用服务才会开启。)
      1、开机自启动服务,等1分钟后开始检测网络状态和GPS是否开启,并通过通知栏提醒用户。(未开启时,提醒三次,5分钟提醒一次)
      2、直接启动应用,立即开始检测网络状态和GPS是否开启,并通过弹Dialog提示用户。若用户不愿意开启网络,即网络不可用时,直接退出应用。
     3、用户在设置-->应用程序-->正在运行的服务里面手动停止掉服务后,服务自动重启。
     4、网络检测可用,开始检测GPS。用户不开启GPS时,使用基站定位(WLAN、3G/2G)。
     5、网络检测可用,启动百度地图定位服务,每隔五分钟确认一次当前我所在的位置,并将经纬度值上传服务器端。
     6、网络检测可用,但是在发送定位数据时,网络断开了,以Toast形式提醒用户。
     7、网络检测可用,但是在定位过程中,网络断开了,并且目前打开的不是我们的应用(也就是说服务在后台运行),以通知的形式提醒用户。
     8、服务运行过程中,意外停止了。当用户重启应用后,服务重新启动。
     9、添加了开机自启动后,检测网络和通过通知栏提醒用户当前的网络、GPS状态。
    10、服务运行过程中,网络检测返回的标识的处理。

三、编码实现:

      完整源码下载地址:核心类的源码如下,

      A、服务类的源码如下:

package com.android.mobile.locator;import java.io.IOException;import java.io.InputStream;import java.util.Timer;import java.util.TimerTask;import android.app.Service;import android.content.Context;import android.content.Intent;import android.content.SharedPreferences;import android.os.Handler;import android.os.IBinder;import android.os.Message;import com.android.mobile.locator.net.HttpRequester;import com.android.mobile.locator.utils.Constant;import com.android.mobile.locator.utils.FileUtil;import com.android.mobile.locator.utils.GPSUtil;import com.android.mobile.locator.utils.LogUtil;import com.android.mobile.locator.utils.NetWorkUtil;import com.android.mobile.locator.utils.NotificationUtil;import com.android.mobile.locator.utils.ServiceUtil;import com.baidu.location.BDLocation;import com.baidu.location.BDLocationListener;import com.baidu.location.LocationClient;import com.baidu.location.LocationClientOption;import com.easi.mobile.locator.R;/** * 类名:MobileLocatorService * 功能描述:定位服务类。 * @author android_ls * 创建日期:2013-2-18 */public class MobileLocatorService extends Service {    /**     * Service action.     */    public static final String ACTION_MOBILE_LOCATOR_SERVICE = "com.easi.mobile.locator.MobileLocatorService";    /**     * 间隔时间5分钟     */     private static final int DELAY_TIME = 5*60*1000;    /**     * 开机一分钟后开始检测网络     */    private static final int CHECK_NETWORK_DELAY_TIME = 1 * 60 * 1000;    private Context mContext;    /**     * 定位SDK的核心类     */    private LocationClient mLocationClient;    /**     * 定位结果处理器 # class MyLocationListener implements BDLocationListener{}     */    private MyLocationListener mLocationListener;    /**     * 通知工具类     */    private NotificationUtil mNotificationUtil;    /**     * 服务的启动方式,开机自启动/手动启动     */    private int startingMode = -1;    /**     * 当前网络是否可用的标志     */    private boolean isOpenNetwork = false;    /**     * 检测网络的次数(5分钟一次,检测三次)     */    private int checkNetworkNumber = 0;    /**     * 定时器     */    private Timer mTimer;    @Override    public IBinder onBind(Intent intent) {        return null;    }    @Override    public void onCreate() {        LogUtil.e("--------------MobileLocatorService onCreate()----------------");        mNotificationUtil = new NotificationUtil(this);        mContext = MobileLocatorService.this;        // 设置为前台进程,尽量避免被系统干掉。        // MobileLocatorService.this.setForeground(true);        // 初始化定位服务,配置相应参数        initLocationService();    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        LogUtil.e("--------------MobileLocatorService onStartCommand()----------------");        if (intent != null) {            startingMode = intent.getIntExtra("startingMode", -1);            LogUtil.i("startingMode = " + startingMode);            if (startingMode == Constant.HANDLER_START_SERVICE) {                LogUtil.e("-------------手动启动---------------");                                // 判断服务是否已开启                boolean isRun = ServiceUtil.isServiceRun(getApplicationContext(), "com.baidu.location.f");                LogUtil.i("isRun = " + isRun);                if (isRun == false) {                    LogUtil.e("MobileLocatorService start Location Service");                    // 没启动,开启定位服务                    mLocationClient.start();                }            } else {                // 关闭手机,再次开启手机。这种情况下,startingMode的值获取不到。                // 关机重启,这种情况下,startingMode的值可以拿到。                // if (startingMode == Constant.BOOT_START_SERVICE) {                LogUtil.e("-------------开机自启动---------------");                checkNetworkNumber++;                // 第一次,1分钟后检测网络                mHandler.postDelayed(new Runnable() {                    @Override                    public void run() {                        LogUtil.e("--------------第一次检测网络---------------");                        checkNetwork();                        Message msg = new Message();                        msg.arg1 = Constant.CHECK_NETWORK_CONNECT_FLAG;                        mHandler.sendMessage(msg);                    }                }, CHECK_NETWORK_DELAY_TIME);            }        }        return Service.START_REDELIVER_INTENT;    }    /**     * 检测网络是否可用     */    private void checkNetwork() {        // 如果网络不可用,开启GPS就没有意义        if (NetWorkUtil.isNetworkAvailable(mContext)) {            isOpenNetwork = true;            if (GPSUtil.isOPen(mContext) == false) {                // 通知用户GPS未开启                mNotificationUtil.sendGPSNotification();            }            LogUtil.i("MobileLocatorService start Location Service");            // 开启定位服务            mLocationClient.start();        } else {            // 通知用户网络不可用            mNotificationUtil.sendNetworkNotification();        }    }    /**     * 初始化定位服务,配置相应参数     */    private void initLocationService() {        mLocationClient = new LocationClient(this.getApplicationContext());        mLocationListener = new MyLocationListener();        mLocationClient.registerLocationListener(mLocationListener);        LocationClientOption locationOption = new LocationClientOption();        locationOption.setOpenGps(true);        locationOption.setCoorType("bd09ll");        locationOption.disableCache(true);        locationOption.setPriority(LocationClientOption.GpsFirst);        locationOption.setScanSpan(DELAY_TIME);        locationOption.setProdName(this.getString(R.string.loaction_prod_name));        mLocationClient.setLocOption(locationOption);    }    Handler mHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            int result = msg.arg1;            switch (result) {            case Constant.CHECK_NETWORK_CONNECT_FLAG:                // 第一检测网络,直接过了。(已打开)                boolean isRun = ServiceUtil.isServiceRun(getApplicationContext(), "com.baidu.location.f");                LogUtil.i("isRun = " + isRun);                if (isOpenNetwork && isRun) {                    LogUtil.i("--------------第一次检测网络,直接过了。(已打开)----------------");                    return;                }                mTimer = new Timer();                mTimer.schedule(new TimerTask() {                    @Override                    public void run() {                        checkNetworkNumber++;                        LogUtil.i("Timer checkNetworkNumber = " + checkNetworkNumber);                        checkNetwork();                        boolean isRun = ServiceUtil.isServiceRun(getApplicationContext(), "com.baidu.location.f");                        if (isOpenNetwork && isRun) {                            mNotificationUtil.cancelNotification(Constant.NOTIFICATIO_NETWORK_NOT_OPEN);                            mTimer.cancel();                            return;                        } else {                            if (checkNetworkNumber == 3) {                                LogUtil.e("--------------第三次检测网络,还未开启,直接退出应用---------");                                // 检查网络,提醒了用户三次依然未开,退出应用。                                mNotificationUtil.cancelNotification(Constant.NOTIFICATIO_NETWORK_NOT_OPEN);                                mNotificationUtil.cancelNotification(Constant.NOTIFICATIO_GPS_NOT_OPEN);                                mTimer.cancel();                                // System.gc();                                System.exit(0);                            }                        }                    }                }, 0, DELAY_TIME);                break;            case Constant.UPLOAD_LOACTION_SUCCESS:                LogUtil.i("您当前的位置上传服务器成功!");                // Toast.makeText(getApplicationContext(), "您当前的位置上传服务器成功!", Toast.LENGTH_LONG).show();                        break;            case Constant.LOCATION_NETWORK_EXCEPTION:                LogUtil.e("网络异常!请检查您的网络连接。");                //  网络异常,没有成功向服务器发起请求。                // Toast.makeText(getApplicationContext(), "网络异常!请检查您的网络连接。", Toast.LENGTH_LONG).show();                // 通知用户网络不可用                mNotificationUtil.sendNetworkNotification();                break;            case Constant.LOCATION_NETWORK_CONNECT_FAIL:                LogUtil.e("网络连接失败,请将网络关闭再重新打开试试!");                // 通知用户网络不可用                mNotificationUtil.sendNetworkNotification();                break;            case Constant.UPLOAD_LOACTION_FAIL:                // Toast.makeText(getApplicationContext(), "您当前的位置上传服务器失败!请查看下你的网络状态。", Toast.LENGTH_LONG).show();                LogUtil.e("您当前的位置上传服务器失败!");                break;            default:                break;            }        }    };        class MyLocationListener implements BDLocationListener {        double longitude;        double latitude;        @Override        public void onReceiveLocation(BDLocation location) {            if (location == null) {                return;            }            LogUtil.i("BDLocationListener onReceiveLocation()");            /* location.getLocType()的返回值含义:               61 : GPS定位结果               62 : 扫描整合定位依据失败。此时定位结果无效。               63 : 网络异常,没有成功向服务器发起请求。此时定位结果无效。               65 : 定位缓存的结果。               66 : 离线定位结果。通过requestOfflineLocaiton调用时对应的返回结果               67 : 离线定位失败。通过requestOfflineLocaiton调用时对应的返回结果               68 : 网络连接失败时,查找本地离线定位时对应的返回结果               161: 表示网络定位结果               162~167: 服务端定位失败。*/            int locType = location.getLocType();            longitude = location.getLongitude();            latitude = location.getLatitude();            // TODO 调试使用            StringBuffer sb = new StringBuffer(256);            sb.append(" time : ");            sb.append(location.getTime());            sb.append("\n error code : ");            sb.append(locType);            sb.append("\n latitude : ");            sb.append(longitude);            sb.append("\n longitude : ");            sb.append(latitude);            LogUtil.i("BDLocationListene " + sb.toString());            if (locType == Constant.LOCATION_GPS || locType == Constant.LOCATION_NETWORK) {                 //  GPS定位结果、网络定位结果                 mHandler.post(new Runnable() {                     @Override                     public void run() {                         String userId = "bgao";                         int result = send(userId, longitude, latitude);                                                  Message msg = new Message();                         msg.arg1 = result;                         mHandler.sendMessage(msg);                     }                 });            } else if (locType == Constant.LOCATION_NETWORK_EXCEPTION || locType == Constant.LOCATION_NETWORK_CONNECT_FAIL) {                //  网络异常,没有成功向服务器发起请求。                Message msg = new Message();                msg.arg1 = locType;                mHandler.sendMessage(msg);            }        }        @Override        public void onReceivePoi(BDLocation arg0) {        }    }    /**     * 向服务器端当前位置的经纬度     * @param usetId 用户ID     * @param longitude 经度值     * @param latitude 纬度值     */    private int send(String usetId, double longitude, double latitude) {        StringBuffer params = new StringBuffer();        params.append("event=save");        params.append("¤tPointX=");        params.append(longitude);        params.append("¤tPointY=");        params.append(latitude);        params.append("&userId=");        params.append(usetId);        try {            InputStream inputStream = HttpRequester.post(Constant.UPLOAD_GPS_URL, params);            if (inputStream != null) {                String result = new String(FileUtil.read(inputStream));                String time = (new java.text.SimpleDateFormat("yyyy-MM-dd hh:mm:ss")).format(System.currentTimeMillis());                LogUtil.e("网络请求返回的结果:result = " + result + "\t 时间:" + time);                if ("Y".equals(result)) {                    return 1;                } else if ("N".equals(result)) {                    return 0;                } else {                    LogUtil.e("服务器端返回的值与预先商定的不否! ");                }            } else {                LogUtil.e("网络请求成功,但是返回的数据流为NULL");            }        } catch (IOException e) {            LogUtil.e("IOException 服务器访问失败!");            e.printStackTrace();            return 0;        }        return 0;    }    @Override    public void onDestroy() {        LogUtil.e("---------------MobileLocatorService onDestroy()----------------");        if (mLocationClient != null && mLocationClient.isStarted()) {            mLocationClient.stop();            if (mLocationListener != null) {                mLocationClient.unRegisterLocationListener(mLocationListener);            }        }        SharedPreferences sp = mContext.getSharedPreferences("MobileLocator", Context.MODE_PRIVATE);        String result = sp.getString("instruct", null);        LogUtil.i("MobileLocatorService onDestroy() result = " + result);        if ("exit".equals(result)) {            sp.edit().putString("instruct", "true").commit();            LogUtil.e("---------------MobileLocatorService onDestroy()-----------1-----");            System.exit(0);            return;        }        LogUtil.e("---------------MobileLocatorService onDestroy()---------2-------");        // 销毁时重新启动Service        Intent intent = new Intent(ACTION_MOBILE_LOCATOR_SERVICE);        intent.putExtra("startingMode", startingMode);        this.startService(intent);    }}

       B、启动时系统发出的广播的接收器类源码:

package com.android.mobile.locator;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import com.android.mobile.locator.utils.Constant;import com.android.mobile.locator.utils.LogUtil;/** * 类名:BootBroadcastReceiver  * 功能描述:启动时系统发出的广播的接收器 * #
* @author android_ls */public class BootBroadcastReceiver extends BroadcastReceiver { private static final String ACTION_BOOT = "android.intent.action.BOOT_COMPLETED"; @Override public void onReceive(Context context, Intent intent) { LogUtil.i("Boot this system , BootBroadcastReceiver onReceive()"); if (intent.getAction().equals(ACTION_BOOT)) { LogUtil.i("BootBroadcastReceiver onReceive(), MobileLocatorService Start"); Intent mIntent = new Intent(MobileLocatorService.ACTION_MOBILE_LOCATOR_SERVICE); mIntent.putExtra("startingMode", Constant.BOOT_START_SERVICE); context.startService(mIntent); } }}

      C、关机时系统发出的广播的接收器类源码:

package com.android.mobile.locator;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.SharedPreferences;import com.android.mobile.locator.utils.LogUtil;/** * 类名:ShutdownBroadcastReceiver * 功能描述:关机时系统发出的广播的接收器 * @author android_ls */public class ShutdownBroadcastReceiver extends BroadcastReceiver {	private static final String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN";		@Override	public void onReceive(Context context, Intent intent) {	    LogUtil.e("Shut down this system, ShutdownBroadcastReceiver onReceive()");	    		if (intent.getAction().equals(ACTION_SHUTDOWN)) {		    LogUtil.i("ShutdownBroadcastReceiver onReceive(), MobileLocatorService Stop");		    		    SharedPreferences sp = context.getSharedPreferences("MobileLocator", Context.MODE_PRIVATE);		    sp.edit().putString("instruct", "exit").commit();		    			context.stopService(new Intent(MobileLocatorService.ACTION_MOBILE_LOCATOR_SERVICE));		}	}}

       D、在AndroidManifest.xml文件中的配置:

 

      前段时间由于忙于公司的项目,所以好久没更新博客了,后面我会继续更新的,谢谢大家的支持!
 

 

 

 

你可能感兴趣的文章
CacheCloud bug修复日志
查看>>
新零售周年考:创业者和投资人交出了怎样的答卷?
查看>>
JSP中HTTP状态码
查看>>
【转】A Beginner's Guide To Understanding Convolutional Neural Networks
查看>>
JSP发送电子邮件
查看>>
“水下机器人”族群开始壮大,却在集体纠结要不要后面的那根线
查看>>
【Troubleshooting Case】无法删除Exchange 数据库DB 排错?
查看>>
C++ 读写MySQL经典 (转载)
查看>>
向量运算
查看>>
js实现图片加载特效(从左到右,百叶窗,从中间到两边)
查看>>
基于matlab的图像处理——高斯噪声&均值滤波,椒盐噪声&中值滤波
查看>>
小程序学习---hello world
查看>>
到数博会看“2017十大黑科技”
查看>>
麦肯锡报告:如果再不转型人工智能,这些行业将被越甩越远
查看>>
Git学习笔记(一)
查看>>
MS CRM 2011 如何从外部连接CRM
查看>>
MySQL读取配置文件的顺序、启动方式、启动原理
查看>>
速度制胜亚特兰大 施耐德电气助Internap与客户共成长
查看>>
重复 HTML 元素
查看>>
非系统数据文件损坏,rman备份恢复
查看>>