Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 中級開發 >> Android特色開發之Google Map和桌面組件(2)

Android特色開發之Google Map和桌面組件(2)

編輯:中級開發

9.3.4  定位系統

全球定位系統(Global Positioning System,GPS)又稱為全球衛星定位系統,是一個中距離圓型軌道衛星導航系統,它可以為地球表面的絕大部分地區(98%)提供准確的定位、測速和高精度的時間標准。該系統由美國國防部研制和維護,可滿足位於全球任何地方或近地空間的軍事用戶連續、精確地確定三維位置、三維運動和時間的需要。該系統包括太空中的24顆GPS衛星,地面上的1個主控站、3個數據注入站和5個監測站及作為用戶端的GPS接收機。最少只需其中3顆衛星,就能迅速確定用戶端在地球上所處的位置及海拔高度。所能連接到的衛星數越多,解碼出來的位置就越精確。GPS廣泛應用於軍事、物流、地理、移動電話、數碼相機、航空等領域,具有非常強大的功能,主要包括:

·精確定時:廣泛應用在天文台、通信系統基站、電視台中。

·工程施工:道路、橋梁、隧道的施工中大量采用GPS設備進行工程測量。

·勘探測繪:野外勘探及城區規劃中都有用到。

·導航。

···武器導航:精確制導導彈、巡航導彈。

···車輛導航:車輛調度、監控系統。

···船舶導航:遠洋導航、港口/內河引水。

···飛機導航:航線導航、進場著陸控制。

···星際導航:衛星軌道定位。

···個人導航:個人旅游及野外探險。

·定位。

···車輛防盜系統。

···手機、PDA、PPC等通信移動設備防盜以及電子地圖、定位系統。

···兒童及特殊人群的防走失系統。

·精准農業:農機具導航、自動駕駛以及土地高精度平整。

Android 支持地理定位服務的API。該地理定位服務可以用來獲取當前設備的地理位置,應用程序可以定時請求更新設備當前的地理定位信息。比如應用程序可以借助一個 Intent接收器來實現如下功能:以經緯度和半徑劃定一個區域,當設備出入該區域時,發出提醒信息,還可以和Google Map API一起使用,完成更多的任務。關於地理定位系統的API全部位於android.location包內,其中包括以下幾個重要的功能類:

·LocationManager:本類提供訪問定位服務的功能,也提供獲取最佳定位提供者的功能。另外,臨近警報功能也可以借助該類來實現。

·LocationProvider:該類是定位提供者的抽象類。定位提供者具備周期性報告設備地理位置的功能。

·LocationListener:提供定位信息發生改變時的回調功能。必須事先在定位管理器中注冊監聽器對象。

·Criteria:該類使得應用能夠通過在LocationProvider中設置的屬性來選擇合適的定位提供者。

·Geocoder:用於處理地理編碼和反向地理編碼的類。地理編碼是指將地址或其他描述轉變為經度和緯度,反向地理編碼則是將經度和緯度轉變為地址或描述語言,其中包含了兩個構造函數,需要傳入經度和緯度的坐標。getFromLocation方法可以得到一組關於地址的數組。

要使用地理定位,首先需要取得LocationManager的實例,在android中,獲得LocationManager的唯一方法是通過 getSystemService()方法的調用。通過使用LocationManager,我們可以獲得一個位置提供者的列表。在一個真實的手持設備中,這個列表包含了一些GPS服務。我們也可以選擇更強大、更精確、不帶有其他附加服務的GPS。代碼如下:

     LocationManager?locationManager?=?(LocationManager)?getSystemService(Context.LOC-

     ATION_SERVICE);?

取得LocationManager對象之後,我們還需要注冊一個周期性的更新視圖,代碼如下:

     locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000, 0,

     locationListener);   

其中第一個參數是設置服務提供者,第二個參數是周期,這裡需要重點說明一下最後一個參數locationListener,它用來監聽定位信息的改變,所以我們必須實現以下幾個方法:

·onLocationChanged(Location location):當坐標改變時觸發此函數,如果Provider傳進相同的坐標,它就不會被觸發。  

·onProviderDisabled(String provider):Provider禁用時觸發此函數,比如GPS被關閉。

·onProviderEnabled(String provider):Provider啟用時觸發此函數,比如GPS被打開。  

·onStatusChanged(String provider, int status, Bundle extras):Provider的轉態在可用、暫時不可用和無服務三個狀態直接切換時觸發此函數。

下面我們通過更改上一節的例子(本書所附代碼:第9章\Examples_09_04)來實現自動通過定位系統獲取用戶當前的坐標,然後加載並顯示地圖,將坐標信息顯示在一個TextVIEw中,運行效果如圖9-15所示。

 

圖9-15 地圖定位

要使用定位的API,首先需要在androidManifest.XML文件中添加其權限,具體代碼如代碼清單9-5所示。

     代碼清單9-5  第9章\Examples_09_04\androidManifest.XML

     <?XML version="1.0" encoding="utf-8"?>

     <manifest XMLns:android="http://schemas.android.com/apk/res/android"

           package="com.yarin.android.Examples_09_04"

           android:versionCode="1"

           android:versionName="1.0">

         <application android:icon="@drawable/icon" android:label="@string/app_name">

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

             <activity android:name=".Activity01"

                       android:label="@string/app_name">

                 <intent-filter>

                     <action android:name="android.intent.action.MAIN" />

                     <category android:name="android.intent.category.LAUNCHER" />

                 </intent-filter>

             </activity>

         </application>

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

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

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

         <uses-sdk android:minSdkVersion="5" />

     </manifest>

由於我們在模擬器上測試,所以需要人為設置一個坐標。可以通過兩種方法來設置一個模擬的坐標值。第一種方法是通過DDMS,我們可以在 Eclipse的ADT插件中使用這種方法,只要啟動Eclipse,選擇“Window”->“Show VIEw”,打開“Emulator Control”界面即可看到如下的設置窗口,我們可以手動或者通過KML和GPX文件來設置一個坐標。如圖9-16所示。

 

圖9-16  設置顯示的坐標

另一種方法是使用geo命令,我們需要telnet到本機的5554端口,然後在命令行下輸入類似於geo fix-121.45356 46.51119 4392 這樣的命令,後面3個參數分別代表了經度、緯度和(可選的)海拔。設置之後在android模擬器屏幕上便多出一個如圖9-17所示的標志,表示模擬了 GPS權限。

 

圖9-17  GPS使用標志

現在我們可以使用位置管理器(LocationManager)和位置提供者進行getFromLocation的調用。這個方法返回本機當前位置的一個快照,這個快照將以 Location對象形式提供。在手持設備中,我們可以獲得當前位置的經度和緯度;調用getFromLocationName方法可能返回一個數據,表示一個地方的名稱。該例中我們還創建了一個菜單用來縮放地圖,這時就使用地圖控制器(MapController)的zoomIn和zoomOut方法來放大和縮小視圖,具體實現如代碼清單9-6所示。

     代碼清單9-6  第9章\Examples_09_04\src\com\yarin\android\Examples_09_04\Activity01.Java

     public class Activity01 extends MapActivity

     {

         public MapController mapController;

         public MyLocationOverlay myPosition;

         public MapView myMapVIEw;

         private static final int ZOOM_IN=Menu.FIRST;

         private static final int ZOOM_OUT=Menu.FIRST+1;

    

     public void onCreate(Bundle savedInstanceState) {

             super.onCreate(savedInstanceState);

             setContentVIEw(R.layout.main);

             //取得LocationManager實例

             LocationManager locationManager;

             String context=Context.LOCATION_SERVICE;

             locationManager=(LocationManager)getSystemService(context);

             myMapView=(MapView)findViewById(R.id.MapVIEw01);

             //取得MapController實例,控制地圖

             mapController=myMapVIEw.getController();

             //設置顯示模式

             myMapVIEw.setSatellite(true);

             myMapView.setStreetVIEw(true);

             //設置縮放控制,這裡我們自己實現縮放菜單

             myMapVIEw.displayZoomControls(false);  

             //設置使用MyLocationOverlay來繪圖

             mapController.setZoom(17);

             myPosition=new MyLocationOverlay();

             List<Overlay> overlays=myMapVIEw.getOverlays();

             overlays.add(myPosition);

             //設置Criteria(服務商)的信息

             Criteria criteria =new Criteria();

             //經度要求

             criteria.setAccuracy(Criteria.ACCURACY_FINE);

             criteria.setAltitudeRequired(false);

             criteria.setBearingRequired(false);

             criteria.setCostAllowed(false);

             criteria.setPowerRequirement(Criteria.POWER_LOW);

             //取得效果最好的criteria

             String provider=locationManager.getBestProvider(criteria, true);

             //得到坐標相關的信息

             Location location=locationManager.getLastKnownLocation(provider);

             //更新坐標

             updateWithNewLocation(location);

             //注冊一個周期性的更新,3000ms更新一次

             //locationListener用來監聽定位信息的改變

             locationManager.requestLocationUpdates(provider, 3000, 0,locationListener);

         }

         private void updateWithNewLocation(Location location)

         {

             String latLongString;

             TextView myLocationText = (TextView)findViewById(R.id.TextVIEw01);

            

             String addressString="沒有找到地址\n";

            

             if(location!=null)

             {

                 //為繪制標志的類設置坐標

                 myPosition.setLocation(location);

                 //取得經度和緯度

                 Double geoLat=location.getLatitude()*1E6;

                 Double geoLng=location.getLongitude()*1E6;

                 //將其轉換為int型

                 GeoPoint point=new GeoPoint(geoLat.intValue(),geoLng.intValue());

                 //定位到指定坐標

                 mapController.animateTo(point);

                 double lat=location.getLatitude();

                 double lng=location.getLongitude();

                 latLongString="經度:"+lat+"\n緯度:"+lng;

                

                 double latitude=location.getLatitude();

                 double longitude=location.getLongitude();

                 //根據地理環境來確定編碼

                 Geocoder gc=new Geocoder(this,Locale.getDefault());

                 try

                 {

                 //取得地址相關的一些信息、經度、緯度

                     List<Address> addresses=gc.getFromLocation(latitude, longitude,1);

                     StringBuilder sb=new StringBuilder();

                     if(addresses.size()>0)

                     {

                         Address address=addresses.get(0);

                         for(int i=0;i<address.getMaxAddressLineIndex();i++)

                             sb.append(address.getAddressLine(i)).append("\n");

                            

                             sb.append(address.getLocality()).append("\n");

                             sb.append(address.getPostalCode()).append("\n");

                             sb.append(address.getCountryName());

                             addressString=sb.toString();

                     }

                 }catch(IOException e){}

             }

             else

             {

                 latLongString="沒有找到坐標.\n";

             }

             //顯示

             myLocationText.setText("你當前的坐標如下:\n"+latLongString+"\n"+addressString);

         }

         private final LocationListener locationListener=new LocationListener()

         {

         //當坐標改變時觸發此函數

             public void onLocationChanged(Location location)

             {

             updateWithNewLocation(location);

             }

             //Provider禁用時觸發此函數,比如GPS被關閉

             public void onProviderDisabled(String provider)

             {

             updateWithNewLocation(null);

             }

             //Provider啟用時觸發此函數,比如GPS被打開

             public void onProviderEnabled(String provider){}

             //Provider的轉態在可用、暫時不可用和無服務三個狀態直接切換時觸發此函數

             public void onStatusChanged(String provider,int status,Bundle extras){}

         };

         protected boolean isRouteDisplayed()

     {

     return false;

     }

         //為應用程序添加菜單

         public boolean onCreateOptionsMenu(Menu menu)

     {

     super.onCreateOptionsMenu(menu);

     menu.add(0, ZOOM_IN, Menu.NONE, "放大");

     menu.add(0, ZOOM_OUT, Menu.NONE, "縮小");

     return true;

     }

         public boolean onOptionsItemSelected(MenuItem item)

     {

     super.onOptionsItemSelected(item);

     switch (item.getItemId())

     {

     case (ZOOM_IN):

     //放大

     mapController.zoomIn();

     return true;

     case (ZOOM_OUT):

     //縮小

     mapController.zoomOut();

     return true;

     }

     return true;

     }

     class MyLocationOverlay extends Overlay

     {

     Location mLocation;

     //在更新坐標時,設置該坐標,以便畫圖

     public void setLocation(Location location)

     {

     mLocation = location;

     }

     @Override

     public boolean draw(Canvas canvas,MapView mapVIEw,boolean shadow,long when)

     {

     super.draw(canvas, mapVIEw, shadow);

     Paint paint = new Paint();

     Point myScreenCoords = new Point();

     // 將經緯度轉換成實際屏幕坐標

     GeoPoint tmpGeoPoint = new GeoPoint((int)(mLocation.

     getLatitude()*1E6),(int)(mLocation.getLongitude()*1E6));

     mapVIEw.getProjection().toPixels(tmpGeoPoint,myScreenCoords);

     paint.setStrokeWidth(1);

     paint.setARGB(255, 255, 0, 0);

     paint.setStyle(Paint.Style.STROKE);

     Bitmap bmp = BitmapFactory.decodeResource(getResources(),

     R.drawable.home);

     canvas.drawBitmap(bmp,myScreenCoords.x,myScreenCoords.y,paint);

     canvas.drawText("Here am I",myScreenCoords.x,myScreenCoords.

     y, paint);

     return true;

     }

     }

     }

9.4  桌面組件

第一次啟動android模擬器時,可以看到在桌面上有很多圖標,如圖9-18所示的Google搜索框、時鐘、聯系人、浏覽器等,點擊這些圖標,系統就會執行相應的程序,與PC操作系統桌面上的快捷方式很像,但是它不完全是快捷方式,還包括了實時文件夾(Live Folder)和桌面插件(Widget),這樣既美觀又方便用戶操作。本節將學習這每一種桌面組件的開發,讓我們自己的應用程序也能輕松地放置到桌面上。

 

圖9-18 android桌面組件

9.4.1  快捷方式

首先我們學習最基本的桌面組件快捷方式,它和PC上的快捷方式一樣,用於啟動某一應用程序的某個組件(如Activity、Service等)。其實要在桌面上添加一個快捷方式很簡單,只需要長按桌面或者點擊“Menu”按鍵(如圖9-19所示),就可以彈出添加桌面組件的選項,如圖9-20所示,“Shortcuts”為添加快捷方式,“Widgets”為Widget開發的桌面插件,“Folders”為實時文件夾,進入相應的選項後即可添加相應的桌面組件。

 

       圖9-19  Menu菜單                                  圖9-20  添加桌面組件

本小節重點介紹在應用程序中通過代碼來將一個應用程序添加到圖9-20的Shortcuts列表中,這裡添加一個發送郵件的應用到快捷方式列表上去(參見本書所附代碼:第9章\Examples_09_05)。

首先需要在Activity注冊時添加一個Action為android.intent.action.CREATE_SHORTCUT的IntentFilter,如代碼清單9-7所示,添加之後列表中就會出現該應用的圖標和名字了。

     代碼清單9-7  第9章\Examples_09_05\androidManifest.XML

     <?XML version="1.0" encoding="utf-8"?>

     <manifest XMLns:android="http://schemas.android.com/apk/res/android"

           package="com.yarin.android.Examples_09_05"

           android:versionCode="1"

           android:versionName="1.0">

         <application android:icon="@drawable/icon" android:label="@string/app_name">

             <activity android:name=".Activity01"

                       android:label="@string/app_name">

                 <intent-filter>

                   <action android:name="android.intent.action.MAIN" />

                   <category android:name="android.intent.category.LAUNCHER" />

     <action android:name="android.intent.action.CREATE_SHORTCUT"/>

                 </intent-filter>

             </activity>

         </application>

         <uses-sdk android:minSdkVersion="5" />

     </manifest>


本文來自CSDN博客,轉載請標明出處:http://blog.csdn.Net/L_serein/archive/2011/01/07/6122116.ASPx

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