Android利用CellId和LocationManager獲取用戶地理位置

警告:Google已經廢棄了基站獲取位置的服務。也就是說該文章只有經過GPS和network獲取位置的部分還有點做用。 java


獲取地理位置有三種方法
一、經過cell id 也就是經過基站方式獲取用戶位置,有些手機在沒有裝SIM卡的時候,你獲取的位置是空
二、經過gps 經過GPS獲取位置,費電,若是用戶是在室內,你可能獲取不到用戶的位置
三、經過network_provider 無論用戶有沒有裝載SIM卡仍是用戶在室內都能得到用戶位置,可是有些手機好像沒有這項功能,個人測試機三星I8150就沒找到從那裏打開這項功能。可是經測試這款手機在沒有安裝SIM卡的狀況下也能使用cell id獲取到位置。 git

個人解決方案是,先使用cell id獲取用戶位置,這樣既不費電也不用用戶手動開啓什麼服務,咱們只要在Manifest文件中生命獲取位置的權限就能夠了,若是使用cell id獲取不到,而後在使用network_provider獲取網絡位置 json

個人勢力代碼是返回經緯度,因此在LocationInfo中直接作了類來記錄經緯度: 網絡

具體代碼以下: app

封裝Cell ID的類: less

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類: ide

我這是直接從個人項目中抽取出來的,使用到Activity的時候可能還帶着我項目的名字 post

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;

    }

 

}
相關文章
相關標籤/搜索