自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

深入探討Android傳感器

移動開發(fā) Android
Android 是一個面向應(yīng)用程序開發(fā)的富平臺,它擁有許多具有吸引力的用戶界面元素和數(shù)據(jù)管理功能。Android 還提供了一組豐富的接口選項(xiàng)。在本文中,學(xué)習(xí)如何配合使用 Android 的各種傳感器選項(xiàng)監(jiān)控您的環(huán)境。樣例代碼展示了如何在 Android 電話中錄制音頻。想構(gòu)建自己的嬰兒監(jiān)視器嗎?想用聲音來接聽電話或者打開房門嗎?請學(xué)習(xí)如何利用配備有 Android 的設(shè)備的硬件功能。

對于Java開發(fā)人員來說,Android 平臺是通過使用硬件傳感器創(chuàng)建創(chuàng)新應(yīng)用程序的理想平臺。我們將學(xué)習(xí)一些可用于 Android 應(yīng)用程序的接口連接選項(xiàng),包括使用傳感器子系統(tǒng)和錄制音頻片段。

利用配備Android 的設(shè)備的硬件功能可以構(gòu)建哪些應(yīng)用程序呢?任何需要電子監(jiān)視和監(jiān)聽的應(yīng)用程序都可以構(gòu)建。嬰兒監(jiān)視器、安全系統(tǒng),甚至地震儀都可以。理論上講,您不能同時 出現(xiàn)在兩個地方,但 Android 可以利用一些可行的方法實(shí)現(xiàn)這一點(diǎn)??v觀本文始末,您必須記住,使用的 Android 設(shè)備不僅僅局限于 “手機(jī)”,還可以是部署在固定位置、具有無線網(wǎng)絡(luò)連接的設(shè)備,比如 EDGE 或 WiFi。

使用 Android 平臺有一個很新穎的地方,那就是您可以在設(shè)備內(nèi)部訪問一些 “好工具”。過去,訪問設(shè)備底層硬件的能力一度讓移動開發(fā)人員感到非常棘手。盡管 Android Java 環(huán)境的角色仍然是您和設(shè)備的橋梁,但 Android 開發(fā)團(tuán)隊(duì)讓許多硬件功能浮出了水面。該平臺是一個開源平臺,因此您可以自由地編寫代碼實(shí)現(xiàn)您的任務(wù)。

如果尚未安裝 Android,您可以 下載 Android SDK。您還可以 瀏覽 android.hardware 包的內(nèi)容并參考本文的示例。android.media 包 包含了一些提供有用和新穎功能的類。

Android SDK 中包含的一些面向硬件的功能描述如下。

表 1. Android SDK 中提供的面向硬件的特性

特性 描述
android.hardware.Camera 允許應(yīng)用程序與相機(jī)交互的類,可以截取照片、獲取預(yù)覽屏幕的圖像,修改用來治理相機(jī)操作的參數(shù)。
android.hardware.SensorManager 允許訪問 Android 平臺傳感器的類。并非所有配備 Android 的設(shè)備都支持 SensorManager 中的所有傳感器,雖然這種可能性讓人非常興奮。(可用傳感器的簡介見下文)
android.hardware.SensorListener 在傳感器值實(shí)時更改時,希望接收更新的類要實(shí)現(xiàn)的接口。應(yīng)用程序?qū)崿F(xiàn)該接口來監(jiān)視硬件中一個或多個可用傳感器。例如,本文中的 代碼 包含實(shí)現(xiàn)該接口的類,實(shí)現(xiàn)后可以監(jiān)視設(shè)備的方向和內(nèi)置的加速表。
android.media.MediaRecorder 用于錄制媒體樣例的類,對于錄制特定位置(比如嬰兒保育)的音頻活動非常有用。還可以分析音頻片段以便在訪問控件或安全應(yīng)用程序時進(jìn)行身份鑒定。例如,它可以幫助您通過聲音打開門,以節(jié)省時間,不需要從房產(chǎn)經(jīng)紀(jì)人處獲取鑰匙。
android.FaceDetector 允許對人臉(以位圖形式包含)進(jìn)行基本識別的類。不可能有兩張完全一樣的臉??梢允褂迷擃愖鳛樵O(shè)備鎖定方法,無需記密碼 — 這是手機(jī)的生物特征識別功能。
android.os.* 包含幾個有用類的包,可以與操作環(huán)境交互,包括電源管理、文件查看器、處理器和消息類。和許多可移動設(shè)備一樣,支持 Android 的電話可能會消耗大量電能。讓設(shè)備在正確的時間 “醒來” 以監(jiān)視感興趣的事件是在設(shè)計時需要首先關(guān)注的方面。
java.util.Date
java.util.Timer
java.util.TimerTask
當(dāng)測量實(shí)際的事件時,數(shù)據(jù)和時間往往很重要。例如,java.util.Date 類允許您在遇到特定的事件或狀況時獲取時間戳。您可以使用 java.util.Timer 和 java.util.TimerTask 分別執(zhí)行周期性任務(wù)或時間點(diǎn)任務(wù)。

android.hardware.SensorManager 包含幾個常量,這表示 Android 傳感器系統(tǒng)的不同方面,包括:

傳感器類型

方向、加速表、光線、磁場、臨近性、溫度等。

采樣率

最快、游戲、普通、用戶界面。當(dāng)應(yīng)用程序請求特定的采樣率時,其實(shí)只是對傳感器子系統(tǒng)的一個提示,或者一個建議。不保證特定的采樣率可用。

準(zhǔn)確性

高、低、中、不可靠。

SensorListener 接口是傳感器應(yīng)用程序的中心。它包括兩個必需方法:

onSensorChanged(int sensor,float values[]) 方法在傳感器值更改時調(diào)用。該方法只對受此應(yīng)用程序監(jiān)視的傳感器調(diào)用(更多內(nèi)容見下文)。該方法的參數(shù)包括:一個整數(shù),指示更改的傳感器;一個浮點(diǎn)值數(shù)組,表示傳感器數(shù)據(jù)本身。有些傳感器只提供一個數(shù)據(jù)值,另一些則提供三個浮點(diǎn)值。方向和加速表傳感器都提供三個數(shù)據(jù)值。

當(dāng)傳感器的準(zhǔn)確性更改時,將調(diào)用 onAccuracyChanged(int sensor,int accuracy) 方法。參數(shù)包括兩個整數(shù):一個表示傳感器,另一個表示該傳感器新的準(zhǔn)確值。

要與傳感器交互,應(yīng)用程序必須注冊以偵聽與一個或多個傳感器相關(guān)的活動。注冊使用 SensorManager 類的 registerListener 方法完成。本文中的 代碼示例 演示了如何注冊和注銷 SensorListener。

記住,并非所有支持 Android 的設(shè)備都支持 SDK 中定義的所有傳感器。如果某個傳感器無法在特定的設(shè)備上使用,您的應(yīng)用程序就會適當(dāng)?shù)亟导墶?/p>

樣例應(yīng)用程序僅監(jiān)控對方向和加速表傳感器的更改(源代碼見 下載)。當(dāng)收到更改時,傳感器值在 TextView 小部件的屏幕上顯示。圖 1 展示了該應(yīng)用程序的運(yùn)行情況。

圖 1. 監(jiān)視加速和方向

監(jiān)視加速和方向

使用 Eclipse 環(huán)境和 Android Developer Tools 插件創(chuàng)建的應(yīng)用程序。(關(guān)于使用 Eclipse 開發(fā) Android 應(yīng)用程序的信息,請參見 參考資料。)清單 1 展示了該應(yīng)用程序的代碼。

清單 1. IBMEyes.java

  1. package com.msi.ibm.eyes; 
  2. import android.app.Activity; 
  3. import android.os.Bundle; 
  4. import android.util.Log; 
  5. import android.widget.TextView; 
  6. import android.hardware.SensorManager; 
  7. import android.hardware.SensorListener; 
  8. public class IBMEyes extends Activity implements SensorListener { 
  9. final String tag = "IBMEyes"
  10. SensorManager sm = null
  11. TextView xViewA = null
  12. TextView yViewA = null
  13. TextView zViewA = null
  14. TextView xViewO = null
  15. TextView yViewO = null
  16. TextView zViewO = null
  17.  
  18. /** Called when the activity is first created. */ 
  19. @Override 
  20. public void onCreate(Bundle savedInstanceState) { 
  21. super.onCreate(savedInstanceState); 
  22. // get reference to SensorManager 
  23. sm = (SensorManager) getSystemService(SENSOR_SERVICE); 
  24. setContentView(R.layout.main); 
  25. xViewA = (TextView) findViewById(R.id.xbox); 
  26. yViewA = (TextView) findViewById(R.id.ybox); 
  27. zViewA = (TextView) findViewById(R.id.zbox); 
  28. xViewO = (TextView) findViewById(R.id.xboxo); 
  29. yViewO = (TextView) findViewById(R.id.yboxo); 
  30. zViewO = (TextView) findViewById(R.id.zboxo); 
  31. public void onSensorChanged(int sensor, float[] values) { 
  32. synchronized (this) { 
  33. Log.d(tag, "onSensorChanged: " + sensor + ", x: " +  
  34. values[0] + ", y: " + values[1] + ", z: " + values[2]); 
  35. if (sensor == SensorManager.SENSOR_ORIENTATION) { 
  36. xViewO.setText("Orientation X: " + values[0]); 
  37. yViewO.setText("Orientation Y: " + values[1]); 
  38. zViewO.setText("Orientation Z: " + values[2]); 
  39. if (sensor == SensorManager.SENSOR_ACCELEROMETER) { 
  40. xViewA.setText("Accel X: " + values[0]); 
  41. yViewA.setText("Accel Y: " + values[1]); 
  42. zViewA.setText("Accel Z: " + values[2]); 
  43. }  
  44.  
  45. public void onAccuracyChanged(int sensor, int accuracy) { 
  46. Log.d(tag,"onAccuracyChanged: " + sensor + ", accuracy: " + accuracy); 
  47. @Override 
  48. protected void onResume() { 
  49. super.onResume(); 
  50. // register this class as a listener for the orientation and accelerometer sensors 
  51. sm.registerListener(this,  
  52. SensorManager.SENSOR_ORIENTATION |SensorManager.SENSOR_ACCELEROMETER, 
  53. SensorManager.SENSOR_DELAY_NORMAL); 
  54.  
  55. @Override 
  56. protected void onStop() { 
  57. // unregister listener 
  58. sm.unregisterListener(this); 
  59. super.onStop(); 
  60. }  

編寫應(yīng)用程序必須基于常見的活動,因?yàn)樗皇抢脧膫鞲衅鳙@取的數(shù)據(jù)更新屏幕。在設(shè)備可能在前臺執(zhí)行其他活動的應(yīng)用程序中,將應(yīng)用程序構(gòu)建為服務(wù)可能更加合適。

該活動的 onCreate 方法可以引用 SensorManager,其中包含所有與傳感器有關(guān)的函數(shù)。onCreate 方法還建立了對 6 個 TextView 小部件的引用,您需要使用傳感器數(shù)據(jù)值更新這些小部件。

onResume() 方法使用對 SensorManager 的引用通過 registerListener 方法注冊傳感器更新:

第一個參數(shù)是實(shí)現(xiàn) SensorListener 接口的類的實(shí)例。

第二個參數(shù)是所需傳感器的位掩碼。在本例中,應(yīng)用程序從 SENSOR_ORIENTATION 和 SENSOR_ACCELEROMETER 請求數(shù)據(jù)。

第三個參數(shù)是一個系統(tǒng)提示,指出應(yīng)用程序更新傳感器值所需的速度。

應(yīng)用程序(活動)暫停后,需要注銷偵聽器,這樣以后就不會再收到傳感器更新。這通過 SensorManager 的 unregisterListener 方法實(shí)現(xiàn)。惟一的參數(shù)是 SensorListener 的實(shí)例。

在 registerListener 和 unregisterListener 方法調(diào)用中,應(yīng)用程序使用關(guān)鍵字 this。注意類定義中的 implements 關(guān)鍵字,其中聲明了該類實(shí)現(xiàn) SensorListener 接口。這就是要將它傳遞到 registerListener 和 unregisterListener 的原因。

SensorListener 必須實(shí)現(xiàn)兩個方法 onSensorChange 和 onAccuracyChanged。示例應(yīng)用程序不關(guān)心傳感器的準(zhǔn)確度,但關(guān)注傳感器當(dāng)前的 X、Y 和 Z 值。onAccuracyChanged 方法實(shí)質(zhì)上不執(zhí)行任何操作;它只在每次調(diào)用時添加一個日志項(xiàng)。

似乎經(jīng)常需要調(diào)用 onSensorChanged 方法,因?yàn)榧铀俦砗头较騻鞲衅髡诳焖侔l(fā)送數(shù)據(jù)。查看第一個參數(shù)確定哪個傳感器在發(fā)送數(shù)據(jù)。確認(rèn)了發(fā)送數(shù)據(jù)的傳感器之后,將使用方法第二個參數(shù)傳遞的浮點(diǎn) 值數(shù)組中所包含的數(shù)據(jù)更新相應(yīng)的 UI 元素。該示例只是顯示這些值,但在更加高級的應(yīng)用程序中,還可以分析這些值,比較原來的值,或者設(shè)置某種模式識別算法來確定用戶(或外部環(huán)境)的行為。

現(xiàn)在您已經(jīng)了解了傳感器子系統(tǒng),接下來的部分將回顧一個在 Android 手機(jī)上錄制音頻的代碼樣例。該樣例運(yùn)行在 DEV1 開發(fā)設(shè)備上。

使用 MediaRecorder

android.media 包包含與媒體子系統(tǒng)交互的類。使用 android.media.MediaRecorder 類進(jìn)行媒體采樣,包括音頻和視頻。MediaRecorder 作為狀態(tài)機(jī)運(yùn)行。您需要設(shè)置不同的參數(shù),比如源設(shè)備和格式。設(shè)置后,可執(zhí)行任何時間長度的錄制,直到用戶停止。

清單 2 包含的代碼在 Android 設(shè)備上錄制音頻。顯示的代碼不包括應(yīng)用程序的 UI 元素(完整源代碼見 下載)。

清單 2. 錄制音頻片段

  1. MediaRecorder mrec ; 
  2. File audiofile = null
  3. private static final String TAG="SoundRecordingDemo"
  4. protected void startRecording() throws IOException  
  5. mrec.setAudioSource(MediaRecorder.AudioSource.MIC); 
  6. mrec.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 
  7. mrec.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 
  8. if (mSampleFile == null)  
  9. File sampleDir = Environment.getExternalStorageDirectory(); 
  10. try 
  11. {  
  12. audiofile = File.createTempFile("ibm"".3gp", sampleDir); 
  13. catch (IOException e)  
  14. Log.e(TAG,"sdcard access error"); 
  15. return
  16. mrec.setOutputFile(audiofile.getAbsolutePath()); 
  17. mrec.prepare(); 
  18. mrec.start(); 
  19. protected void stopRecording()  
  20. mrec.stop(); 
  21. mrec.release(); 
  22. processaudiofile(audiofile.getAbsolutePath()); 
  23. protected void processaudiofile()  
  24. ContentValues values = new ContentValues(3); 
  25. long current = System.currentTimeMillis(); 
  26. values.put(MediaStore.Audio.Media.TITLE, "audio" + audiofile.getName()); 
  27. values.put(MediaStore.Audio.Media.DATE_ADDED, (int) (current / 1000)); 
  28. values.put(MediaStore.Audio.Media.MIME_TYPE, "audio/3gpp"); 
  29. values.put(MediaStore.Audio.Media.DATA, audiofile.getAbsolutePath()); 
  30. ContentResolver contentResolver = getContentResolver(); 
  31.  
  32. Uri base = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; 
  33. Uri newUri = contentResolver.insert(base, values); 
  34.  
  35. sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, newUri)); 

在 startRecording 方法中,實(shí)例化并初始化 MediaRecorder 的實(shí)例:

輸入源被設(shè)置為麥克風(fēng)(MIC)。

輸出格式被設(shè)置為 3GPP(*.3gp 文件),這是移動設(shè)備專用的媒體格式。

編碼器被設(shè)置為 AMR_NB,這是音頻格式,采樣率為 8 KHz。NB 表示窄頻。SDK 文檔 解釋了不同的數(shù)據(jù)格式和可用的編碼器。

音頻文件存儲在存儲卡而不是內(nèi)存中。External.getExternalStorageDirectory() 返回存儲卡位置的名稱,在該目錄中將創(chuàng)建一個臨時文件名。然后,通過調(diào)用 setOutputFile 方法將文件關(guān)聯(lián)到 MediaRecorder 實(shí)例。音頻數(shù)據(jù)將存儲到該文件中。

調(diào)用 prepare 方法完成 MediaRecorder 的初始化。準(zhǔn)備開始錄制流程時,將調(diào)用 start 方法。在調(diào)用 stop 方法之前,將對存儲卡上的文件進(jìn)行錄制。release 方法將釋放分配給 MediaRecorder 實(shí)例的資源。

音頻采樣完成之后,需要采取以下步驟:

向設(shè)備的媒體庫添加該音頻。

執(zhí)行一些模式識別步驟確定聲音:

  • 這是嬰兒的啼哭聲嗎? 
  • 這是所有人的聲音嗎?是否要解鎖手機(jī)? 
  • 這是 “芝麻開門” 嗎?是否要打開通往 “秘密通道” 的大門? 

自動將音頻文件上傳到網(wǎng)絡(luò)位置以便處理。

在該代碼樣例中,processaudiofile 方法將音頻添加到媒體庫。使用 Intent 通知設(shè)備上的媒體應(yīng)用程序有新內(nèi)容可用。

關(guān)于該代碼片段最后要注意的是:如果您試用,它一開始不會錄制音頻。您將看到創(chuàng)建的文件,但是沒有任何音頻。您需要向 AndroidManifest.xml 文件添加權(quán)限:

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

現(xiàn)在,您已經(jīng)學(xué)了一點(diǎn)關(guān)于與 Android 傳感器和錄制音頻相關(guān)的內(nèi)容。下一節(jié)將更全面的介紹與數(shù)據(jù)采集和報告系統(tǒng)有關(guān)的應(yīng)用程序架構(gòu)。

Android 作為傳感器平臺

Android 平臺包含各種用于監(jiān)視環(huán)境的傳感器選項(xiàng)。有了輸入或模擬選項(xiàng)數(shù)組,以及高級計算和互聯(lián)功能,Android 成為構(gòu)建實(shí)際系統(tǒng)的最佳平臺。圖 2 顯示了輸入、應(yīng)用程序邏輯、通知方法或輸出之間的簡單視圖。

圖 2. 以 Android 為中心的傳感器系統(tǒng)的方塊圖

以 Android 為中心的傳感器系統(tǒng)的方塊圖

該架構(gòu)很靈活;應(yīng)用程序邏輯可以劃分為本地 Android 設(shè)備和服務(wù)器端資源(可以實(shí)現(xiàn)更大的數(shù)據(jù)庫和計算功能)。例如,本地 Android 設(shè)備上錄制的音軌可以 POST 到 Web 服務(wù)器,其中將根據(jù)音頻模式數(shù)據(jù)庫比較數(shù)據(jù)。很明顯,這僅僅是冰山一角。希望您能更深入地研究,讓 Android 平臺超越移動電話的范疇。

結(jié)束語

在本文中,我們介紹了 Android 傳感器。樣例應(yīng)用程序度量了方向和加速,以及使用 MediaRecorder 類與錄制功能進(jìn)行交互。對于構(gòu)建實(shí)際系統(tǒng),Android 是一個靈活、有吸引力的平臺。Android 領(lǐng)域發(fā)展迅速,并且不斷壯大。請務(wù)必關(guān)注該平臺。

責(zé)任編輯:佚名 來源: 開源中國社區(qū)
相關(guān)推薦

2011-02-25 09:23:00

Java類加載器

2009-11-12 13:56:54

2017-01-03 17:57:46

Android異步精髓Handler

2009-12-23 16:13:00

WPF Attache

2010-11-22 14:18:32

MySQL鎖機(jī)制

2010-07-21 09:38:15

PHP緩存技術(shù)

2010-01-26 13:47:57

Android電話功能

2009-11-20 17:17:08

Oracle函數(shù)索引

2021-05-17 05:36:02

CSS 文字動畫技巧

2009-12-07 17:26:50

tenda路由器

2009-12-18 10:39:46

家用寬帶路由器設(shè)置

2015-09-02 08:57:56

JavaHashMap工作原理

2009-08-27 11:27:58

foreach語句C# foreach語

2010-03-05 13:44:00

Python序列

2010-03-31 14:58:03

云計算

2023-01-12 17:18:06

數(shù)據(jù)庫多云

2009-12-03 13:55:10

路由器主要功能

2024-01-26 06:42:05

Redis數(shù)據(jù)結(jié)構(gòu)

2013-07-11 09:45:48

扁平化扁平化設(shè)計

2009-10-16 09:17:39

屏蔽布線系統(tǒng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號