Android應用開發實戰GPS與加速度傳感器 android
本文將爲讀者詳細介紹Android中加強現實應用程序的兩個關鍵元素:GPS與加速度傳感器。 git
所需工具 安全
下面是本文中將用到的工具: ide
如何與衛星通訊 函數
在實現了Android加強現實引擎的前兩個元素即攝像頭與指南針以後,下一步要作的就是肯定位置。爲了完成這項任務,咱們主要用到Android的LocationManager對象。不過在此以前,咱們還需首先解決一些其餘問題,其中權限是咱們首先要掃除的第一個障礙。 工具
Android的LocationManager支持兩種權限請求: 佈局
1. 須要告知系統您但願取得用戶的位置。 spa
2. 須要告訴它您想要十分詳細的地理信息。 插件
您須要在AndroidManifest.xmlxml 文件標籤內的標籤中請求這兩種權限,以下所示: 線程
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--><uses-permission android:name="android.permission.LOCATION"/>
對於細粒度的位置更新,也就是近距離顯示有關對象,還須要添加如下內容:
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
若是沒有這兩行,當您試圖註冊位置更新時,Android就將返回一個安全異常,從而致使您的應用關閉。
獲取位置管理器
得到位置管理器看起來好像挺簡單的,可是仍是得牢記一些事項。首先,咱們也許只能在UI主線程中請求位置管理器。咱們要麼在有關動做的onCreate調用中請求LocationManager對象,要麼使用LocationManager請求建立一個運行於主線程的可執行對象。
爲簡單起見,下面的示例代碼將從一個動做的onCreate方法中註冊LocationManager更新。
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->public void onCreate(Bundle savedInstanceState)
{
LocationManager locMan;
locMan =
(LocationManager)getSystemService(Context.LOCATION_SERVICE);
locMan.requestLocationUpdates(LocationManager.GPS_PROVIDER,
100, 1, gpsListener);
}
如您所見,這裏聲明瞭一個LocationManager對象,使用getSystemService得到您的對象,而後調用了requestLocationUpdates。
您可能想知道位置更新時須要哪些參數。首先,您告訴系統,您想使用系統中GPS裝置的位置更新功能。而後,您告訴它您但願多長時間更新一次(本例時間間隔爲100ms),而且每當移動一米以上時就更新。這樣,就能迅速識別他們的移動狀況並調整它們與其餘對象的位置關係。最後,傳入實現LocationListener接口的類的實例。
位置更新的偵聽藝術
爲位置更新傳遞請求後,LocationListener類將收到初始位置,繼之之後來位置的改變狀況。下面是咱們的LocationListener:
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->LocationListener gpsListener = new LocationListener(){
Location curLocation;
boolean locationChanged = false;
public void onLocationChanged(Location location)
{
if(curLocation == null)
{
curLocation = location;
locationChanged = true;
}
if(curLocation.getLatitude() == location.getLatitude() &&
curLocation.getLongitude() == location.getLongitude())
locationChanged = false;
else
locationChanged = true;
curLocation = location;
}
public void onProviderDisabled(String provider){}
public void onProviderEnabled(String provider){}
public void onStatusChanged(String provider, int status, Bundle extras){}
};
在上面的代碼中,咱們惟一須要關心的就是onLocationChanged這個方法。然而,咱們還會介紹這個對象的其它方法,以便您將這個對象複製到您本身的代碼中時可以瞭解它們。 一旦衛星鎖定了這個設備,方法onLocationChanged就會被調用,以後每通過在請求更新時指定的時間間隔(本例中爲100ms)後,就會調用一次。
每當位置更新時,都會帶來一個Location對象。咱們經過這個類能夠得到目標的經緯度,並完成許多重要事情。這裏咱們最感興趣的方法是getLatitude()、getLongitude()、bearingTo()與distanceTo()。使用這四個函數,咱們能夠計算出任何隨後的位置的方位角,並肯定出離您的距離有多遠。
請求加速度傳感器數據
爲了實現咱們的加強現實引擎,最後還須要用到加速度傳感器數據。不過,Android已經爲咱們簡化了這些數據的收集工做。在上一篇介紹加強現實技術的文章中,咱們的示例程序能夠請求手機的方位,並調用位置管理器對象中的registerListener來檢索指南針數據。咱們也可使用一樣的技術來請求加速度傳感器數據,咱們用來請求加速度傳感器數據的代碼以下所示:
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->sensorMan = (SensorManager) ctx.getSystemService(Context.SENSOR_SERVICE);
sensorMan.registerListener(listener,
sensorMan.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_FASTEST);
咱們調用了上下文對象(上述代碼中爲ctx)的getSystemService方法。下面是用於方向監聽器與加速度傳感器監聽器的完整代碼。
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->private SensorEventListener listener = new SensorEventListener(){
public static volatile float direction = (float) 0;
public static volatile float inclination;
public static volatile float rollingZ = (float)0;
public static volatile float kFilteringFactor = (float)0.05;
public static float aboveOrBelow = (float)0;
public void onAccuracyChanged(Sensor arg0, int arg1){}
public void onSensorChanged(SensorEvent evt)
{
float vals[] = evt.values;
if(evt.sensor.getType() == Sensor.TYPE_ORIENTATION)
{
float rawDirection = vals[0];
direction =(float) ((rawDirection * kFilteringFactor) +
(direction * (1.0 - kFilteringFactor)));
inclination =
(float) ((vals[2] * kFilteringFactor) +
(inclination * (1.0 - kFilteringFactor)));
if(aboveOrBelow > 0)
inclination = inclination * -1;
if(evt.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
{
aboveOrBelow =
(float) ((vals[2] * kFilteringFactor) +
(aboveOrBelow * (1.0 - kFilteringFactor)));
}
}
}
};
呵呵,這裏的代碼稍微有點多,下面咱們來了解一下。首先,要爲監聽器設置全部的值。這意味着,您能夠隨時能夠向監聽器查詢指南針方位與手機傾角。這些值會隨着您請求的更新的類型的不一樣而有所變化。
而後,咱們會收到傳感器信息,這時須要肯定出兩種主要信息:
1. 手機指向
2. 屏幕相對於水平面的傾角
第一種信息稱爲方位角;第二種信息稱爲傾角。爲了肯定這些值,第一個計算任務就是過濾出攝像頭的指南針運動。這稱爲翻轉過濾器(rolling filter)。變量direction用於指出手機頂部指向哪裏,而非攝像頭自己指向哪裏,因此咱們須要進行一些校訂。
第二個數學計算任務是利用翻轉過濾器對斜度進行處理,從而獲得一個以度爲單位的度量值,其中水平的度量值爲90,向上或向下半傾的度量值爲45,垂直向上或垂直向下的度量值爲0。注意,當得數爲45的時候,咱們沒法肯定手機究竟是向上傾斜,仍是向下傾斜。 這時加速度傳感器就派上用場了。它可以肯定出傾角的正負,正值表示從水平線向上,複製表示從水平線向下。
簡言之,咱們須要的東西都能從加速度傳感器那裏獲得。
加強現實技術的構件
到目前爲止,打造本身加強現實技術引擎所需的工具咱們已經所有介紹過了,您還須要的就是少量數學知識、一些Android版面佈局和大量的精力了。若是您對打造加強現實應用程序的興趣遠勝於打造加強現實引擎自己的話,能夠關注我當前正在爲Android開發的一個開源的加強現實技術引擎。爲了得到更多的進展狀況,能夠在Twitter上跟隨twitter.com/androidarkit。
雖然我喜歡儘量把全部的數學和繪圖代碼放在一塊兒,並將三種信息統一疊放到攝像頭上,可是這些已經超出了本文的討論範圍。然而,本文加上上一篇文章,已經構成了對Android的指南針、攝像頭預覽、加速度傳感器與GPS子系統進行了全面的介紹。如今,您已經具有了建立大型加強現實技術應用程序所需的所有構件。