Android利用CellId和LocationManager获取用户地理位置

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

    }

 

}

 

你可能感兴趣的:(Android获取地理位置)