Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中LocationManager的簡單使用03

Android中LocationManager的簡單使用03

編輯:關於Android編程

上接前兩篇,要自己去讀取什麼CellId,LocationAreaCode, MobileCountryCode,MobileNetworkCode等參數,而且多數是針對GSM/UMTS。而自己使用的CDMA,跟上面的參數叫法不一樣,還得自己一個一個去對應。雖然最後算是解決了,但是難道就沒有更好的辦法嗎。

翻了翻Android Developer找到一個不錯的東西LocationManager。LocationManager是通過listener的方式來告知調用者,而原來寫好的模塊是直接return的,於是得稍微改造一下:

首先定義一個Model:

  1. public class LocationData {
  2. String lat;
  3. String lon;
  4. String address;
  5. }

然後LBS的所有功能都封裝到一個工具類裡面:

首先在構造函數裡面獲取系統服務中的LocationManager:

  1. public class LBSTool {
  2. private Context mContext;
  3. private LocationManager mLocationManager;
  4. private LocationData mLocation;
  5. private LBSThread mLBSThread;
  6. private MyLocationListner mNetworkListner;
  7. private MyLocationListner mGPSListener;
  8. private Looper mLooper;
  9. public LBSTool(Context context) {
  10. mContext = context;
  11. //獲取Location manager
  12. mLocationManager = (LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE);
  13. }
  14. ......
  15. }

然後是入口方法,這裡會啟動一個子線程去獲取地理位置信息,並讓主線程進入等待,時長通過timeout設置

  1. /**
  2. * 開始定位
  3. * @param timeout 超時設置
  4. * @return LocationData位置數據,如果超時則為null
  5. */
  6. public LocationData getLocation(long timeout) {
  7. mLocation = null;
  8. mLBSThread = new LBSThread();
  9. mLBSThread.start();//啟動LBSThread
  10. timeout = timeout > 0 ? timeout : 0;
  11. synchronized (mLBSThread) {
  12. try {
  13. Log.i(Thread.currentThread().getName(), "Waiting for LocationThread to complete...");
  14. mLBSThread.wait(timeout);//主線程進入等待,等待時長timeout ms
  15. Log.i(Thread.currentThread().getName(), "Completed.Now back to main thread");
  16. }
  17. catch (InterruptedException e) {
  18. e.printStackTrace();
  19. }
  20. }
  21. mLBSThread = null;
  22. return mLocation;
  23. }

子線程通過調用registerLocationListener開啟位置服務的監聽,並且講監聽器分配給指定looper

  1. private class LBSThread extends Thread {
  2. @Override
  3. public void run() {
  4. setName("location thread");
  5. Log.i(Thread.currentThread().getName(), "--start--");
  6. Looper.prepare();//給LBSThread加上Looper
  7. mLooper = Looper.myLooper();
  8. registerLocationListener();
  9. Looper.loop();
  10. Log.e(Thread.currentThread().getName(), "--end--");
  11. }
  12. }
  13. private void registerLocationListener () {
  14. Log.i(Thread.currentThread().getName(), "registerLocationListener");
  15. if (isGPSEnabled()) {
  16. mGPSListener=new MyLocationListner();
  17. //五個參數分別為位置服務的提供者,最短通知時間間隔,最小位置變化,listener,listener所在消息隊列的looper
  18. mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 0, mGPSListener, mLooper);
  19. }
  20. if (isNetworkEnabled()) {
  21. mNetworkListner=new MyLocationListner();
  22. mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3000, 0, mNetworkListner, mLooper);
  23. }
  24. }

isGPSEnabled和isNetworkEnabled分別為判斷當前手機是否開啟了GPS以及網絡的狀況(包含了是否開啟wifi和移動網絡),以決定使用哪一種服務提供者:GPS_PROVIDER或者NETWORK_PROVIDER。

  1. /**
  2. * 判斷GPS是否開啟
  3. * @return
  4. */
  5. public boolean isGPSEnabled() {
  6. if(mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
  7. Log.i(Thread.currentThread().getName(), "isGPSEnabled");
  8. return true;
  9. }
  10. else {
  11. return false;
  12. }
  13. }
  14. /**
  15. * 判斷Network是否開啟(包括移動網絡和wifi)
  16. * @return
  17. */
  18. public boolean isNetworkEnabled() {
  19. return (isWIFIEnabled() || isTelephonyEnabled());
  20. }
  21. /**
  22. * 判斷移動網絡是否開啟
  23. * @return
  24. */
  25. public boolean isTelephonyEnabled() {
  26. boolean enable = false;
  27. TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
  28. if (telephonyManager != null) {
  29. if (telephonyManager.getNetworkType() != TelephonyManager.NETWORK_TYPE_UNKNOWN) {
  30. enable = true;
  31. Log.i(Thread.currentThread().getName(), "isTelephonyEnabled");
  32. }
  33. }
  34. return enable;
  35. }
  36. /**
  37. * 判斷wifi是否開啟
  38. */
  39. public boolean isWIFIEnabled() {
  40. boolean enable = false;
  41. WifiManager wifiManager = (WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);
  42. if(wifiManager.isWifiEnabled()) {
  43. enable = true;
  44. Log.i(Thread.currentThread().getName(), "isWIFIEnabled");
  45. }
  46. return enable;
  47. }

當LocationManager在大於最短時間且檢測到最小位置變化時,就會通知給監聽器,然後我們就可以通過返回的經緯度信息去google服務器查找對應的地址,然後停止LocationManger的工作,解除LBSThread中的Looper,讓LBSThread結束,最後通知主線程可以繼續,整個流程結束。

  1. private class MyLocationListner implements LocationListener{
  2. @Override
  3. public void onLocationChanged(Location location) {
  4. // 當LocationManager檢測到最小位置變化時,就會回調到這裡
  5. Log.i(Thread.currentThread().getName(), "Got New Location of provider:"+location.getProvider());
  6. unRegisterLocationListener();//停止LocationManager的工作
  7. try {
  8. synchronized (mLBSThread) {
  9. parseLatLon(location.getLatitude()+"", location.getLongitude()+"");//解析地理位置
  10. mLooper.quit();//解除LBSThread的Looper,LBSThread結束
  11. mLBSThread.notify();//通知主線程繼續
  12. }
  13. }
  14. catch (Exception e) {
  15. e.printStackTrace();
  16. }
  17. }
  18. //後3個方法此處不做處理
  19. @Override
  20. public void onStatusChanged(String provider, int status, Bundle extras) {}
  21. @Override
  22. public void onProviderEnabled(String provider) {}
  23. @Override
  24. public void onProviderDisabled(String provider) {}
  25. };
  26. /**
  27. * 使用經緯度從goole服務器獲取對應地址
  28. * @param 經緯度
  29. */
  30. private void parseLatLon(String lat, String lon) throws Exception {
  31. Log.e(Thread.currentThread().getName(), "---parseLatLon---");
  32. Log.e(Thread.currentThread().getName(), "---"+lat+"---");
  33. try {
  34. HttpClient httpClient = new DefaultHttpClient();
  35. HttpGet get = new HttpGet("http://ditu.google.cn/maps/geo?output=json&q="+lat+","+lon);
  36. HttpResponse response = httpClient.execute(get);
  37. String resultString = EntityUtils.toString(response.getEntity());
  38. JSONObject jsonresult = new JSONObject(resultString);
  39. if(jsonresult.optJSONArray("Placemark") != null) {
  40. mLocation = new LocationData();
  41. mLocation.lat = lat;
  42. mLocation.lon = lon;
  43. mLocation.address = jsonresult.optJSONArray("Placemark").optJSONObject(0).optString("address");
  44. }
  45. }
  46. catch (Exception e) {
  47. e.printStackTrace();
  48. }
  49. }
  50. /**
  51. * 注銷監聽器
  52. */
  53. private void unRegisterLocationListener () {
  54. if(mGPSListener!=null){
  55. mLocationManager.removeUpdates(mGPSListener);
  56. mGPSListener=null;
  57. }
  58. if(mNetworkListner!=null){
  59. mLocationManager.removeUpdates(mNetworkListner);
  60. mNetworkListner=null;
  61. }
  62. }

接下來可以在界面上安放個button:

  1. locationBtn.setOnClickListener(new OnClickListener() {
  2. @Override
  3. public void onClick(View v) {
  4. //return mode
  5. LBSTool lbs = new LBSTool(LBStestActivity.this);
  6. LocationData location = lbs.getLocation(120000);
  7. if (location != null) {
  8. Log.i("---lat---",location.lat);
  9. Log.i("---lon---",location.lon);
  10. Log.i("---address---",location.address);
  11. Toast.makeText(LBStestActivity.this, location.lat + " " + location.lon + " " + location.address, Toast.LENGTH_LONG).show();
  12. }
  13. }
  14. });

最後別忘了加入權限:

此外,LocationManager還有些高級的用法,比如設置一些關鍵參數,以及獲取最後一次定位信息等等:

  1. Criteria criteria = new Criteria();
  2. criteria.setAccuracy(Criteria.ACCURACY_FINE); // 高精度
  3. criteria.setAltitudeRequired(false);
  4. criteria.setBearingRequired(false);
  5. criteria.setCostAllowed(true);
  6. criteria.setPowerRequirement(Criteria.POWER_LOW); // 低功耗
  7. String bestprovider = locationManager.getBestProvider(criteria, true); // 獲取GPS信息
  8. Location location = locationManager.getLastKnownLocation(bestprovider); // 通過GPS獲取位置
  9. Log.e("--bestprovider--", bestprovider);
  10. Log.e("--bestprovider--", location.getLatitude()+"");

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved