顯示具有 Location Maps 標籤的文章。 顯示所有文章
顯示具有 Location Maps 標籤的文章。 顯示所有文章

星期二, 10月 18, 2011

MapView

Android應用程式學習筆記

MapView

顯示地圖的View,從Google Map Service取得數據。當它為焦點時,它可以抓取按鍵和觸碰手勢去搖鏡頭和變焦地圖。你也可以在程式碼中控制(getController())和可以繪製Overlay物件在地圖上(getOverlays())。

地圖可以顯示許多種模式:setSatellite(boolean)設定為衛星地圖、setTracffic(boolean)、setStreetView(boolean)。

首選的變焦機制就是內建的變焦機制,setBuildInZoomControls(boolean),當用戶搖鏡頭時,變焦控制會自動出現在MapView的底部。

MapView也是一個ViewGroup,LayoutParameters允許你附加其他View。

MapView只能藉由MapActivity建立,這是因為MapView必須依賴在後台存取網路及檔案系統的執行續。這些執行續的生命週期是由MapActivity看管,Tips是在應用程式目錄下緩衝的檔案系統,緩衝是自動管理,所以你不需要做任何事。

為了在MapView顯示Google Map,你必須註冊Google Map Service並獲得Map API 金鑰,可以參考如何利用Eclipse取得MD5 Fingerprint文章。

一旦你取得金鑰,你需要在XML布局文件中MapView的android:apiKey屬性上引用它。

Package com.google.android.maps

Android應用程式學習筆記

Package com.google.android.maps

此地圖套件允許應用程式顯示及控制Google Map介面,建立一個Google Map,你需要繼承MapActivity並且在布局上實現一個MapView。

為了在應用程式中使用MapView,你需要一個有"android:apiKey"屬性的MapView。

注意此套件並不是Android函式庫的標準套件,為了使用它,你必須在Androidmanifest文件中新增xml標籤在<application>標籤範圍中:

<uses-library android:name="com.google.android.maps" />


星期一, 10月 17, 2011

如何利用Eclipse取得MD5 Fingerprint

Android應用程式學習筆記

如何利用Eclipse取得MD5 Fingerprint

為何需要取得MD5 Fingerprint?
因為如果是想使用Google Map API就必須取得使用金鑰,那取得金鑰必須先取得MD5 fingerprint,再到官網產生金鑰。得到金鑰就能在應用程式中使用MapView等Google Map APIs。

取得方式有許多,可以使用指令完成,那對於指令不熟該怎麼辦?

以下就是不須透過指令,也一樣可以取得MD5 fingerprint的流程。

1.打開Eclipse。
2.Help > Install New Software。
3.在work with:中輸入http://keytool.sourceforge.net/update。
4.等到Name表中出現"Keytool",選取"Keytool"。
5.點擊Next。
6.當一切安裝完成時,在Eclipse中會出現"Keytool"菜單。



7.點擊Keytool > Open keystore。
8.點擊"Browse"然後在.android目錄下找到"debug.keystore"。
9.輸入android為密碼。
10.雙擊"androiddebugkey",顯示MD5 Fingerprint。



取得MD5 Fingerprint到Maps API Key Signup產生金鑰。

星期日, 10月 16, 2011

LocationManager LocationProvider LocationListener

Android應用程式學習筆記

LocationManager
此類提供存取系統定位服務,這些服務允許應用程式定期獲得裝置地理位置的更新,或是啟動應用程式指定的Intent,當裝置接近預設的地理位置時。 
你無須直接實現此類,透過context.getSystemService(Context.LOCATIO_SERVICE)取得LocationManager。
以下介紹幾個此類中的方法。
 public LocationProvider getProvider(String name)-取得名稱為name的LocationProvider。如果沒有此LocationProvider,回傳值為null。
public List<String> getProviders(boolean EnableOnly)-取得一組LocationProviders。參數值為true表示只回傳目前可用的LocationProvider。
public Location getLastKnownLocation(String provider)-回傳provider最後得知的位置。 
public void requestLocationUpdates(String provider , long minTime , float minDistance , LocationListener listener)-註冊目前的activity定期接受provider的通知,隨著當前位置不同或是狀態更新定期地呼叫LocationLListener。它也許要花一些時間接收最近期的位置,如果需要立即接收位置,應用程式可以利用getLastKnownLocation(String)方法。用戶關閉provider的情況下,更新將停止,並且呼叫onProviderDisable(String)方法。當provider再次啟動,onProviderEnable(String)將被呼叫,且位置更新將再次啟動。利用minTime和minDistance參數控制通知的頻率。如果minTime參數值大於0,LocationManager有機會在位置更新之間休息minTime毫秒來保存電力;如果minDistance參數值大於0,裝置移動超過minDistance距離,廣播一個位置。想盡可能的獲得通知,就將兩個參數設為0。後台服務應該留意設定充分的minTime,如此裝置不會消耗太多電力在保持GPS或是無線電台,特別是,不建議minTime數值小於6000毫秒。
LocationProvider
Location provider提供有關裝置的地理位置的定期報告,每個提供器有一組標準,在標準之下也許可以使用。舉例,一些提供器需要GPS硬體設備及許多衛星的能見度;其他需要蜂巢式無線電,或是存取特定載體的網路,或是網路。它們也有不同的電池消耗特性或是成本。
LocationListener
利用於接收當位置改變時LocationManager的通知,利用reuqestLocationUpdates(String , long , float , LocationListener)方法將監聽器註冊到位置管理服務(LocationManager)。
public void onLocationChanged(Location location)-當位置改變時呼叫此方法。
public void onProviderEnable(String provider)-當提供器啟用時呼叫此方法。
public void onProviderDisable(String provider)-當提供器關閉時呼叫此方法。
public void onStatusChanged(String provider , int status , Bundle extras)-當provider狀態改變時呼叫此方法。
 

實作Location的取得與LocationListener的設置

實作Location的取得與LocationListener的設置


1.在main.xml新增一個TextView

  1. <TextView 
  2. android:text="TextView" 
  3. android:id="@+id/location" 
  4. android:layout_width="wrap_content" 
  5. android:layout_height="wrap_content">
  6. </TextView>
2.編輯activity
  1. package test.location;

  2. import java.util.List;

  3. import android.app.Activity;
  4. import android.content.Context;
  5. import android.location.Location;
  6. import android.location.LocationListener;
  7. import android.location.LocationManager;
  8. import android.os.Bundle;
  9. import android.widget.TextView;

  10. public class HelloLocationActivity extends Activity {
  11.     /** Called when the activity is first created. */
  12. //創建新專案,注意創建時,target build選擇Google APIs,這是為了添加jar文件maps.jar。
  13. //引入LocationManager實例。
  14. //在main文件中宣告TextView。
  15. //在Androidmanifest文件中宣告權限。
  16. private LocationManager locationManager;
  17.     @Override
  18.     public void onCreate(Bundle savedInstanceState) {
  19.         super.onCreate(savedInstanceState);
  20.         setContentView(R.layout.main);
  21.         //呼叫getSystemService()取得LocationManager物件。
  22.         locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
  23.         locate();
  24.     }
  25.     
  26.     private void locate(){
  27.      TextView tv = (TextView)findViewById(R.id.location);
  28.      StringBuilder builder = new StringBuilder("可利用的provider");
  29.      //呼叫getProviders(boolean EnableOnly)取得一組可用的location provider名稱,true表示為可用的;false表示停用的。
  30.      List<String> providers = locationManager.getProviders(true);
  31.      //定義位置監聽器,接收來自LocationManager的通知。
  32.      LocationListener locationlistener = new LocationListener(){
  33.      //位置管理服務利用reuqestLocationUpdates(String , long , float , LocationListener)方法註冊位置監聽器後,這些方法就會被呼叫。
  34.      //Provider狀態改變時呼叫此方法。
  35.      public void onStatusChanged(String provider , int status , Bundle extras){
  36.     
  37.      }
  38.      //位置改變時呼叫此方法。
  39. @Override
  40. public void onLocationChanged(Location location) {
  41. // TODO Auto-generated method stub
  42. System.out.println("onLcationChanged");
  43. }

  44. //用戶關閉provider時呼叫此方法。
  45. @Override
  46. public void onProviderDisabled(String provider) {
  47. // TODO Auto-generated method stub
  48. System.out.println("onProviderDisabled");
  49. }

  50. //用戶啟動provider時呼叫此方法。
  51. @Override
  52. public void onProviderEnabled(String provider) {
  53. // TODO Auto-generated method stub
  54. System.out.println("onProviderEnabled");
  55. }
  56.      };
  57.     
  58.      for (String provider:providers){
  59.      //註冊目前的activity定期由provider通知位置更新。
  60.      locationManager.requestLocationUpdates(provider, 0, 1000, locationlistener);
  61.     
  62.      builder.append("\n").append(provider).append(":");
  63.      //回傳從provider最後所知的位置。
  64.      Location location = locationManager.getLastKnownLocation(provider);
  65.      if(location != null){
  66.      double lat = location.getLatitude();
  67.      double lng = location.getLongitude();
  68.      builder.append("(");
  69.      builder.append(lat);
  70.      builder.append(",");
  71.      builder.append(lng);
  72.      builder.append(")");
  73.     
  74.      }else{
  75.      builder.append("沒有訊息");
  76.      }
  77.      }
  78.      tv.setText(builder);
  79.     }
  80. }
3.記得在Androidmanifest文件中</application>後宣告權限,此宣告為採用GPS_PROVIDER。
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
 4.在真實的設備當中要獲得定位服務需要有GPS硬體支援,但在開發或測試,使用模擬器是最方便的。將Eclipse切換到DDMS模式,在Emulator control中可以找到定位服務選項,選項可以手動發送經緯度、GPX、KML格式數據來測試定位服務。如果發現選項無法調整及發送(呈現灰色),原因可能是尚未選擇裝置,在Devices中選擇裝置。

          星期六, 10月 15, 2011

          Location and Maps (三)

          Android應用程式學習筆記

          Defining a Model for the Best Performance

          以定位為基礎的應用程式現在已司空見慣,但是由於不到理想準確度、用戶移動、眾多獲得位置的方法、保存電力,因此取得用戶位置變得複雜。為克服取得一個好的用戶位置又兼顧維護電力的障礙,你必須定義兼容的模型,模型指定應用程式如何取得用戶位置。模型包括何時開始及停止監聽更新,何時使用緩存的位置數據。


          Flow for obtaining user location

          以下是獲得用戶位置的典型流程:

          1. 開始應用程式。
          2. 一段時間後,開始監聽預期位置提供器的更新。
          3. 維護篩選出新的"目前最佳估計"位置,但缺乏固定準確度。
          4. 停止監聽更新。
          5. 利用最後最佳位置估計的優勢。
          圖一演示在時間軸上的模型,視覺化應用程式何時監聽位置更新及事件發生的時間。



          Deciding when to start listening for updates

          你可能會想在應用程式啟動時就開始監聽更新,或只在用戶激活某功能時。小心較長的監聽位置窗口消耗較多的電力,但較短又無法達到足夠的準確度。

          如上述,你可以呼叫requestLocationUpdates()方法監聽位置更新。


          LocationProvider locationProvider = LocationManager.NETWORK_PROVIDER;
          // Or, use GPS location data:
          // LocationProvider locationProvider = LocationManager.GPS_PROVIDER;
          
          locationManager.requestLocationUpdates(locationProvider, 0, 0, locationListener);

          Getting a fast fix with the last known location

          你的位置監聽器鳩收第一個位置所花的時間通常為用戶等待時間過長,直到更加正確的位置提供給你的位置監聽器,你應該呼叫getLastKnownLocation()方法使用暫存的位置。


          LocationProvider locationProvider = LocationManager.NETWORK_PROVIDER;
          // Or use LocationManager.GPS_PROVIDER
          Location lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);

          Deciding when to stop listening for updates

           決定新的修復的邏輯不再需要根據你的應用程式從簡單到複雜的,何時獲得定位和何時需要使用定位之間最短的距離,改善估計的準確度,永遠都要注意長時間的監聽會消耗許多電力,所以當你取得你需要的資訊,就應該呼叫removeUpdates(PendingIntent)立即停止監聽更新。


          // Remove the listener you previously added
          locationManager.removeUpdates(locationListener);



          Maintaining a current best estimate

          你也許會期望大部分的位置修復是準確的,然而,因為位置修復的準確度多變,大部分的修復都不是最佳的,你必須有邏輯地從許多標準選擇位置修復,標準也依應用程式的使用與測試領域變化。

          以下有幾個步驟可以驗證位置修復的準確度:

          • 檢查檢索的位置是否明顯的比前一次估計的新。
          • 檢查定位聲明的準確度是否比前一次估計的來的更好或更糟。
          • 檢查新的位置是哪一個提供器及決定更相信哪一個提供器。
          以下是邏輯的闡述例子:


          private static final int TWO_MINUTES = 1000 * 60 * 2;
          /** Determines whether one Location reading is better than the current Location fix
            * @param location  The new Location that you want to evaluate
            * @param currentBestLocation  The current Location fix, to which you want to compare the new one
            */
          protected boolean isBetterLocation(Location location, Location currentBestLocation) {
              if (currentBestLocation == null) {
                  // A new location is always better than no location
                  return true;
              }
          
              // Check whether the new location fix is newer or older
              long timeDelta = location.getTime() - currentBestLocation.getTime();
              boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
              boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
              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 true;
              // If the new location is more than two minutes older, it must be worse
              } else if (isSignificantlyOlder) {
                  return false;
              }
          
              // Check whether the new location fix is more or less accurate
              int accuracyDelta = (int) (location.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(location.getProvider(),
                      currentBestLocation.getProvider());
          
              // Determine location quality using a combination of timeliness and accuracy
              if (isMoreAccurate) {
                  return true;
              } else if (isNewer && !isLessAccurate) {
                  return true;
              } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
                  return true;
              }
              return false;
          }
          /** Checks whether two providers are the same */
          private boolean isSameProvider(String provider1, String provider2) {
              if (provider1 == null) {
                return provider2 == null;
              }
              return provider1.equals(provider2);
          }


          Adjusting the model to save battery and data exchange

          當你測試你的應用程式,你可能發現你的模型要提供優異的定位及優異的表現需要一些調整,這裡也一些事你可能需要改變找出兩著之間的平衡。

          Reduce the size of  the window

          較小的監聽位置更新視窗意味著與GPS和Network location services較少的互動,因此保住電池的壽命,但是它也提供較少的位置選擇最佳的估計。

          Set the location providers to return updates less frequently

          減少新的更新出現在視窗的頻率也可以改善電池的壽命,但是準確度較低,這兩者之間的權衡依賴你的應用程式如何使用,你可以減少更新頻率,透過呼叫requestLocationUpdates()方法中的參數。

          Restrict a set of providers

          依據你的應用程式使用或是準確度的需求的環境,選擇只採用Network location provider或是只採用GPS,取代兩者皆採用,

          星期五, 10月 14, 2011

          Location and Maps (二)

          Android應用程式

          Obtaining User Location

          知道用戶的位置,讓你的應用程式更加智慧,傳遞更多訊息給用戶,當為Android開發一個位置感知的應用程式,你可以採用GPS及Android的Network Location Provider獲得用戶位置,雖然GPS是最準確的,它只在戶外有用,消耗電力快速,無法如用戶預期快速地回應位置。Android的Network Location Provider利用手機信號塔和無線網路提供位置資訊,如此方式它能夠運行於室內及戶外,反應快速,消耗較少電力。在你的應用程式中獲得用戶位置,你可以採用GPS及Android的Network Location Provider,或是其一。


          Challenges in Determining User Location

          從移動裝置獲得用戶位置是複雜的,為什麼位置讀取有錯誤及不準確,以下有幾個原因:

          • 眾多的定位來源
            GPS、Cell-ID、Wi-Fi每個皆可提供線索給用戶,決定採用及信任哪一種,權衡自準確度、速度、電池的消耗。
          • 用戶移動
            因為用戶位置改變,你必須不斷地計算用戶的位置交待用戶移動。
          • 準確度不定
            來自每個位置來源的位置估計它們的準確度並不一致,10秒前在一個來源獲得的位置比起最新從其他來源或同一個來源更加準確。
          這些問題使得獲得可靠的用戶讀取是困難的。


          Requesting Location Updates

          在解決上述定位錯誤之前,先介紹在Android平台上你如何取得用戶位置。

          在Android上獲得用戶位置要藉著回調手段,你表示你要從LocationManager接收位置更新,呼叫requestLocationUpdates()傳入一個LocationListener,你的LocationListener必須呼叫許多回調方法,當用戶位置改變或是服務狀態改變時Location Manager呼叫這些方法。

          舉例,以下程式碼顯示如何定義LocationListener及獲得位置更新。


          // Acquire a reference to the system Location Manager
          LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
          // Define a listener that responds to location updates
          LocationListener locationListener = new LocationListener() {
              public void onLocationChanged(Location location) {
                // Called when a new location is found by the network location provider.
                makeUseOfNewLocation(location);
              }
          
              public void onStatusChanged(String provider, int status, Bundle extras) {}
          
              public void onProviderEnabled(String provider) {}
          
              public void onProviderDisabled(String provider) {}
            };
          // Register the listener with the Location Manager to receive location updates
          locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);

          requestLocationUpdates()的第一個參數是採用哪一種定位提供器形式(此例,手機信號塔及無線網路的Network Location Provider),你可以利用第二及第三個參數控制你的監聽器接收更新的頻率,第二個是控制通知與通知之間的區段最小時間,第三個是控制通知與通知之間最小改變距離,兩個都設為0,表示盡可能獲得定位通知,第四個參數是LocationListener,接收位置更新的回調方法。

          從GPS提供器獲得位置更新,GPS_PROVIDER替代NETWORK_PROVIDER,你也可以從GPS及Network Location Provider獲得位置更新,呼叫requestLocationUpdates()兩次,一次為NETWORK_PROVIDER,一次為GPS_PROVIDER。


          Requesting User Permissions


          為了從NETWORK_PROVIDER或GPS_PROVIDER接收位置更新,你必須獲得用戶權限,分別宣告ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION在Androidmanifest檔案中,例如:


          <manifest ... >
              <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
              ...</manifest>

          沒有這個權限,你的應用程式在runtime要求位置更新會失敗。

          星期四, 10月 13, 2011

          Location and Maps (一)

          Android應用程式學習筆記

          Location and Maps

          以定位和地圖為基礎的應用程式正受到移動裝置用戶的注目,你可以利用android.location和Goole地圖外部函式庫在你的應用程式建立這些功能。以下就來學習相關內容。


          Location Service


          Android讓你的應用程式存取定位服務,透過android.location包中的類別支持裝置,定位架構的核心組件是LocationManager系統服務,它提供APIs決定底層裝置的位置和方位。

          其他系統服務,你不用直接啟動LocationManager,而是,你呼叫getSystemService(Context , LOCATION_SERVICE)方法從系統獲得實例,該方法回傳一個新的LocationManager的實例。

          一旦你的應用程式有一個LocationManager,你的應用程式就能做到三件事:

          • 查詢一系列最後已知的用戶位置的LocationProvider。
          • 註冊/註銷LocationProvider對目前用戶的位置的定期更新。
          • 註冊/註銷預設意圖被解雇,如果裝置接近某經度和緯度。
          相關資訊會在Obtaining User Location中學到。


          Google Maps External Library

          為了讓你能更輕易地將強大的地圖功能加到你的應用程式,Google提供了一個地圖的外部函式庫,包括com.google.android.maps包,com.google.android.maps包中的類別提供內建的地圖的下載、翻譯、緩存,以及各式各樣的顯示選項與控制項。

          地圖包中的關鍵類別是com.google.android.maps.MapView,ViewGroup的子類別,它顯示了一張地圖,數據來自Google Map服務。當MapView在焦距上,它抓取按鍵和觸摸手勢自動地放大縮小地圖。它也提供所有用戶控制地圖必須的使用者介面完素。你的應用程式可利用MapView類別方法控制及繪製其他不同類型在地圖上。

          一般來說,MapView類別提供了一個對Google Map APIs的包裝,讓你的應用程式可以透過類別方法處理Google Map的數據,且它可以讓Map數據與其他View運行。

          地圖外部函式庫不是Android標準函式庫的一部份,所以它無法顯示在一些兼容Android平台的裝置,地圖外部函式庫也不包括SDK提供的標準Android函式庫,所以你可以利用com.google.android.maps包來開發,地圖外部函式庫提供給你加在Android SDk,像是Google APIs加在Android SDK。

          可以從以下網址學到更多資訊。

          注意,為了顯示Google地圖在MapView上,你必須註冊Google Map Service並取得Map APIs金鑰,詳細請見Obtaining a Map APIs Key