-package com.enqualcomm.support;\r
-\r
-import android.content.Context;\r
-import android.location.Criteria;\r
-import android.location.GpsSatellite;\r
-import android.location.GpsStatus;\r
-import android.location.GpsStatus.NmeaListener;\r
-\r
-import android.location.Location;\r
-import android.location.LocationListener;\r
-import android.location.LocationManager;\r
-import android.os.Bundle;\r
-import android.os.Handler;\r
-import android.os.Message;\r
-import android.provider.Settings;\r
-\r
-import com.enqualcomm.support.bean.ICLocation;\r
-import com.enqualcomm.support.bean.Runtime;\r
-import com.enqualcomm.support.utils.FileOutputUtil;\r
-import com.enqualcomm.support.utils.ICLogger;\r
-import com.enqualcomm.support.utils.TimeUtil;\r
-import com.enqualcomm.support.bean.ICLocation.GPS_locationStatus;\r
-import java.text.DecimalFormat;\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-\r
-import rx.Single;\r
-import rx.android.schedulers.AndroidSchedulers;\r
-import rx.functions.Action1;\r
-\r
-import static android.location.LocationManager.GPS_PROVIDER;\r
-\r
-public class NMEAListener implements NmeaListener, LocationListener {\r
- private static boolean listening = false;\r
-\r
- public boolean isListening() {\r
- return listening;\r
- }\r
-\r
- private LocationManager locationManager;\r
- private String locationInfo;\r
-\r
- private double longitude;\r
- private double latitude;\r
-\r
- private boolean noStop = false;\r
-\r
-\r
- private int SearchTimeout = 120;\r
- private int noSignalCount = 0;\r
- private int searchCout = 0;\r
- private GPS_CURRENT_STATUS gpsMode;\r
- int numberOfSatellites;\r
- Runtime runtime;\r
-\r
- private static int MaxFixedTimes = 3;\r
-\r
- private static int locationFixedCount = 0;\r
-\r
-\r
- private static location_callback mCallback = null;\r
-\r
- public interface location_callback {\r
- public void on_locating_changed(GPS_locationStatus gps_status);\r
- }\r
-\r
- public static void set_callback(location_callback callback) {\r
- mCallback = callback;\r
- }\r
-\r
- private GPS_locationStatus gps_status = new GPS_locationStatus();\r
-\r
- public GPS_locationStatus get_gps_status() {\r
- return gps_status;\r
- }\r
-\r
-\r
- public void setNoStop(boolean nostop) {\r
- if (Config.noLocationCycle==false)\r
- noStop = nostop;\r
- else\r
- ICLogger.i("skip setNoStop " + nostop);\r
- ICLogger.i("setNoStop " + nostop);\r
- if (noStop == false) {\r
- switch (runtime.getLocationInstance().getWorkingMod()) {\r
- case ICLocation.CUSTOM_MOD:\r
- case ICLocation.CUSTOM_MOD8_GPS:\r
- case ICLocation.EMERGNECY_MOD:\r
- case ICLocation.REALTIME_MOD:\r
- //GPS 定位模式不关闭GPS,防止 1分钟定位超时后,重新关闭开启GPS。\r
- //不给GPS继续定位的机会,造成第一次定位困难!\r
- break;\r
- case ICLocation.LOWPOWER_MOD:\r
- case ICLocation.NORMAL_MOD:\r
- case ICLocation.CUSTOM_MOD8_WIFI:\r
- default:\r
- ICLogger.i("非GPS定位模式,关闭GPS");\r
- //非GPS定位模式的话,需要关闭GPS。\r
- stopListen();\r
- break;\r
- }\r
-\r
- }\r
- }\r
-\r
- public NMEAListener(LocationManager paramLocationManager, Runtime paramRuntime) {\r
- this.locationManager = paramLocationManager;\r
- this.runtime = paramRuntime;\r
- }\r
-\r
- static int satindex = 0;\r
-\r
- public void onNmeaReceived(long paramLong, String nmeastr) {\r
-// EqcAlgorithmNative.native_EqcAlgorithmMethod5(paramString);\r
-// ICLogger.i("Nmea :"+nmeastr+" "+paramLong);\r
-\r
- if (Config.LOG_TOFILE)\r
- ICLogger.logToFile("Nmea", nmeastr);\r
-\r
- if (nmeastr.startsWith("$RD_RSSI")) {\r
- //每组NMEA数据的头,只适用于 SL8521E,9820E\r
- gps_status.numSatelliteList.clear();\r
- gps_status.search_time_cost = searchCout;\r
- }\r
-\r
- if (nmeastr.startsWith("$GPVTG")) {\r
- //每组NMEA数据的尾,只适用于 SL8521E,9820E\r
- searchCout++;\r
- //最后一页,打印搜星情况,并作一些判断。\r
- StringBuilder sb = new StringBuilder();\r
- sb.append("搜索" + searchCout + "次,搜索到卫星个数" + gps_status.satlite_numbss + ", [SNR>0] =" + runtime.getLocationInstance().numSatelliteList.size());\r
- sb.append(", Max 5 SNR [");\r
- for (int i = 0; i < runtime.getLocationInstance().max3Satellite.size(); i++) {\r
- sb.append(runtime.getLocationInstance().max3Satellite.get(i).getSnr() + ",");\r
- }\r
- sb.append("]");\r
- if (Config.LOG_TOFILE)\r
- ICLogger.logToFile( "GPS", sb.toString());\r
-\r
- ICLogger.i(sb.toString());\r
- // 卫星总数小于2 ,或者 snr小于20\r
- if (runtime.getLocationInstance().numSatelliteList.size() < 3 && (runtime.getLocationInstance().max3Satellite.size() > 0 ? (runtime.getLocationInstance().max3Satellite.get(0).getSnr() < 20 ? true : false) : true)) {\r
- noSignalCount++;\r
- }else{\r
- noSignalCount=0;//只要有一次满足有信号,则重新开始计数。\r
- }\r
-\r
-\r
- StringBuilder sb2 = new StringBuilder();\r
- if (!noStop) {\r
- if (searchCout > ICLocation.MAX_GPS_SEARCH_TIMEOUT) {\r
- sb2.append(" 搜索" + searchCout + "次未定位,超过" + ICLocation.MAX_GPS_SEARCH_TIMEOUT + "限制退出GPS定位");\r
-\r
- runtime.getLocationInstance().setLocationStat(ICLocation.LOCATION_STAT.LOCATION_GPS_TIEMOUT);\r
-\r
- stop(MSG_WHAT_GPS_TIMEOUT);\r
- }\r
- if (noSignalCount > ICLocation.MAX_GPS_NOSIGNAL_COUNT) {\r
- sb2.append(" 搜索" + searchCout + "次,超过" + noSignalCount + "次没有收到星,退出GPS定位");\r
- runtime.getLocationInstance().setLocationStat(ICLocation.LOCATION_STAT.LOCATION_GPS_TIEMOUT);\r
- stop(MSG_WHAT_GPS_NOSTAR);\r
- }\r
- }\r
- ICLogger.i(sb2.toString());\r
- if (Config.LOG_TOFILE)\r
- ICLogger.logToFile("GPS", sb2.toString());\r
-\r
-\r
- if (mCallback != null)\r
- mCallback.on_locating_changed(get_gps_status());\r
- }\r
- if (nmeastr.startsWith("$GPGLL,")) {\r
- String tmplist[] = nmeastr.split(",");\r
-// GPGLL编辑\r
-//(地理定位信息)\r
-// 例:$GPGLL,4250.5589,S,14718.5084,E,092204.999,A*2D\r
-// 字段0:$GPGLL,语句ID,表明该语句为Geographic Position(GLL)地理定位信息\r
-// 字段1:纬度ddmm.mmmm,度分格式(前导位数不足则补0)\r
-// 字段2:纬度N(北纬)或S(南纬)\r
-// 字段3:经度dddmm.mmmm,度分格式(前导位数不足则补0)\r
-// 字段4:经度E(东经)或W(西经)\r
-// 字段5:UTC时间,hhmmss.sss格式\r
-// 字段6:状态,A=定位,V=未定位\r
-// 字段7:校验值($与*之间的数异或后的值)\r
- String Lat = tmplist[1];\r
- String lon = tmplist[3];\r
- String fixed = tmplist[6];\r
-// ICLogger.i("GPGLL Lat="+Lat+",Lon="+lon+",fixed="+fixed);\r
-\r
- } else if (nmeastr.startsWith("$GPRMC,")) {\r
-// GPRMC编辑\r
-//(推荐定位信息数据格式)\r
-// 例:$GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A*50\r
-// 字段0:$GPRMC,语句ID,表明该语句为Recommended Minimum Specific GPS/TRANSIT Data(RMC)推荐最小定位信息\r
-// 字段1:UTC时间,hhmmss.sss格式\r
-// 字段2:状态,A=定位,V=未定位\r
-// 字段3:纬度ddmm.mmmm,度分格式(前导位数不足则补0)\r
-// 字段4:纬度N(北纬)或S(南纬)\r
-// 字段5:经度dddmm.mmmm,度分格式(前导位数不足则补0)\r
-// 字段6:经度E(东经)或W(西经)\r
-// 字段7:速度,节,Knots\r
-// 字段8:方位角,度\r
-// 字段9:UTC日期,DDMMYY格式\r
-// 字段10:磁偏角,(000 - 180)度(前导位数不足则补0)\r
-// 字段11:磁偏角方向,E=东W=西\r
-// 字段12:模式,A=自动,D=差分,E=估测,N=数据无效(3.0协议内容)\r
-// 字段13:校验值($与*之间的数异或后的值)\r
- String tmplist[] = nmeastr.split(",");\r
- String utctime = tmplist[1];\r
- String Lat = tmplist[3];\r
- String lon = tmplist[5];\r
- String fixed = tmplist[2];\r
- String speed = tmplist[7];\r
-// ICLogger.i("GPRMC GPSTime="+utctime+",Lat="+Lat+",Lon="+lon+",fixed="+fixed+",speed="+speed);\r
-// if (Config.LOG_TOFILE)\r
-// FileOutputUtil.fileOutput(this.runtime.getCacheDir(), "GPS", "GPRMC GPSTime="+utctime+",Lat="+Lat+",Lon="+lon+",fixed="+fixed+",speed="+speed);\r
- if (fixed.trim().equals("A")) {\r
- if (speed.trim().isEmpty()) speed = "0.0";\r
- runtime.getLocationInstance().setSpeed(Float.valueOf(speed));\r
- }\r
-\r
-\r
- } else if (nmeastr.startsWith("$GPGSV,")) {\r
-\r
-// GPGSV编辑\r
-// (可见卫星信息)\r
-// 例:$GPGSV,3,1,10,20,78,331,45,01,59,235,47,22,41,069,,13,32,252,45*70\r
-// 字段0:$GPGSV,语句ID,表明该语句为GPS Satellites in View(GSV)可见卫星信息\r
-// 字段1:本次GSV语句的总数目(1 - 3)\r
-// 字段2:本条GSV语句是本次GSV语句的第几条(1 - 3)\r
-// 字段3:当前可见卫星总数(00 - 12)(前导位数不足则补0)\r
-// 字段4:PRN 码(伪随机噪声码)(01 - 32)(前导位数不足则补0)\r
-// 字段5:卫星仰角(00 - 90)度(前导位数不足则补0)\r
-// 字段6:卫星方位角(00 - 359)度(前导位数不足则补0)\r
-// 字段7:信噪比(00-99)dbHz\r
-// 字段8:PRN 码(伪随机噪声码)(01 - 32)(前导位数不足则补0)\r
-// 字段9:卫星仰角(00 - 90)度(前导位数不足则补0)\r
-// 字段10:卫星方位角(00 - 359)度(前导位数不足则补0)\r
-// 字段11:信噪比(00-99)dbHz\r
-// 字段12:PRN 码(伪随机噪声码)(01 - 32)(前导位数不足则补0)\r
-// 字段13:卫星仰角(00 - 90)度(前导位数不足则补0)\r
-//// 字段14:卫星方位角(00 - 359)度(前导位数不足则补0)\r
-//// 字段15:信噪比(00-99)dbHz\r
-// 字段16:校验值($与*之间的数异或后的值)\r
-\r
- String tmplist[] = nmeastr.split(",");\r
- int maxPageCount = Integer.valueOf(tmplist[1]);\r
- int currentPage = Integer.valueOf(tmplist[2]);\r
- int SatlitesCount = Integer.valueOf(tmplist[3]);\r
- if (maxPageCount > 0 && currentPage == 1) {\r
- //第一页把数组初始化一遍。\r
- satindex = 0;\r
- runtime.getLocationInstance().numSatelliteList.clear(); //清除 SNR >0的卫星\r
- runtime.getLocationInstance().max3Satellite.clear(); //清除 最大3个星值\r
-\r
- gps_status.satlite_numbss = SatlitesCount;\r
- }\r
- int satcount = (tmplist.length - 4) / 4;\r
-// ICLogger.i("Nmea :"+nmeastr+" "+satcount);\r
- runtime.getLocationInstance().set_adding_satlite_flag(true);\r
- for (int i = 0; i < satcount; i++) {\r
- satindex++;\r
- String prn = tmplist[i * 4 + 4];\r
- String snr = tmplist[i * 4 + 4 + 3];\r
- if (snr.contains("*")) {\r
- snr = snr.substring(0, snr.indexOf("*"));\r
- }\r
- if (snr.trim().isEmpty()) {\r
- snr = "0";\r
- }\r
-// ICLogger.i("Sat=" + satindex + ",prn=" + prn + ",snr=" + snr);\r
-\r
- int intprn = Integer.valueOf(prn);\r
- float floatsnr = Float.valueOf(snr);\r
- if (floatsnr > 0) {\r
- //排序取得最大3个SNR\r
- get3MaxSnrSatellite(new ICLocation.GpsSatellitePriv(intprn, floatsnr));\r
- runtime.getLocationInstance().numSatelliteList.add(new ICLocation.GpsSatellitePriv(intprn, floatsnr));\r
- gps_status.numSatelliteList.add(new ICLocation.GpsSatellitePriv(intprn, floatsnr));\r
- }\r
- }\r
-\r
- runtime.getLocationInstance().set_adding_satlite_flag(false);\r
-\r
- } else if (nmeastr.startsWith("$GPGGA,")) {\r
-\r
-// GPGGA编辑\r
-//(定位信息)\r
-// 例:$GPGGA,092204.999,4250.5589,S,14718.5084,E,1,04,24.4,12.2,M,19.7,M,,0000*1F\r
-// 字段0:$GPGGA,语句ID,表明该语句为Global Positioning System Fix Data(GGA)GPS定位信息\r
-// 字段1:UTC 时间,hhmmss.sss,时分秒格式\r
-// 字段2:纬度ddmm.mmmm,度分格式(前导位数不足则补0)\r
-// 字段3:纬度N(北纬)或S(南纬)\r
-// 字段4:经度dddmm.mmmm,度分格式(前导位数不足则补0)\r
-// 字段5:经度E(东经)或W(西经)\r
-// 字段6:GPS状态,0=不可用(FIX NOT valid),1=单点定位(GPS FIX),2=差分定位(DGPS),3=无效PPS,4=实时差分定位(RTK FIX),5=RTK FLOAT,6=正在估算\r
-// 字段7:正在使用的卫星数量(00 - 12)(前导位数不足则补0)\r
-// 字段8:HDOP水平精度因子(0.5 - 99.9)\r
-// 字段9:海拔高度(-9999.9 - 99999.9)\r
-// 字段10:单位:M(米)\r
-// 字段11:地球椭球面相对大地水准面的高度 WGS84水准面划分\r
-// 字段12:WGS84水准面划分单位:M(米)\r
-// 字段13:差分时间(从接收到差分信号开始的秒数,如果不是差分定位将为空)\r
-// 字段14:差分站ID号0000 - 1023(前导位数不足则补0,如果不是差分定位将为空)\r
-// 字段15:校验值($与*之间的数异或后的值)\r
-\r
- String tmplist[] = nmeastr.split(",");\r
- String utctime = tmplist[1];\r
- String Lat = tmplist[2];\r
- String lon = tmplist[4];\r
- String latname= tmplist[3];\r
- String lonname=tmplist[5];\r
- String fixed = tmplist[6];\r
- String usedStarts = tmplist[7];\r
- String hdop = tmplist[8];\r
-\r
-\r
- if ((fixed.trim().equals("1")) || (fixed.trim().equals("2")) || (fixed.trim().equals("6"))) {\r
-\r
-\r
- // 转换GPS坐标为度,以便在各种应用中可以方便查找。\r
- latitude = Double.valueOf(Lat);\r
- longitude = Double.valueOf(lon);\r
- // 转换单位,从分转换到度\r
-\r
- double intdu = (int) (longitude / 100f); //小数转换到分为单位\r
- double du = (longitude - intdu * 100) / 60f;\r
- double last = intdu + du;\r
- longitude = last;\r
- intdu = (int) (latitude / 100f); //小数转换到分为单位\r
- du = (latitude - intdu * 100) / 60f;\r
- last = intdu + du;\r
- latitude = last;\r
-\r
- // 经纬度 保留4位小数点\r
- DecimalFormat df = new DecimalFormat("#.0000000");\r
- String strLatitude = df.format(latitude);\r
- String strLongitude = df.format(longitude);\r
-\r
- //定位\r
- StringBuilder sb = new StringBuilder();\r
- sb.append("GPGGA, location time= " + TimeUtil.getLocalTime() + ", FixedCount=" + locationFixedCount + ", GPSTime=" + utctime + ", Lat("+latname+")=" + Lat + " (" + strLatitude + "), Lon("+lonname+")=" + lon + " (" + strLongitude + "), fixed=" + fixed + ", hdop=" + hdop + ", usedStarts=" + usedStarts);\r
- ICLogger.i(sb.toString());\r
- if (Config.LOG_TOFILE)\r
- ICLogger.logToFile( "GPS", sb.toString());\r
- //定位了,\r
- if (hdop != null && hdop.trim().length() > 0 && Float.valueOf(hdop) < ICLocation.MAX_HDOP) {\r
- locationFixedCount++;\r
- } else {\r
- ICLogger.i("HDOP is larger than " + ICLocation.MAX_HDOP + " , skip this location!");\r
- if (Config.LOG_TOFILE)\r
- ICLogger.logToFile( "GPS", "HDOP is larger than " + ICLocation.MAX_HDOP + " , skip this location!");\r
- }\r
- if (locationFixedCount > MaxFixedTimes) {\r
- /*\r
- 只有当前GPS已经定位,且location不为空才给 runtime赋值GPS坐标。\r
- 延迟MaxFixedTimes秒后才设置runtime的定位标志,以便稳定坐标值。\r
- */\r
- runtime.getLocationInstance().setLocation(Lat, lon);\r
- runtime.getLocationInstance().setLocationGPS(strLatitude, strLongitude);\r
- runtime.getLocationInstance().setLocationlatlonName(latname,lonname);\r
- runtime.getLocationInstance().setUsedStarts(Integer.valueOf(usedStarts.trim()));\r
- runtime.getLocationInstance().setHod(Float.valueOf(hdop.trim()));\r
- runtime.getLocationInstance().setLocationStat(ICLocation.LOCATION_STAT.LOCATION_FIXED);\r
- ICLogger.i("定位" + locationFixedCount + "次 > " + MaxFixedTimes + ", set LOCATION_FIXED ");\r
- if (Config.LOG_TOFILE)\r
- ICLogger.logToFile("GPS", "定位" + locationFixedCount + "次 > " + MaxFixedTimes + ", set LOCATION_FIXED ");\r
- if (!noStop) {\r
- stopListen();\r
- }\r
- }\r
- gps_status.locating_status = 1; //fixed\r
- } else {\r
- gps_status.locating_status = 0; //notfixed\r
- }\r
- gps_status.hdop = Float.valueOf(hdop.trim());\r
- gps_status.used_gps_numbs = Integer.valueOf(usedStarts.trim());\r
-\r
-\r
- } else if (nmeastr.startsWith("$GPGSA,")) {\r
-\r
-// GPGSA编辑\r
-//( 当前卫星信息)\r
-// 例:$GPGSA,A,3,01,20,19,13,,,,,,,,,40.4,24.4,32.2*0A\r
-// 字段0:$GPGSA,语句ID,表明该语句为GPS DOP and Active Satellites(GSA)当前卫星信息\r
-// 字段1:定位模式(选择2D/3D),A=自动选择,M=手动选择\r
-// 字段2:定位类型,1=未定位,2=2D定位,3=3D定位\r
-// 字段3:PRN码(伪随机噪声码),第1信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)\r
-// 字段4:PRN码(伪随机噪声码),第2信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)\r
-// 字段5:PRN码(伪随机噪声码),第3信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)\r
-// 字段6:PRN码(伪随机噪声码),第4信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)\r
-// 字段7:PRN码(伪随机噪声码),第5信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)\r
-// 字段8:PRN码(伪随机噪声码),第6信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)\r
-// 字段9:PRN码(伪随机噪声码),第7信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)\r
-// 字段10:PRN码(伪随机噪声码),第8信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)\r
-// 字段11:PRN码(伪随机噪声码),第9信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)\r
-// 字段12:PRN码(伪随机噪声码),第10信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)\r
-// 字段13:PRN码(伪随机噪声码),第11信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)\r
-// 字段14:PRN码(伪随机噪声码),第12信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)\r
-// 字段15:PDOP综合位置精度因子(0.5 - 99.9)\r
-// 字段16:HDOP水平精度因子(0.5 - 99.9)\r
-// 字段17:VDOP垂直精度因子(0.5 - 99.9)\r
-// 字段18:校验值($与*之间的数异或后的值)\r
-\r
-// String tmplist[]=nmeastr.split(",");\r
-// String locationmod=tmplist[1];\r
-// String fixed=tmplist[2];\r
-// String hdop=tmplist[16];\r
-// if (!fixed.trim().equals("1")){\r
-// //定位\r
-// ICLogger.i("GPGSA fixed="+fixed+",hdop="+hdop);\r
-// }\r
- }\r
- }\r
-\r
- public void onProviderDisabled(String paramString) {\r
- }\r
-\r
- public void onProviderEnabled(String paramString) {\r
- }\r
-\r
- @Override\r
- public void onLocationChanged(Location location) {\r
-\r
- }\r
-\r
- public void onStatusChanged(String paramString, int paramInt, Bundle paramBundle) {\r
- }\r
-\r
- public boolean gpsColdStart() {\r
-//冷启动\r
- Bundle bundle = null;\r
- locationManager.sendExtraCommand("gps", "force_xtra_injection", bundle); //command\r
- locationManager.sendExtraCommand("gps", "force_time_injection", bundle);\r
- boolean b1 = locationManager.sendExtraCommand("gps", "delete_aiding_data", bundle);\r
- return b1;\r
-\r
- }\r
-\r
- public boolean gpsWormStart() {\r
-\r
-//温启动\r
- Bundle bundleWarm = new Bundle();\r
- bundleWarm.putBoolean("ephemeris", true);\r
- locationManager.sendExtraCommand("gps", "force_xtra_injection", bundleWarm); //command\r
- locationManager.sendExtraCommand("gps", "force_time_injection", bundleWarm);\r
- boolean b2 = locationManager.sendExtraCommand("gps", "delete_aiding_data", bundleWarm);\r
- return b2;\r
- }\r
-\r
- public boolean gpsHotStart() {\r
-//热启动\r
- Bundle bundleHot = new Bundle();\r
- bundleHot.putBoolean("almanac", true);\r
- locationManager.sendExtraCommand("gps", "force_xtra_injection", bundleHot); //command\r
- locationManager.sendExtraCommand("gps", "force_time_injection", bundleHot);\r
- boolean b3 = locationManager.sendExtraCommand("gps", "delete_aiding_data", bundleHot);\r
- return b3;\r
- }\r
-\r
-\r
- private final int MSG_WHAT_GPS_FIXED = 300;\r
- private final int MSG_WHAT_GPS_TIMEOUT = 100;\r
- private final int MSG_WHAT_GPS_NOSTAR = 200;\r
- private final int MSG_WHAT_GPS_FIXED_NO_STOP = 400;\r
-\r
- Handler temHandler = new Handler(new Handler.Callback() {\r
- @Override\r
- public boolean handleMessage(Message message) {\r
-\r
- if (message.what == MSG_WHAT_GPS_TIMEOUT || message.what == MSG_WHAT_GPS_NOSTAR) {\r
- //no start\r
- //do nothing\r
-\r
- } else if (message.what == MSG_WHAT_GPS_FIXED) {\r
- //fixed\r
- /*\r
- 只有当前GPS已经定位,且location不为空才给 runtime赋值GPS坐标。\r
- 延迟三秒后才设置runtime的定位标志,以便稳定坐标值。\r
- */\r
- runtime.getLocationInstance().setLocationStat(ICLocation.LOCATION_STAT.LOCATION_FIXED);\r
-\r
- }\r
-\r
- if (!noStop) {\r
- ICLogger.i("handleMessage MSG_WHAT_GPS_TIMEOUT/ MSG_WHAT_GPS_NOSTAR/ MSG_WHAT_GPS_FIXED " + message.what);\r
-\r
- stopListen();\r
- }\r
- return true;\r
- }\r
- });\r
-\r
- private void get3MaxSnrSatellite(ICLocation.GpsSatellitePriv gst) {\r
-\r
- float snr = gst.getSnr();\r
- for (int k = 0; k < runtime.getLocationInstance().max3Satellite.size(); k++) {\r
- if (runtime.getLocationInstance().max3Satellite.get(k).getPrn() == gst.getPrn())\r
- runtime.getLocationInstance().max3Satellite.remove(k);\r
- }\r
- runtime.getLocationInstance().max3Satellite.add(gst);//先添加进来。\r
-\r
- //从大到小排序\r
- for (int i = 0; i < runtime.getLocationInstance().max3Satellite.size(); i++) {\r
- for (int j = i; j < runtime.getLocationInstance().max3Satellite.size(); j++) {\r
- if (runtime.getLocationInstance().max3Satellite.get(i).getSnr() < runtime.getLocationInstance().max3Satellite.get(j).getSnr()) {\r
- ICLocation.GpsSatellitePriv ts = runtime.getLocationInstance().max3Satellite.get(j);\r
- runtime.getLocationInstance().max3Satellite.remove(j);\r
- runtime.getLocationInstance().max3Satellite.add(i, ts);//大的放前面\r
- }\r
- }\r
- }\r
- if (runtime.getLocationInstance().max3Satellite.size() > 5) { //超过三个,谁小就删掉\r
- runtime.getLocationInstance().max3Satellite.remove(5);\r
- }\r
-\r
- }\r
-\r
- //停止定位\r
- private void stop(int id) {\r
-\r
- // 经纬度 保留6位小数点\r
-// DecimalFormat df = new DecimalFormat("#.000000");\r
-// String strLatitude = df.format(latitude);\r
-// String strLongitude = df.format(longitude);\r
-// runtime.setLatitude(strLatitude);\r
-// runtime.setLongitude(strLongitude);\r
-//\r
-// ICLogger.i("Location " +runtime.getLocationInstance().getLocationStat().name());\r
- //发送停止消息\r
- temHandler.sendEmptyMessage(id);\r
- }\r
-\r
- boolean isFrist = true;\r
-\r
-\r
- public boolean startListen() {\r
-\r
- if (this.listening == false) {\r
- Settings.Secure.setLocationProviderEnabled(runtime.getContextProxy().getResolver(), GPS_PROVIDER, true);\r
-\r
- runtime.getLocationInstance().setLocationStat(ICLocation.LOCATION_STAT.LOCATION_OPEN);\r
-\r
- Criteria criteria = new Criteria();\r
- criteria.setAccuracy(Criteria.ACCURACY_FINE);// 设置为最大精度\r
- criteria.setAltitudeRequired(false);//不要求海拔信息\r
- criteria.setBearingRequired(false);// 不要求方位信息\r
- criteria.setCostAllowed(true);//是否允许付费\r
- criteria.setPowerRequirement(Criteria.POWER_LOW);// 对电量的要求\r
-\r
- String provider = locationManager.getBestProvider(criteria, true);\r
-\r
-\r
- ICLogger.i("GPS StartListen with Provider " + provider);\r
-\r
- if (Config.LOG_TOFILE) ICLogger.logToFile("GPS", "GPS StartListen with Provider " + provider);\r
-\r
- this.locationManager.requestLocationUpdates(provider, 0L, 0.0F, this);\r
-\r
- this.listening = true;\r
- noSignalCount = 0;\r
- longitude = 0;\r
- latitude = 0;\r
- searchCout = 0;\r
- locationFixedCount = 0;\r
- gpsMode = GPS_CURRENT_STATUS.GPS_LISTENING;\r
-// locationManager.addGpsStatusListener(statusListener);//监听搜星状态\r
- locationManager.addNmeaListener(this); //监听NMEA 协议数据。\r
-\r
- //做个热启动\r
- return true;//gpsHotStart();\r
- } else {\r
- ICLogger.i(" location listening, skip !");\r
-\r
- runtime.getLocationInstance().setLocationStat(ICLocation.LOCATION_STAT.LOCATION_SEARCHING);\r
-\r
- if (Config.LOG_TOFILE) ICLogger.logToFile("GPS", " location listening, skip !");\r
-\r
- return true;\r
- }\r
- }\r
- public boolean isGpsOpening() {\r
- return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);\r
- }\r
-\r
- public void stopListen() {\r
- this.locationManager.removeNmeaListener(this);\r
- this.locationManager.removeUpdates(this);\r
- ICLogger.i("stopListen 定位 ");\r
- if (Config.LOG_TOFILE) ICLogger.logToFile("GPS", "stopListen 定位 ");\r
- if (listening==true) {\r
- this.listening = false;\r
- Settings.Secure.setLocationProviderEnabled(runtime.getContextProxy().getResolver(), GPS_PROVIDER, false);\r
- ICLogger.i("stopListen 定位 done ");\r
- }else{\r
- if (isGpsOpening()){\r
- Settings.Secure.setLocationProviderEnabled(runtime.getContextProxy().getResolver(), GPS_PROVIDER, false);\r
- ICLogger.i("flag stoped but gps still opening , stop GPS!");\r
- }else {\r
- ICLogger.i("stopListen 定位 already stop skip stopListen");\r
- }\r
- }\r
- }\r
-\r
- public enum GPS_CURRENT_STATUS {\r
- GPS_LISTENING,\r
- GPS_FIXED,\r
- GPS_NOTFIXED,\r
- GPS_TIMEOUT,\r
- GPS_NOSINGAL,\r
- }\r
-}\r
+package com.enqualcomm.support;
+
+import android.content.Context;
+import android.location.Criteria;
+import android.location.GpsSatellite;
+import android.location.GpsStatus;
+import android.location.GpsStatus.NmeaListener;
+
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.provider.Settings;
+
+import com.enqualcomm.support.bean.ICLocation;
+import com.enqualcomm.support.bean.Runtime;
+import com.enqualcomm.support.utils.FileOutputUtil;
+import com.enqualcomm.support.utils.ICLogger;
+import com.enqualcomm.support.utils.TimeUtil;
+import com.enqualcomm.support.bean.ICLocation.GPS_locationStatus;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import rx.Single;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.functions.Action1;
+
+import static android.location.LocationManager.GPS_PROVIDER;
+
+public class NMEAListener implements NmeaListener, LocationListener {
+ private static boolean listening = false;
+
+ public boolean isListening() {
+ return listening;
+ }
+
+ private LocationManager locationManager;
+ private String locationInfo;
+
+ private double longitude;
+ private double latitude;
+
+ private boolean noStop = false;
+
+
+ private int SearchTimeout = 120;
+ private int noSignalCount = 0;
+ private int searchCout = 0;
+ private GPS_CURRENT_STATUS gpsMode;
+ int numberOfSatellites;
+ Runtime runtime;
+
+ private static int MaxFixedTimes = 3;
+
+ private static int locationFixedCount = 0;
+
+
+ private static location_callback mCallback = null;
+
+ public interface location_callback {
+ public void on_locating_changed(GPS_locationStatus gps_status);
+ }
+
+ public static void set_callback(location_callback callback) {
+ mCallback = callback;
+ }
+
+ private GPS_locationStatus gps_status = new GPS_locationStatus();
+
+ public GPS_locationStatus get_gps_status() {
+ return gps_status;
+ }
+
+
+ public void setNoStop(boolean nostop) {
+ if (Config.noLocationCycle==false)
+ noStop = nostop;
+ else
+ ICLogger.i("skip setNoStop " + nostop);
+ ICLogger.i("setNoStop " + nostop);
+ if (noStop == false) {
+ switch (runtime.getLocationInstance().getWorkingMod()) {
+ case ICLocation.CUSTOM_MOD:
+ case ICLocation.CUSTOM_MOD8_GPS:
+ case ICLocation.EMERGNECY_MOD:
+ case ICLocation.REALTIME_MOD:
+ //GPS 定位模式不关闭GPS,防止 1分钟定位超时后,重新关闭开启GPS。
+ //不给GPS继续定位的机会,造成第一次定位困难!
+ break;
+ case ICLocation.LOWPOWER_MOD:
+ case ICLocation.NORMAL_MOD:
+ case ICLocation.CUSTOM_MOD8_WIFI:
+ default:
+ ICLogger.i("非GPS定位模式,关闭GPS");
+ //非GPS定位模式的话,需要关闭GPS。
+ stopListen();
+ break;
+ }
+
+ }
+ }
+
+ public NMEAListener(LocationManager paramLocationManager, Runtime paramRuntime) {
+ this.locationManager = paramLocationManager;
+ this.runtime = paramRuntime;
+ }
+
+ static int satindex = 0;
+
+ public void onNmeaReceived(long paramLong, String nmeastr) {
+// EqcAlgorithmNative.native_EqcAlgorithmMethod5(paramString);
+// ICLogger.i("Nmea :"+nmeastr+" "+paramLong);
+
+ if (Config.LOG_TOFILE)
+ ICLogger.logToFile("Nmea", nmeastr);
+
+ if (nmeastr.startsWith("$RD_RSSI")) {
+ //每组NMEA数据的头,只适用于 SL8521E,9820E
+ gps_status.numSatelliteList.clear();
+ gps_status.search_time_cost = searchCout;
+ runtime.getLocationInstance().numSatelliteList.clear(); //清除 SNR >0的卫星
+ runtime.getLocationInstance().max3Satellite.clear(); //清除 最大3个星值
+ }
+
+ if (nmeastr.startsWith("$GPVTG")) {
+ //每组NMEA数据的尾,只适用于 SL8521E,9820E
+ searchCout++;
+ //最后一页,打印搜星情况,并作一些判断。
+ StringBuilder sb = new StringBuilder();
+ sb.append("搜索" + searchCout + "次,搜索到卫星个数" + gps_status.satlite_numbss + ", [SNR>0] =" + runtime.getLocationInstance().numSatelliteList.size());
+ sb.append(", Max 5 SNR [");
+ for (int i = 0; i < runtime.getLocationInstance().max3Satellite.size(); i++) {
+ sb.append(runtime.getLocationInstance().max3Satellite.get(i).getSnr() + ",");
+ }
+ sb.append("]");
+ if (Config.LOG_TOFILE)
+ ICLogger.logToFile( "GPS", sb.toString());
+
+ ICLogger.i(sb.toString());
+ // 卫星总数小于2 ,或者 snr小于20
+ if (runtime.getLocationInstance().numSatelliteList.size() < 3 && (runtime.getLocationInstance().max3Satellite.size() > 0 ? (runtime.getLocationInstance().max3Satellite.get(0).getSnr() < 20 ? true : false) : true)) {
+ noSignalCount++;
+ }else{
+ noSignalCount=0;//只要有一次满足有信号,则重新开始计数。
+ }
+
+
+ StringBuilder sb2 = new StringBuilder();
+ if (!noStop) {
+ if (searchCout > ICLocation.MAX_GPS_SEARCH_TIMEOUT) {
+ sb2.append(" 搜索" + searchCout + "次未定位,超过" + ICLocation.MAX_GPS_SEARCH_TIMEOUT + "限制退出GPS定位");
+
+ runtime.getLocationInstance().setLocationStat(ICLocation.LOCATION_STAT.LOCATION_GPS_TIEMOUT);
+
+ stop(MSG_WHAT_GPS_TIMEOUT);
+ }
+ if (noSignalCount > ICLocation.MAX_GPS_NOSIGNAL_COUNT) {
+ sb2.append(" 搜索" + searchCout + "次,超过" + noSignalCount + "次没有收到星,退出GPS定位");
+ runtime.getLocationInstance().setLocationStat(ICLocation.LOCATION_STAT.LOCATION_GPS_TIEMOUT);
+ stop(MSG_WHAT_GPS_NOSTAR);
+ }
+ }
+ ICLogger.i(sb2.toString());
+ if (Config.LOG_TOFILE)
+ ICLogger.logToFile("GPS", sb2.toString());
+
+
+ if (mCallback != null)
+ mCallback.on_locating_changed(get_gps_status());
+ }
+ if (nmeastr.startsWith("$GPGLL,") ||nmeastr.startsWith("$GNGLL,")) {
+ String tmplist[] = nmeastr.split(",");
+// GPGLL编辑
+//(地理定位信息)
+// 例:$GPGLL,4250.5589,S,14718.5084,E,092204.999,A*2D
+// 字段0:$GPGLL,语句ID,表明该语句为Geographic Position(GLL)地理定位信息
+// 字段1:纬度ddmm.mmmm,度分格式(前导位数不足则补0)
+// 字段2:纬度N(北纬)或S(南纬)
+// 字段3:经度dddmm.mmmm,度分格式(前导位数不足则补0)
+// 字段4:经度E(东经)或W(西经)
+// 字段5:UTC时间,hhmmss.sss格式
+// 字段6:状态,A=定位,V=未定位
+// 字段7:校验值($与*之间的数异或后的值)
+ String Lat = tmplist[1];
+ String lon = tmplist[3];
+ String fixed = tmplist[6];
+// ICLogger.i("GPGLL Lat="+Lat+",Lon="+lon+",fixed="+fixed);
+
+ } else if (nmeastr.startsWith("$GPRMC,")||nmeastr.startsWith("$GNRMC,")) {
+// GPRMC编辑
+//(推荐定位信息数据格式)
+// 例:$GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A*50
+// 字段0:$GPRMC,语句ID,表明该语句为Recommended Minimum Specific GPS/TRANSIT Data(RMC)推荐最小定位信息
+// 字段1:UTC时间,hhmmss.sss格式
+// 字段2:状态,A=定位,V=未定位
+// 字段3:纬度ddmm.mmmm,度分格式(前导位数不足则补0)
+// 字段4:纬度N(北纬)或S(南纬)
+// 字段5:经度dddmm.mmmm,度分格式(前导位数不足则补0)
+// 字段6:经度E(东经)或W(西经)
+// 字段7:速度,节,Knots
+// 字段8:方位角,度
+// 字段9:UTC日期,DDMMYY格式
+// 字段10:磁偏角,(000 - 180)度(前导位数不足则补0)
+// 字段11:磁偏角方向,E=东W=西
+// 字段12:模式,A=自动,D=差分,E=估测,N=数据无效(3.0协议内容)
+// 字段13:校验值($与*之间的数异或后的值)
+ String tmplist[] = nmeastr.split(",");
+ String utctime = tmplist[1];
+ String Lat = tmplist[3];
+ String lon = tmplist[5];
+ String fixed = tmplist[2];
+ String speed = tmplist[7];
+// ICLogger.i("GPRMC GPSTime="+utctime+",Lat="+Lat+",Lon="+lon+",fixed="+fixed+",speed="+speed);
+// if (Config.LOG_TOFILE)
+// FileOutputUtil.fileOutput(this.runtime.getCacheDir(), "GPS", "GPRMC GPSTime="+utctime+",Lat="+Lat+",Lon="+lon+",fixed="+fixed+",speed="+speed);
+ if (fixed.trim().equals("A")) {
+ if (speed.trim().isEmpty()) speed = "0.0";
+ runtime.getLocationInstance().setSpeed(Float.valueOf(speed));
+ }
+
+
+ } else if (nmeastr.startsWith("$GPGSV,")||nmeastr.startsWith("$GLGSV,")||nmeastr.startsWith("$GAGSV,")||nmeastr.startsWith("$GBGSV,")||nmeastr.startsWith("$BDGSV,")) {
+
+// GPGSV编辑
+// (可见卫星信息)
+// 例:$GPGSV,3,1,10,20,78,331,45,01,59,235,47,22,41,069,,13,32,252,45*70
+// 字段0:$GPGSV,语句ID,表明该语句为GPS Satellites in View(GSV)可见卫星信息
+// 字段1:本次GSV语句的总数目(1 - 3)
+// 字段2:本条GSV语句是本次GSV语句的第几条(1 - 3)
+// 字段3:当前可见卫星总数(00 - 12)(前导位数不足则补0)
+// 字段4:PRN 码(伪随机噪声码)(01 - 32)(前导位数不足则补0)
+// 字段5:卫星仰角(00 - 90)度(前导位数不足则补0)
+// 字段6:卫星方位角(00 - 359)度(前导位数不足则补0)
+// 字段7:信噪比(00-99)dbHz
+// 字段8:PRN 码(伪随机噪声码)(01 - 32)(前导位数不足则补0)
+// 字段9:卫星仰角(00 - 90)度(前导位数不足则补0)
+// 字段10:卫星方位角(00 - 359)度(前导位数不足则补0)
+// 字段11:信噪比(00-99)dbHz
+// 字段12:PRN 码(伪随机噪声码)(01 - 32)(前导位数不足则补0)
+// 字段13:卫星仰角(00 - 90)度(前导位数不足则补0)
+//// 字段14:卫星方位角(00 - 359)度(前导位数不足则补0)
+//// 字段15:信噪比(00-99)dbHz
+// 字段16:校验值($与*之间的数异或后的值)
+
+ String tmplist[] = nmeastr.split(",");
+ int maxPageCount = 0;
+ int currentPage = 0;
+ int SatlitesCount = 0;
+
+ try {
+ maxPageCount = Integer.valueOf(tmplist[1]);
+ } catch (Exception e) {
+ }
+ try {
+ currentPage = Integer.valueOf(tmplist[2]);
+ } catch (Exception e) {
+ }
+ try {
+ SatlitesCount = Integer.valueOf(tmplist[3]);
+ } catch (Exception e) {
+ }
+ if (maxPageCount > 0 && currentPage == 1) {
+ //第一页把数组初始化一遍。
+ satindex = 0;
+ gps_status.satlite_numbss = SatlitesCount;
+ }
+ int satcount = (tmplist.length - 4) / 4;
+// ICLogger.i("Nmea :"+nmeastr+" "+satcount);
+ runtime.getLocationInstance().set_adding_satlite_flag(true);
+ for (int i = 0; i < satcount; i++) {
+ satindex++;
+ String prn = tmplist[i * 4 + 4];
+ String snr = tmplist[i * 4 + 4 + 3];
+ if (snr.contains("*")) {
+ snr = snr.substring(0, snr.indexOf("*"));
+ }
+ if (snr.trim().isEmpty()) {
+ snr = "0";
+ }
+// ICLogger.i("Sat=" + satindex + ",prn=" + prn + ",snr=" + snr);
+
+ int intprn = 0;
+ try {
+ intprn = Integer.valueOf(prn);
+ } catch (Exception e) {
+ }
+ float floatsnr = 0;
+ try {
+ floatsnr = Float.valueOf(snr);
+ } catch (Exception e) {
+ }
+ if (floatsnr > 0) {
+ //排序取得最大3个SNR
+ get3MaxSnrSatellite(new ICLocation.GpsSatellitePriv(intprn, floatsnr));
+ runtime.getLocationInstance().numSatelliteList.add(new ICLocation.GpsSatellitePriv(intprn, floatsnr));
+ gps_status.numSatelliteList.add(new ICLocation.GpsSatellitePriv(intprn, floatsnr));
+ }
+ }
+
+ runtime.getLocationInstance().set_adding_satlite_flag(false);
+
+ } else if (nmeastr.startsWith("$GPGGA,")||nmeastr.startsWith("$GNGGA,")) {
+
+// GPGGA编辑
+//(定位信息)
+// 例:$GPGGA,092204.999,4250.5589,S,14718.5084,E,1,04,24.4,12.2,M,19.7,M,,0000*1F
+// 字段0:$GPGGA,语句ID,表明该语句为Global Positioning System Fix Data(GGA)GPS定位信息
+// 字段1:UTC 时间,hhmmss.sss,时分秒格式
+// 字段2:纬度ddmm.mmmm,度分格式(前导位数不足则补0)
+// 字段3:纬度N(北纬)或S(南纬)
+// 字段4:经度dddmm.mmmm,度分格式(前导位数不足则补0)
+// 字段5:经度E(东经)或W(西经)
+// 字段6:GPS状态,0=不可用(FIX NOT valid),1=单点定位(GPS FIX),2=差分定位(DGPS),3=无效PPS,4=实时差分定位(RTK FIX),5=RTK FLOAT,6=正在估算
+// 字段7:正在使用的卫星数量(00 - 12)(前导位数不足则补0)
+// 字段8:HDOP水平精度因子(0.5 - 99.9)
+// 字段9:海拔高度(-9999.9 - 99999.9)
+// 字段10:单位:M(米)
+// 字段11:地球椭球面相对大地水准面的高度 WGS84水准面划分
+// 字段12:WGS84水准面划分单位:M(米)
+// 字段13:差分时间(从接收到差分信号开始的秒数,如果不是差分定位将为空)
+// 字段14:差分站ID号0000 - 1023(前导位数不足则补0,如果不是差分定位将为空)
+// 字段15:校验值($与*之间的数异或后的值)
+
+ String tmplist[] = nmeastr.split(",");
+ String utctime = tmplist[1];
+ String Lat = tmplist[2];
+ String lon = tmplist[4];
+ String latname= tmplist[3];
+ String lonname=tmplist[5];
+ String fixed = tmplist[6];
+ String usedStarts = tmplist[7];
+ String hdop = tmplist[8];
+
+
+ if ((fixed.trim().equals("1")) || (fixed.trim().equals("2")) || (fixed.trim().equals("6"))) {
+
+
+ // 转换GPS坐标为度,以便在各种应用中可以方便查找。
+ try {
+ latitude = Double.valueOf(Lat);
+ longitude = Double.valueOf(lon);
+ } catch (Exception e){}
+ // 转换单位,从分转换到度
+
+ double intdu = (int) (longitude / 100f); //小数转换到分为单位
+ double du = (longitude - intdu * 100) / 60f;
+ double last = intdu + du;
+ longitude = last;
+ intdu = (int) (latitude / 100f); //小数转换到分为单位
+ du = (latitude - intdu * 100) / 60f;
+ last = intdu + du;
+ latitude = last;
+
+ // 经纬度 保留4位小数点
+ DecimalFormat df = new DecimalFormat("#.0000000");
+ String strLatitude = df.format(latitude);
+ String strLongitude = df.format(longitude);
+
+ //定位
+ StringBuilder sb = new StringBuilder();
+ sb.append("GPGGA, location time= " + TimeUtil.getLocalTime() + ", FixedCount=" + locationFixedCount + ", GPSTime=" + utctime + ", Lat("+latname+")=" + Lat + " (" + strLatitude + "), Lon("+lonname+")=" + lon + " (" + strLongitude + "), fixed=" + fixed + ", hdop=" + hdop + ", usedStarts=" + usedStarts);
+ ICLogger.i(sb.toString());
+ if (Config.LOG_TOFILE)
+ ICLogger.logToFile( "GPS", sb.toString());
+ //定位了,
+ if (hdop != null && hdop.trim().length() > 0 && Float.valueOf(hdop) < ICLocation.MAX_HDOP) {
+ locationFixedCount++;
+ } else {
+ ICLogger.i("HDOP is larger than " + ICLocation.MAX_HDOP + " , skip this location!");
+ if (Config.LOG_TOFILE)
+ ICLogger.logToFile( "GPS", "HDOP is larger than " + ICLocation.MAX_HDOP + " , skip this location!");
+ }
+ if (locationFixedCount > MaxFixedTimes) {
+ /*
+ 只有当前GPS已经定位,且location不为空才给 runtime赋值GPS坐标。
+ 延迟MaxFixedTimes秒后才设置runtime的定位标志,以便稳定坐标值。
+ */
+ runtime.getLocationInstance().setLocation(Lat, lon);
+ runtime.getLocationInstance().setLocationGPS(strLatitude, strLongitude);
+ runtime.getLocationInstance().setLocationlatlonName(latname,lonname);
+ runtime.getLocationInstance().setUsedStarts(Integer.valueOf(usedStarts.trim()));
+ runtime.getLocationInstance().setHod(Float.valueOf(hdop.trim()));
+ runtime.getLocationInstance().setLocationStat(ICLocation.LOCATION_STAT.LOCATION_FIXED);
+ ICLogger.i("定位" + locationFixedCount + "次 > " + MaxFixedTimes + ", set LOCATION_FIXED ");
+ if (Config.LOG_TOFILE)
+ ICLogger.logToFile("GPS", "定位" + locationFixedCount + "次 > " + MaxFixedTimes + ", set LOCATION_FIXED ");
+ if (!noStop) {
+ stopListen();
+ }
+ }
+ gps_status.locating_status = 1; //fixed
+ } else {
+ gps_status.locating_status = 0; //notfixed
+ }
+ try {
+ gps_status.hdop = Float.valueOf(hdop.trim());
+ gps_status.used_gps_numbs = Integer.valueOf(usedStarts.trim());
+ } catch (Exception e) {
+ }
+
+ } else if (nmeastr.startsWith("$GPGSA,")||nmeastr.startsWith("$GNGSA,")) {
+
+// GPGSA编辑
+//( 当前卫星信息)
+// 例:$GPGSA,A,3,01,20,19,13,,,,,,,,,40.4,24.4,32.2*0A
+// 字段0:$GPGSA,语句ID,表明该语句为GPS DOP and Active Satellites(GSA)当前卫星信息
+// 字段1:定位模式(选择2D/3D),A=自动选择,M=手动选择
+// 字段2:定位类型,1=未定位,2=2D定位,3=3D定位
+// 字段3:PRN码(伪随机噪声码),第1信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
+// 字段4:PRN码(伪随机噪声码),第2信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
+// 字段5:PRN码(伪随机噪声码),第3信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
+// 字段6:PRN码(伪随机噪声码),第4信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
+// 字段7:PRN码(伪随机噪声码),第5信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
+// 字段8:PRN码(伪随机噪声码),第6信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
+// 字段9:PRN码(伪随机噪声码),第7信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
+// 字段10:PRN码(伪随机噪声码),第8信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
+// 字段11:PRN码(伪随机噪声码),第9信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
+// 字段12:PRN码(伪随机噪声码),第10信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
+// 字段13:PRN码(伪随机噪声码),第11信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
+// 字段14:PRN码(伪随机噪声码),第12信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
+// 字段15:PDOP综合位置精度因子(0.5 - 99.9)
+// 字段16:HDOP水平精度因子(0.5 - 99.9)
+// 字段17:VDOP垂直精度因子(0.5 - 99.9)
+// 字段18:校验值($与*之间的数异或后的值)
+
+// String tmplist[]=nmeastr.split(",");
+// String locationmod=tmplist[1];
+// String fixed=tmplist[2];
+// String hdop=tmplist[16];
+// if (!fixed.trim().equals("1")){
+// //定位
+// ICLogger.i("GPGSA fixed="+fixed+",hdop="+hdop);
+// }
+ }
+ }
+
+ public void onProviderDisabled(String paramString) {
+ }
+
+ public void onProviderEnabled(String paramString) {
+ }
+
+ @Override
+ public void onLocationChanged(Location location) {
+
+ }
+
+ public void onStatusChanged(String paramString, int paramInt, Bundle paramBundle) {
+ }
+
+ public boolean gpsColdStart() {
+//冷启动
+ Bundle bundle = null;
+ locationManager.sendExtraCommand("gps", "force_xtra_injection", bundle); //command
+ locationManager.sendExtraCommand("gps", "force_time_injection", bundle);
+ boolean b1 = locationManager.sendExtraCommand("gps", "delete_aiding_data", bundle);
+ return b1;
+
+ }
+
+ public boolean gpsWormStart() {
+
+//温启动
+ Bundle bundleWarm = new Bundle();
+ bundleWarm.putBoolean("ephemeris", true);
+ locationManager.sendExtraCommand("gps", "force_xtra_injection", bundleWarm); //command
+ locationManager.sendExtraCommand("gps", "force_time_injection", bundleWarm);
+ boolean b2 = locationManager.sendExtraCommand("gps", "delete_aiding_data", bundleWarm);
+ return b2;
+ }
+
+ public boolean gpsHotStart() {
+//热启动
+ Bundle bundleHot = new Bundle();
+ bundleHot.putBoolean("almanac", true);
+ locationManager.sendExtraCommand("gps", "force_xtra_injection", bundleHot); //command
+ locationManager.sendExtraCommand("gps", "force_time_injection", bundleHot);
+ boolean b3 = locationManager.sendExtraCommand("gps", "delete_aiding_data", bundleHot);
+ return b3;
+ }
+
+
+ private final int MSG_WHAT_GPS_FIXED = 300;
+ private final int MSG_WHAT_GPS_TIMEOUT = 100;
+ private final int MSG_WHAT_GPS_NOSTAR = 200;
+ private final int MSG_WHAT_GPS_FIXED_NO_STOP = 400;
+
+ Handler temHandler = new Handler(new Handler.Callback() {
+ @Override
+ public boolean handleMessage(Message message) {
+
+ if (message.what == MSG_WHAT_GPS_TIMEOUT || message.what == MSG_WHAT_GPS_NOSTAR) {
+ //no start
+ //do nothing
+
+ } else if (message.what == MSG_WHAT_GPS_FIXED) {
+ //fixed
+ /*
+ 只有当前GPS已经定位,且location不为空才给 runtime赋值GPS坐标。
+ 延迟三秒后才设置runtime的定位标志,以便稳定坐标值。
+ */
+ runtime.getLocationInstance().setLocationStat(ICLocation.LOCATION_STAT.LOCATION_FIXED);
+
+ }
+
+ if (!noStop) {
+ ICLogger.i("handleMessage MSG_WHAT_GPS_TIMEOUT/ MSG_WHAT_GPS_NOSTAR/ MSG_WHAT_GPS_FIXED " + message.what);
+
+ stopListen();
+ }
+ return true;
+ }
+ });
+
+ private void get3MaxSnrSatellite(ICLocation.GpsSatellitePriv gst) {
+
+ float snr = gst.getSnr();
+ for (int k = 0; k < runtime.getLocationInstance().max3Satellite.size(); k++) {
+ if (runtime.getLocationInstance().max3Satellite.get(k).getPrn() == gst.getPrn())
+ runtime.getLocationInstance().max3Satellite.remove(k);
+ }
+ runtime.getLocationInstance().max3Satellite.add(gst);//先添加进来。
+
+ //从大到小排序
+ for (int i = 0; i < runtime.getLocationInstance().max3Satellite.size(); i++) {
+ for (int j = i; j < runtime.getLocationInstance().max3Satellite.size(); j++) {
+ if (runtime.getLocationInstance().max3Satellite.get(i).getSnr() < runtime.getLocationInstance().max3Satellite.get(j).getSnr()) {
+ ICLocation.GpsSatellitePriv ts = runtime.getLocationInstance().max3Satellite.get(j);
+ runtime.getLocationInstance().max3Satellite.remove(j);
+ runtime.getLocationInstance().max3Satellite.add(i, ts);//大的放前面
+ }
+ }
+ }
+ if (runtime.getLocationInstance().max3Satellite.size() > 5) { //超过三个,谁小就删掉
+ runtime.getLocationInstance().max3Satellite.remove(5);
+ }
+
+ }
+
+ //停止定位
+ private void stop(int id) {
+
+ // 经纬度 保留6位小数点
+// DecimalFormat df = new DecimalFormat("#.000000");
+// String strLatitude = df.format(latitude);
+// String strLongitude = df.format(longitude);
+// runtime.setLatitude(strLatitude);
+// runtime.setLongitude(strLongitude);
+//
+// ICLogger.i("Location " +runtime.getLocationInstance().getLocationStat().name());
+ //发送停止消息
+ temHandler.sendEmptyMessage(id);
+ }
+
+ boolean isFrist = true;
+
+
+ public boolean startListen() {
+
+ if (this.listening == false) {
+ Settings.Secure.setLocationProviderEnabled(runtime.getContextProxy().getResolver(), GPS_PROVIDER, true);
+
+ runtime.getLocationInstance().setLocationStat(ICLocation.LOCATION_STAT.LOCATION_OPEN);
+
+ Criteria criteria = new Criteria();
+ criteria.setAccuracy(Criteria.ACCURACY_FINE);// 设置为最大精度
+ criteria.setAltitudeRequired(false);//不要求海拔信息
+ criteria.setBearingRequired(false);// 不要求方位信息
+ criteria.setCostAllowed(true);//是否允许付费
+ criteria.setPowerRequirement(Criteria.POWER_LOW);// 对电量的要求
+
+ String provider = locationManager.getBestProvider(criteria, true);
+
+
+ ICLogger.i("GPS StartListen with Provider " + provider);
+
+ if (Config.LOG_TOFILE) ICLogger.logToFile("GPS", "GPS StartListen with Provider " + provider);
+
+ this.locationManager.requestLocationUpdates(provider, 0L, 0.0F, this);
+
+ this.listening = true;
+ noSignalCount = 0;
+ longitude = 0;
+ latitude = 0;
+ searchCout = 0;
+ locationFixedCount = 0;
+ gpsMode = GPS_CURRENT_STATUS.GPS_LISTENING;
+// locationManager.addGpsStatusListener(statusListener);//监听搜星状态
+ locationManager.addNmeaListener(this); //监听NMEA 协议数据。
+
+ //做个热启动
+ return true;//gpsHotStart();
+ } else {
+ ICLogger.i(" location listening, skip !");
+
+ runtime.getLocationInstance().setLocationStat(ICLocation.LOCATION_STAT.LOCATION_SEARCHING);
+
+ if (Config.LOG_TOFILE) ICLogger.logToFile("GPS", " location listening, skip !");
+
+ return true;
+ }
+ }
+ public boolean isGpsOpening() {
+ return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
+ }
+
+ public void stopListen() {
+ this.locationManager.removeNmeaListener(this);
+ this.locationManager.removeUpdates(this);
+ ICLogger.i("stopListen 定位 ");
+ if (Config.LOG_TOFILE) ICLogger.logToFile("GPS", "stopListen 定位 ");
+ if (listening==true) {
+ this.listening = false;
+ Settings.Secure.setLocationProviderEnabled(runtime.getContextProxy().getResolver(), GPS_PROVIDER, false);
+ ICLogger.i("stopListen 定位 done ");
+ }else{
+ if (isGpsOpening()){
+ Settings.Secure.setLocationProviderEnabled(runtime.getContextProxy().getResolver(), GPS_PROVIDER, false);
+ ICLogger.i("flag stoped but gps still opening , stop GPS!");
+ }else {
+ ICLogger.i("stopListen 定位 already stop skip stopListen");
+ }
+ }
+ }
+
+ public enum GPS_CURRENT_STATUS {
+ GPS_LISTENING,
+ GPS_FIXED,
+ GPS_NOTFIXED,
+ GPS_TIMEOUT,
+ GPS_NOSINGAL,
+ }
+}