編輯:中級開發
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
Android ANR這個錯誤大家並不陌生,但是從Android 2.2開始出錯的ANR信息會自動上傳給Google進行系統分析改進,當然了你的應用ANR錯誤其實保存在
簡介: 學習了解 IBM® Rational® Rhapsody® V7.5.2 版本中的新特性與改進之處,幫助系統管理員和實時、嵌入
簡介: 學習如何使用混合應用程序編程模型為 WebSphere® Commerce 構建移動應用程序。本文描述混合模型,它與其他移動應用程序編程模型的
(2) RelativeLayout相對布局,它是依靠與父容器,同一容器中其它控件的相對位置來排列顯示的。主要常用的屬性如下:相對父容器的屬性:android:layo