Android開發10:傳感器器及地圖相關應用


前言

  啦啦啦~各位小伙伴們好~經過這一學期的Android知識的學習,我們學到了很多和Android開發相關的知識,這一學期的學習也要告一段落了。(博客中有很多照片上有代碼,代碼文本較小,各位可按下Ctrl和前滾輪放大后再看~)

  一起進入我們今天的相關內容~這次我們將一起學習使用 android 手機不同的傳感器,包括磁強計、加速度傳感器等。學會使用 android 位置服務獲得經緯度信息。學會使用百度地圖基礎API進行地圖應用的開發。

 

基礎知識

一、傳感器簡介

      手機中內置的傳感器是一種微型的物理設備,它能夠探測、感受到外界的信號,並按一定規律轉換成我們所需要的信息。Android 手機通常都會支持多種類型的傳感器,如光照傳感器、加速度傳感器、地磁傳感器、壓力傳感器、溫度傳感器等。

      當然,Android 系統只是負責將這些傳感器所輸出的信息傳遞給我們,至於具體如何去利用這些信息就要充分發揮開發者的想象力了。

二、Android傳感器框架

  Android SDK為我們提供了ASF,可以用來訪問當前Android設備內置的傳感器。ASF提供了很多類和接口,幫助我們完成各種與傳感器有關的任務。例如:

1)確定當前Android設備內置了哪些傳感器。

2)確定某一個傳感器的技術指標。

3)獲取傳感器傳回來的數據,以及定義傳感器回傳數據的精度。

4)注冊和注銷傳感器事件監聽器,這些監聽器用於監聽傳感器的變化,通常從傳感器回傳的數據需要利用這些監聽器完成。

  ASF允許我們訪問很多傳感器類型,這些傳感器有一些是基於硬件的傳感器,還有一些是基於軟件的傳感器。基於硬件的傳感器就是直接以芯片形式嵌入到Android設備中,這些傳感器直接從外部環境獲取數據。基於軟件的傳感器並不是實際的硬件芯片,基於軟件的傳感器傳回的數據本質上也來自於基於硬件的傳感器,只是這些數據通常會經過二次加工。所以基於軟件的傳感器也可以稱為虛擬(virtual)傳感器或合成(synthetic)傳感器。

  Android對每個設備的傳感器都進行了抽象,其中SensorManger類用來控制傳感器,Sensor用來描述具體的傳感器,SensorEventListener用來監聽傳感器值的改變。

 

(1)SensorManager類

  用於創建sensor service的實例。該類提供了很多用於訪問和枚舉傳感器,注冊和注銷傳感器監聽器的方法。而且還提供了與傳感器精度、掃描頻率、校正有關的常量。

(2)Sensor類

  Sensor類為我們提供了一些用於獲取傳感器技術參數的方法。如版本、類型、生產商等。例如所有傳感器的TYPE類型如下:

序號 傳感器 Sensor類中定義的TYPE常量
1 加速度傳感器 TYPE_ACCELEROMETER
2 溫度傳感器 TYPE_AMBIENT_TEMPERATURE
3 陀螺儀傳感器 TYPE_GYROSCOPE
4 光線傳感器 TYPE_LIGHT
5 磁場傳感器 TYPE_MAGNETIC_FIELD
6 壓力傳感器 TYPE_PRESSURE
7 臨近傳感器 TYPE_PROXIMITY
8 濕度傳感器 TYPE_RELATIVE_HUMIDITY
9 方向傳感器 TYPE_ORIENTATION
10 重力傳感器 TYPE_GRAVITY
11 線性加速傳感器 TYPE_LINEAR_ACCELERATION
12 旋轉向量傳感器 TYPE_ROTATION_VECTOR

  注意:1-8是硬件傳感器,9是軟件傳感器,其中方向傳感器的數據來自重力和磁場傳感器,10-12是硬件或軟件傳感器。

(3)SensorEvent類

  系統使用該類創建傳感器事件對象。該對象可以提供與傳感器事件有關的信息。傳感器事件對象包括的信息有原始的傳感器回傳數據、傳感器類型、數據的精度以及觸發事件的時間。

(4)SensorEventListener接口

該接口包含兩個回調方法,當傳感器的回傳值或精度發生變化時,系統會調用這兩個回調方法。

/**
 * 傳感器精度變化時回調
 */
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) { } /** * 傳感器數據變化時回調 */ @Override public void onSensorChanged(SensorEvent event) { }

 到了這里,我們就可以進行傳感器開發工作了。

 

實驗內容

本次實驗主要是涉及傳感器及地圖相關應⽤,實現簡單的地圖功能。

實現最終結果實現效果如圖所示:

    

                                             實驗效果圖

 

主要分為以下三部分

a) 調用百度地圖SDK實現地圖的展示以及交互,其中包括左下角的按鈕要求實現的功能如下:

i. 當按鈕處於狀態時:如果GPS位置有更新,那么更新用戶當前所在位置,並使得當前位置的箭頭圖標一直保持在屏幕中心。

ii. 按鈕處於 狀態時,更新當前位置的箭頭的時候不移動地圖。

iii. 點擊按鈕可以切換這兩種狀態,當按鈕進入狀態的時候,使得表示當前位置的箭頭位於屏幕中央。

iv. 如果按鈕處於 的狀態手動平移百度地圖的時候,地圖進行平移並且按鈕變為 狀態。

b) 獲取當前所在位置與方向,並在百度地圖上顯示出來,如圖中黑色箭頭所示,箭頭中心位置為定位結果,箭頭方向為手機的朝向。

c) 實現簡單搖一搖功能,當晃動手機的時候作出相應的響應。

 

實驗過程

  1. 首先要申請百度的開發者密鑰(申請密鑰 Android SDK http://lbsyun.baidu.com/index.php?title=androidsdk/guide/key),申請地址:http://lbsyun.baidu.com/apiconsole/key

首先,在申請AK的表單中選擇AndroidSDK,發現還要輸入發布版SHA1以及報名這兩個信息。

 

  其中,應用包名為build.gradle里的ApplicationId,並且保證這個ApplicationId與Manifest里的package字段名是一樣的(如下圖所示)。

                              Manifest 里的應用包名

 

                               build.gradle 里的應用包名

 

  發布版SHA1為了方便直接使用Android默認的debug.keystore里的SHA1,進入用戶文件夾(Windows為C:\Users\username,Linux為/home/username,Mac為/Users/username)后,輸入如下命令即可看到SHA1值(輸入密鑰庫口令里直接回車)

證書指紋里的SHA1值為在申請應用AK的時候需要填寫的。


點擊確定后即可得到一個Android SDK的應用AK:

              成功申請應用 AK

 

  下載百度地圖SDK的依賴庫<BaiduLBS_AndroidSDK_Lib.zip>,按照百度地圖SDK配置環境與發布 (配置環境及發布 Android SDK :http://lbsyun.baidu.com/index.php?title=androidsdk/guide/buildproject) 把依賴庫放到相應的文件夾並添加到工程里,並按照HelloBaiduMap (Hello BaiduMap:http://lbsyun.baidu.com/index.php?title=androidsdk/guide/hellobaidumap)中的步驟,在AndroidManifest.xml文件里添加權限以及應用AK。

 

  特別的,由於Android API 23以上需要動態申請權限,這里使用一個Github上的開源工具RxAndroid( https://github.com/ReactiveX/RxAndroid)進行處理,也可以自己根據Android官方的API進行或者其他的工具。首先需要在build.gradle中加入需要的依賴項:

  然后新建一個啟動的Activity,在這個單獨的Activity的onCreate方法里檢查是否獲取需要的權限,如果沒有則直接退出程序,實現代碼參考如下:

 

  本次實驗主要涉及使用 android 手機不同的傳感器,包括磁強計、加速度傳感器等,使用 android 位置服務獲得經緯度信息,使用百度地圖基礎 API 進行地圖應用的開發。

  首先按照文檔中的要求申請百度的開發者密鑰,並正確申請 AK(應用包名為build.gradle里的ApplicationId,並且保證這個ApplicationId與Manifest里的 package 字段名是一樣的):

 

  按照百度地圖 SDK 配置環境與發布把依賴庫放到相應的文件夾並添加到工程里,並按照 HelloBaiduMap 中的步驟,在 AndroidManifest.xml 文件里添加權限以及應用 AK:

這里進行 so 的配置時,在 app 工程路徑下,新建 libs,並在 libs 目錄下放入對應不同 CPU 架構的 so 文件。

  這樣工程並不會自動加載 libs 下的 so,需在gradle 編譯時,通過加入代碼:jniLibs.srcDir 'libs' 來說明 so 的路徑為該libs 路徑。代碼如下:

由於 Android API 23 以上需要動態申請權限,這里使用開源工具 RxAndroid進行處理(具體方法之前已敘述過,這里就不再贅述)。

 

接下來通過使用傳感器來獲取手機的方向信息和位置信息。

  手機的方向信息是通過地磁傳感器和加速度傳感器共同計算出來的,需要獲取地磁傳感器和加速度傳感器的信息(調用手機大多數傳感器首先需要獲取傳感器的管理器,傳感器都需要由這個傳感器管理器進行管理,包括注冊傳感器注銷傳感器等操作)。

  獲取用戶的經緯度信息需要使用位置管理器 LocationManager ,同時需要確認手機打開了位置服務。位置服務有一個位置的數據來源稱為 provider ,可以分為 NETWORK_PROVIDER 和 GPS_PROVIDER ,其中 NETWORK_PROVIDER 使用基站和 Wi-Fi 信號來決定用戶的位置,更新速度更快耗電量更少,但可能精確度較低,而 GPS_PROVIDER 使用 GPS 衛星進行定位,精度高但只能在室外使用,耗電量也更高。在使用過程中可以選擇使用其中一個 provider,也可以兩個provider 同時使用。在判斷使用哪個 Provider 的時候,首先使用 isProviderEnabled 函數判斷該 Provider 是否已經啟用,從而選取一個合適的 Provider:

  在 Activity 在前台運行(onResume)的時候注冊傳感器,在離開前台(onPause)的時候取消注冊。同時在注冊傳感器的時候,需要指定傳感器的監聽器,當傳感器數據更新的時候,系統會回調監聽器里的 onSensorChange 函數,可以在這里對傳感器數據進行相應處理:

  手機的朝向是通過地磁傳感器和加速度傳感器共同計算出來,Android 提供了計算這個數值的 API,首先通過 getRotationMatrix 得到一個旋轉矩陣,然后使用 getOrientation 得到手機的朝向:

  在使用加速度傳感器的時候我們可以實現檢測手機搖一搖的功能,這里我實現了通過搖一搖,彈出是否退出應用的對話框,選擇是則退出應用:

  對於位置信息的更新,可以注冊 LocationListener 監聽位置信息的更新並作出相應的處理,使用 getLastKnownLocation 可以立刻獲得一個位置坐標,如果之前有進行過定位操作,那么這個位置就是之前獲取到的位置緩存,如果沒有獲得或位置,那么返回一個空對象:

 

  接下來實現地圖的相關功能。首先,寫好界面的 XML 布局文件。這里我們在布局文件里添加百度地圖並需要設置一個 ToggleButton,並將 ToggleButton 背景設為@drawable/state,實現按鈕背景圖片的切換。

XML 文件如下:

背景 state.xml 文件如下:

 

  在 Activity 中初始化百度地圖正常顯示地圖后,需要使用百度地圖里MyLocationConfiguration 添加當前所在位置的箭頭,並根據用戶方向以及位置構造 MyLocationData ,相應設置箭頭的方向與位置:

  LocationManager 返回的 Location 中的坐標系與百度地圖的坐標系並不一樣,需要進行坐標系的轉換,最后 LatLng 得到的經緯度為百度地圖坐標系下的經緯度:

  在地圖中使顯示手機朝向的箭頭居中是使用 MapStatus 實現的(這里設置ToggleButton 為 cheaked 狀態時顯示手機朝向的箭頭居中):

實現 BaiduMap 中的setOnMapTouchListener 函數來實現手動拖動地圖平移之后按鈕變化的功能:

  在 ToggleButton 點擊事件、傳感器監聽器等位置再次實現獲取當前位置信息的功能實現當按鈕處於狀態一時,如果 GPS 位置有更新,那么更新用戶當前所在位置,並使得當前位置的箭頭圖標一直保持在屏幕中心;按鈕處於狀態二時,更新當前位置的箭頭的時候不移動地圖。

 

完成實驗~

 

可能遇到的問題及解決方法

  在使用 locationManager.getLastKnownLocation(provider);時報錯,出現Call requires permission which may be rejected by user. Code shouldexplicitly check to see if permission is available.的錯誤,不知道怎樣解決。

解決方案:

  在查詢了網上資料之后,了解到 Android 6.0 (SDK API level 23)新增了動態獲取權限的特性。在獲取用戶信息時,需要檢查用戶是否授權,如果沒有授權則需要向用戶請求授權,對 Android 版本做兼容處理,對於 Android 6 及以上版本需要向用戶請求授權,而低版本的則直接調用。

在加了以下語句后解決了此問題:

參考: http://majing.io/questions/226
    http://blog.5ibc.net/p/62176.html

 

實驗截圖

 

實現搖一搖功能:

 

其他總結

  Android 傳感器框架讓你訪問許多類型的傳感器。這些傳感器的一些事基於硬件的,一些是基於軟件的。基於硬件的傳感器是內嵌到手機或者平板中的物理元件,它們通過直接測量指定的環境屬性來得到它們的數據,例如加速度,磁場強度,或者角度變化。基於軟件的傳感器不是物理設備,盡管它們模仿基於硬件的傳感器。基於軟件的傳感器從一個或更多基於硬件的傳感器獲取它們的數據,並且有時候被稱為虛擬傳感器或者合成傳感器。線性加速度傳感器和重力傳感器是基於軟件傳感器的例子。表 1 總結了 Android 平台支持的傳感器。很少 Android 設備有所有類型的傳感器。例如,大部分手機和平板有一個加速計和磁場計,但是很少的設備擁有氣壓或者溫度傳感器。並且,一個設備可以擁有一個類型不止一個的傳感器。例如,設備能有兩個重力傳感器,每個有不同的范圍。

  大多數 Android 設備有內置的傳感器,來測量運動,方向和各種環境條件。這些傳感器能提供高精度和准確度的原始數據,如果你想監控設備三維運動或者位置,或者你想監控設備周圍的環境變化,是非常有用的。例如,游戲可能跟蹤設備重力傳感器的數據,來推斷復雜的用戶首飾和動作,例如傾斜,震動,旋轉,或者振幅。同樣的,天氣應用可能使用設備的溫度傳感器和濕度傳感器的數據來計算和報告結露點,或者旅行應用可能使用磁場傳感器和加速度傳感器來報告一個指南針方位。

 

Android 平台支持三大類的傳感器:

(1)位移傳感器

這些傳感器測量沿三個軸線測量加速度和旋轉。這類包含加速度,重力傳感器,陀螺儀,和矢量傳感器。

(2)環境傳感器

這些傳感器測量各種環境參數,例如周圍的空氣溫度和壓力,光線,和濕度。這類包含氣壓,光線,和溫度傳感器。

(3)位置傳感器

  這些傳感器測量設備的物理位置。這類包含方向和磁力傳感器。

  我們可以訪問設備上可用的傳感器,並通過使用 Android 傳感器框架獲取原始傳感器數據。傳感器框架提供了一些類和接口,來幫助你執行各種傳感器相關的任務。例如,你能使用傳感器框架做如下事情:

(1)確定什么傳感器在設備上有效。

(2)確定當個傳感器的功能,例如它的最大射程,廠商,電力需求,和分辨率。

(3)獲取原始數據,並定義你獲取傳感器數據的最小速率。

(4)注冊和注銷傳感器事件監聽,來監聽傳感器改變。

 

(額~這段話好繞口~ 話粗理不粗嘛~)

 

源碼下載

  源碼下載點擊這里~

 

1、本實驗實驗環境:

操作系統 Windows 10 

實驗軟件 Android Studio 2.2.1

虛擬設備:Nexus_5X

API:23

2、貼代碼的時候由於插入代碼框的大小問題,代碼格式不太嚴整,望見諒~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM