警告: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;
}
}