基于百度定位SDK的定位服务的实现
来源:互联网 发布:游戏服务端 python 编辑:程序博客网 时间:2024/06/11 19:36
转载:http://blog.csdn.net/android_ls/article/details/10179013
一、定位模块的需求:我们想知道使用我们应用的用户的大概位置,每隔五分钟上传一次用户当前所在地的经纬度值到服务器端。
二、需求分析
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、服务运行过程中,网络检测返回的标识的处理。
三、编码实现:
完整源码下载地址:http://download.csdn.net/detail/android_ls/5993623,核心类的源码如下,
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
- * 功能描述:启动时系统发出的广播的接收器
- * #<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
- * @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文件中的配置:
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.easi.mobile.locator"
- android:versionCode="1"
- android:versionName="1.0" >
- <uses-sdk android:minSdkVersion="8" />
- <!--
- android:sharedUserId="android.uid.system"
- android:killAfterRestore="true"
- android:process=":remote"
- android:enabled="true"
- -->
- <application
- android:allowClearUserData="false"
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name" >
- <activity
- android:label="@string/app_name"
- android:name="com.android.mobile.locator.MobileLocatorActivity" >
- <intent-filter >
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- <service
- android:enabled="true"
- android:name="com.android.mobile.locator.MobileLocatorService"
- android:process=":remote" >
- <intent-filter >
- <action android:name="com.easi.mobile.locator.MobileLocatorService" />
- </intent-filter>
- </service>
- <service
- android:enabled="true"
- android:name="com.baidu.location.f"
- android:process=":remote" />
- <receiver android:name="com.android.mobile.locator.BootBroadcastReceiver" >
- <intent-filter >
- <action android:name="android.intent.action.BOOT_COMPLETED" />
- <category android:name="android.intent.category.HOME" />
- </intent-filter>
- </receiver>
- <receiver android:name="com.android.mobile.locator.ShutdownBroadcastReceiver" >
- <intent-filter >
- <action android:name="android.intent.action.ACTION_SHUTDOWN" />
- <category android:name="android.intent.category.HOME" />
- </intent-filter>
- </receiver>
- </application>
- <!-- 授予应用程序访问系统开机事件的权限 -->
- <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
- <uses-permission android:name="android.permission.READ_PHONE_STATE" />
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
- <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
- <uses-permission android:name="android.permission.READ_PHONE_STATE" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
- <uses-permission android:name="android.permission.READ_LOGS" />
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.WRITE_SETTINGS" />
- </manifest>
前段时间由于忙于公司的项目,所以好久没更新博客了,后面我会继续更新的,谢谢大家的支持!
- 基于百度定位SDK的定位服务的实现
- 基于百度定位SDK的定位服务的实现
- 基于百度地图定位SDK实现定位
- Android学习-- 基于位置的服务 LBS(基于百度地图Android SDK)--定位SDK
- 实现android基于百度的定位
- 百度定位的实现
- 百度定位SDK只定位一次以及系统没有出现位置服务图标的解决
- 使用百度地图SDK实现定位功能,定位你当前的位置
- 百度地图Android定位SDK的API
- 基于百度地图的定位实现天气预报查询
- 百度定位服务的管理类
- Android基于百度定位SDK v4.1(LBS)实现定位功能
- Android--定位 基于百度地图SDK
- 基于百度地图的手机定位
- Android基于百度API的定位功能
- 百度地图(SDK v3.1.1)和百度定位(SDKv4.2)的实现!
- Android--百度地图定位功能的具体实现<百度地图SDK版本 v3.7.3>
- 百度地图定位在Activity的实现<百度地图SDK版本 v3.7.3>
- VS2008远程调试
- jQuery开发之超链接提示效果和图片提示效果
- sat数学逻辑推理题解题方法
- MySQL中函数CONCAT及GROUP_CONCAT
- java中JFrame 窗口关闭时,弹出一个对话框提示是否确定关闭
- 基于百度定位SDK的定位服务的实现
- 【整理】MySQL引擎
- vtkPolyData中GetPoint函数冲掉上一个数据的问题
- 单例设计模式
- Scripts:ash_gcwait_to_obj.sql
- iOS block
- ps -aux|grep 详细信息
- 十六进制转化为十进制的方法
- 合理规划SAT阅读备考节奏