警告:Google已经废弃了基站获取位置的服务。也就是说该文章只有通过GPS和network获取位置的部分还有点作用。
获取地理位置有三种方法
1、通过cell id 也就是通过基站方式获取用户位置,有些手机在没有装SIM卡的时候,你获取的位置是空
2、通过gps 通过GPS获取位置,费电,如果用户是在室内,你可能获取不到用户的位置
3、通过network_provider 不管用户有没有装载SIM卡还是用户在室内都能获得用户位置,但是有些手机好像没有这项功能,我的测试机三星I8150就没找到从那里打开这项功能。但是经测试这款手机在没有安装SIM卡的情况下也能使用cell id获取到位置。
我的解决方案是,先使用cell id获取用户位置,这样既不费电也不用用户手动开启什么服务,我们只要在Manifest文件中生命获取位置的权限就可以了,如果使用cell id获取不到,然后在使用network_provider获取网络位置
我的势力代码是返回经纬度,所以在LocationInfo中直接做了类来记录经纬度:
具体代码如下:
封装Cell ID的类:
public class LocationInfo { /** 基站信息结构体 */ public static class CellIDInfo { /** 移动国家代码(中国的为460) */ public int MCC; /** 移动网络号码(中国移动为00,中国联通为01) */ public int MNC; /** gsm location area code, -1 if unknown, 0xffff max legal value 位置区域码 */ public int LAC; /** gsm cell id, -1 if unknown, 0xffff max legal value 基站编号,是个16位的数据 */ public int CID; /** 网络类型 */ public String TYPE; } /** 经纬度信息结构体 */ public static class SItude { /** 纬度 */ public double latitude; /** 经度 */ public double longitude; } }
获得网络经纬度并封装后返回SItude类:
我这是直接从我的项目中抽取出来的,使用到Activity的时候可能还带着我项目的名字
public class LocationProvider { private Context context; public LocationProvider (Context context){ this.context=context; } /** * 获取位置信息 * * @return LocationInfo.SItude * @throws Exception */ public LocationInfo.SItude getLocationInfo() throws Exception { SItude station = new SItude(); List<CellIDInfo> infoList = getCellIDInfo(); if (infoList == null){ Location gpsNetLoc = getGPSNetLocInfo(); station .latitude= gpsNetLoc.getLatitude(); station.longitude = gpsNetLoc.getLongitude(); if(station!= null ){ return station; } } Location loc = callGear(infoList); station.latitude = loc.getLatitude(); station.longitude = loc.getLongitude(); Logger.i(loc.getLatitude() + "手机纬度"); Logger.i(loc.getLongitude() + "手机经度"); return station; } private static Location getGPSNetLocInfo() { Location loc = null; LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); final boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); boolean netEnable = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); //这里我只判断了network_provider是否开启了,可根据自己实际需求来做判断 if (!netEnable) { new AlertDialog.Builder(context) .setTitle("请允许我获得你的位置信息") .setMessage("点击设置开启位置服务") .setPositiveButton("开启位置服务", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { enableLocationSettings(); } }) .create() .show(); } if(gpsEnabled||netEnable){ loc = setup(locationManager); } return loc; } // Method to launch Settings private static void enableLocationSettings() { Intent settingsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(settingsIntent); } private static Location setup(LocationManager mLocationManager ) { Location gpsLocation = null; Location networkLocation = null; mLocationManager.removeUpdates(listener); gpsLocation = requestUpdatesFromProvider( LocationManager.GPS_PROVIDER,mLocationManager); networkLocation = requestUpdatesFromProvider( LocationManager.NETWORK_PROVIDER,mLocationManager ); // If both providers return last known locations, compare the two and use the better // one to update the UI. If only one provider returns a location, use it. if (gpsLocation != null && networkLocation != null) { return getBetterLocation(gpsLocation, networkLocation); } else if (gpsLocation != null) { return gpsLocation; } else if (networkLocation != null) { return networkLocation; } return null; } private static Location requestUpdatesFromProvider(final String provider, final LocationManager mLocationManager) { Location location = null; if (mLocationManager.isProviderEnabled(provider)) { mLocationManager.requestLocationUpdates(provider, 10000, 10, listener); location = mLocationManager.getLastKnownLocation(provider); } else { if(provider.equals(LocationManager.NETWORK_PROVIDER)){ Toast.makeText(PalmdealApplication.getInstance(),"网络位置服务未开启可能导致不能获取您在室内时的位置", Toast.LENGTH_LONG).show(); } } return location; } protected static Location getBetterLocation(Location newLocation, Location currentBestLocation) { if (currentBestLocation == null) { // A new location is always better than no location return newLocation; } // Check whether the new location fix is newer or older long timeDelta = newLocation.getTime() - currentBestLocation.getTime(); boolean isSignificantlyNewer = timeDelta > 10000; boolean isSignificantlyOlder = timeDelta < -10000; boolean isNewer = timeDelta > 0; // If it's been more than two minutes since the current location, use the new location // because the user has likely moved. if (isSignificantlyNewer) { return newLocation; // If the new location is more than two minutes older, it must be worse } else if (isSignificantlyOlder) { return currentBestLocation; } // Check whether the new location fix is more or less accurate int accuracyDelta = (int) (newLocation.getAccuracy() - currentBestLocation.getAccuracy()); boolean isLessAccurate = accuracyDelta > 0; boolean isMoreAccurate = accuracyDelta < 0; boolean isSignificantlyLessAccurate = accuracyDelta > 200; // Check if the old and new location are from the same provider boolean isFromSameProvider = isSameProvider(newLocation.getProvider(), currentBestLocation.getProvider()); // Determine location quality using a combination of timeliness and accuracy if (isMoreAccurate) { return newLocation; } else if (isNewer && !isLessAccurate) { return newLocation; } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) { return newLocation; } return currentBestLocation; } /** Checks whether two providers are the same */ private static boolean isSameProvider(String provider1, String provider2) { if (provider1 == null) { return provider2 == null; } return provider1.equals(provider2); } private final static LocationListener listener = new LocationListener() { @Override public void onLocationChanged(Location location) { // A new location update is received. Do something useful with it. Update the UI with // the location update. } @Override public void onProviderDisabled(String provider) { } @Override public void onProviderEnabled(String provider) { } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } }; public static List<CellIDInfo> getCellIDInfo() throws Exception { TelephonyManager manager = (TelephonyManager) context.getSystemService( Context.TELEPHONY_SERVICE); List<CellIDInfo> cellID = new ArrayList<CellIDInfo>(); int type = manager.getNetworkType(); Logger.i("getCellIDInfo--> NetworkType = " + type); int phoneType = manager.getPhoneType(); Logger.i("getCellIDInfo--> phoneType = " + phoneType); // gsm if (isGsm(type)) { return getCellGsmList(manager); } // cdma if (isCdma(type)) { return getCellCDMAList(manager); } // other cellID = getCellGsmList(manager); if (cellID == null || cellID.isEmpty()) { cellID = getCellCDMAList(manager); } return cellID; } private static int[] gsm_types = { TelephonyManager.NETWORK_TYPE_GPRS, TelephonyManager.NETWORK_TYPE_EDGE, TelephonyManager.NETWORK_TYPE_HSDPA, TelephonyManager.NETWORK_TYPE_UMTS }; private static int[] cdma_types = { TelephonyManager.NETWORK_TYPE_CDMA, TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyManager.NETWORK_TYPE_EVDO_A }; private static boolean isGsm(int network_type) { return checkType(network_type,gsm_types); } private static boolean isCdma(int network_type) { return checkType(network_type,cdma_types); } private static boolean checkType(int network_type, int[] types) { for (int type : types) { if (network_type == type) return true; } return false; } /** * 获得CDMA的CellInfo * * @param manager * @return */ private static List<CellIDInfo> getCellCDMAList(TelephonyManager manager) { try { List<CellIDInfo> cellCDMAList = new ArrayList<CellIDInfo>(); CellIDInfo currentCell = new CellIDInfo(); CdmaCellLocation cdma = (CdmaCellLocation) manager.getCellLocation(); if (cdma == null) { Logger.i("CdmaCellLocation is null!!!"); return null; } int lac = cdma.getNetworkId(); int mcc = Integer.parseInt(manager.getNetworkOperator().substring(0, 3)); int mnc = Integer.parseInt(String.valueOf(cdma.getSystemId())); int cid = cdma.getBaseStationId(); currentCell.CID = cid; currentCell.MCC = mcc; currentCell.MNC = mnc; currentCell.LAC = lac; currentCell.TYPE = "cdma"; cellCDMAList.add(currentCell); // 获得邻近基站信息 List<NeighboringCellInfo> list = manager.getNeighboringCellInfo(); int size = list.size(); for (int i = 0; i < size; i++) { CellIDInfo info = new CellIDInfo(); info.CID = list.get(i).getCid(); info.MCC = mcc; info.MNC = mnc; info.LAC = lac; cellCDMAList.add(info); } return cellCDMAList; } catch (Exception e) { e.printStackTrace(); return null; } } /** * 获得GSM的CellInfo * * @param manager * @return */ private static List<CellIDInfo> getCellGsmList(TelephonyManager manager) { try { List<CellIDInfo> cellGsmList = new ArrayList<CellIDInfo>(); CellIDInfo currentCell = new CellIDInfo(); GsmCellLocation gsm = ((GsmCellLocation) manager.getCellLocation()); if (gsm == null) { Logger.i("GsmCellLocation is null!!!"); return null; } int lac = gsm.getLac(); int mcc = Integer.parseInt(manager.getNetworkOperator().substring(0, 3)); int mnc = Integer.parseInt(manager.getNetworkOperator().substring(3, 5)); int cid = gsm.getCid(); currentCell.CID = gsm.getCid(); currentCell.MCC = mcc; currentCell.MNC = mnc; currentCell.LAC = lac; currentCell.TYPE = "gsm"; cellGsmList.add(currentCell); // 获得邻近基站信息 List<NeighboringCellInfo> list = manager.getNeighboringCellInfo(); int size = list.size(); for (int i = 0; i < size; i++) { CellIDInfo info = new CellIDInfo(); info.CID = list.get(i).getCid(); info.MCC = mcc; info.MNC = mnc; info.LAC = lac; cellGsmList.add(info); } return cellGsmList; } catch (Exception e) { e.printStackTrace(); return null; } } public static Location callGear(List<CellIDInfo> cellID) { if (cellID == null || cellID.size() == 0) return null; DefaultHttpClient client = new DefaultHttpClient(); HttpPost post = new HttpPost("http://www.google.com/loc/json"); JSONObject holder = new JSONObject(); try { holder.put("version", "1.1.0"); holder.put("host", "maps.google.com"); holder.put("home_mobile_country_code", cellID.get(0).MCC);// mobileCountryCode); holder.put("home_mobile_network_code", cellID.get(0).MNC);// mobileNetworkCode); holder.put("radio_type", cellID.get(0).TYPE); holder.put("request_address", true); if ("460".equals(cellID.get(0).TYPE)) holder.put("address_language", "zh_CN"); else holder.put("address_language", "en_US"); JSONObject data, current_data; JSONArray array = new JSONArray(); current_data = new JSONObject(); current_data.put("cell_id", cellID.get(0).CID); current_data.put("location_area_code", cellID.get(0).LAC); current_data.put("mobile_country_code", cellID.get(0).MCC); current_data.put("mobile_network_code", cellID.get(0).MNC); current_data.put("age", 0); current_data.put("signal_strength", -60); current_data.put("timing_advance", 5555); array.put(current_data); if (cellID.size() > 2) { for (int i = 1; i < cellID.size(); i++) { data = new JSONObject(); data.put("cell_id", cellID.get(i).CID); data.put("location_area_code", cellID.get(i).LAC); data.put("mobile_country_code", cellID.get(i).MCC); data.put("mobile_network_code", cellID.get(i).MNC); data.put("age", 0); array.put(data); } } holder.put("cell_towers", array); StringEntity se = new StringEntity(holder.toString()); Log.e("Location send", holder.toString()); post.setEntity(se); HttpResponse resp = client.execute(post); HttpEntity entity = resp.getEntity(); BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent())); StringBuffer sb = new StringBuffer(); String result = br.readLine(); while (result != null) { Log.e("Locaiton reseive-->", result); sb.append(result); result = br.readLine(); } data = new JSONObject(sb.toString()); data = (JSONObject) data.get("location"); Location loc = new Location(LocationManager.NETWORK_PROVIDER); loc.setLatitude((Double) data.get("latitude")); loc.setLongitude((Double) data.get("longitude")); loc.setAccuracy(Float.parseFloat(data.get("accuracy").toString())); loc.setTime(System.currentTimeMillis());// AppUtil.getUTCTime()); return loc; } catch (JSONException e) { e.printStackTrace(); return null; } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } }