生活随笔
收集整理的這篇文章主要介紹了
Android传感器编程入门
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、前言
我很喜歡電腦,可是筆記本還是太大,筆記本電腦再小還是要弄個小包背起來的,智能手機則不同,它完全就是一個手機,可以隨意裝在一個口袋里隨身攜帶。因此我在2002年左右時最喜歡玩裝備是Dell的PDA,2007年的時候最喜歡玩的是N73,而在2010年最喜歡玩的則是Milestone。眼見著手機的功能越來越強,時至今日智能手機甚至在某些方面已經強過了臺式機和筆記本。本節課講的就是智能手機強過臺式機和筆記本的地方:傳感器。
2008年的時候我很喜歡我的小白筆記本Macbook,喜歡玩它的一個小軟件,一拍桌子,筆記本感受到了震動,它就轉換了一個桌面出來,這讓我像個小孩子一樣沒事就拍拍桌子。這一功能這得益于蘋果筆記本內置有傳感器。
我不知道iPhone手機是不是第一個把各種各樣的傳感器運用在手機上的,不過我知道iPhone是把傳感器運用在手機上最成功的第一個。隨后的Android系統也內置了大量的傳感器,這讓Android系統手機和普通的諾基亞智能機和Windows CE智能機相比牛氣了許多,在擁有了Milestone之后,我的N73就被仍在抽屜的角落里了。
從Android1.5開始,系統內置了對多達八種傳感器的支持,他們分別是:加速度傳感器(accelerometer),陀螺儀(gyroscope),環境光照傳感器(light),磁力傳感器(magnetic field),方向傳感器(orientation),壓力傳感器(pressure),距離傳感器(proximity)和溫度傳感器(temperature)。
利用這些傳感器我們可以制作出各種有趣的應用程序和游戲。譬如在口袋里晃一晃手機,手機就開始神不知鬼不覺的錄音,不要著急這個很容易做,我們在本文的結尾就一起制作這個小應用。
本講的學習方式還是在實戰中學習,需要提醒的是模擬器中無法模擬傳感器,因此你需要準備一款Android真機才能運行本講的例子。
二、實例:手機傳感器清單
我們還是先看程序后解釋,
1、創建一個項目 Lesson37_HelloSensor , 主Activity名字叫 mainActivity.java
2、UI布局文件main.xml的內容如下:
| 1 | <?xml version="1.0"?encoding="utf-8"?> |
| 2 | <linearlayout android:layout_height="fill_parent"android:layout_width="fill_parent"?android:orientation="vertical"xmlns:android="/apk/res/android"> |
| 3 | <textview android:layout_height="wrap_content"android:layout_width="fill_parent"?android:text=""android:id="@+id/TextView01"> |
| 4 | </textview></linearlayout> |
3、mainActivity.java的內容如下:
| 01 | package?basic.android.lesson37; |
| 05 | import?android.app.Activity; |
| 06 | import?android.content.Context; |
| 07 | import?android.hardware.Sensor; |
| 08 | import?android.hardware.SensorManager; |
| 09 | import?android.os.Bundle; |
| 10 | import?android.widget.TextView; |
| 12 | public?class?MainActivity?extends?Activity { |
| 14 | ????/** Called when the activity is first created. */ |
| 16 | ????public?void?onCreate(Bundle savedInstanceState) { |
| 17 | ????????super.onCreate(savedInstanceState); |
| 18 | ????????setContentView(R.layout.main); |
| 21 | ????????final?TextView tx1 = (TextView) findViewById(R.id.TextView01); |
| 23 | ????????//從系統服務中獲得傳感器管理器 |
| 24 | ????????SensorManager sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE); |
| 26 | ????????//從傳感器管理器中獲得全部的傳感器列表 |
| 27 | ????????List<sensor> allSensors = sm.getSensorList(Sensor.TYPE_ALL); |
| 30 | ????????tx1.setText("經檢測該手機有"?+ allSensors.size() +?"個傳感器,他們分別是:\n"); |
| 33 | ????????for?(Sensor s : allSensors) { |
| 35 | ????????????String tempString =?"\n"?+?"? 設備名稱:"?+ s.getName() +?"\n"+?"? 設備版本:"?+ s.getVersion() +?"\n"?+?"? 供應商:" |
| 36 | ????????????????????+ s.getVendor() +?"\n"; |
| 38 | ????????????switch?(s.getType()) { |
| 39 | ????????????case?Sensor.TYPE_ACCELEROMETER: |
| 40 | ????????????????tx1.setText(tx1.getText().toString() + s.getType() +?" 加速度傳感器accelerometer"?+ tempString); |
| 42 | ????????????case?Sensor.TYPE_GYROSCOPE: |
| 43 | ????????????????tx1.setText(tx1.getText().toString() + s.getType() +?" 陀螺儀傳感器gyroscope"?+ tempString); |
| 45 | ????????????case?Sensor.TYPE_LIGHT: |
| 46 | ????????????????tx1.setText(tx1.getText().toString() + s.getType() +?" 環境光線傳感器light"?+ tempString); |
| 48 | ????????????case?Sensor.TYPE_MAGNETIC_FIELD: |
| 49 | ????????????????tx1.setText(tx1.getText().toString() + s.getType() +?" 電磁場傳感器magnetic field"?+ tempString); |
| 51 | ????????????case?Sensor.TYPE_ORIENTATION: |
| 52 | ????????????????tx1.setText(tx1.getText().toString() + s.getType() +?" 方向傳感器orientation"?+ tempString); |
| 54 | ????????????case?Sensor.TYPE_PRESSURE: |
| 55 | ????????????????tx1.setText(tx1.getText().toString() + s.getType() +?" 壓力傳感器pressure"?+ tempString); |
| 57 | ????????????case?Sensor.TYPE_PROXIMITY: |
| 58 | ????????????????tx1.setText(tx1.getText().toString() + s.getType() +?" 距離傳感器proximity"?+ tempString); |
| 60 | ????????????case?Sensor.TYPE_TEMPERATURE: |
| 61 | ????????????????tx1.setText(tx1.getText().toString() + s.getType() +?" 溫度傳感器temperature"?+ tempString); |
| 64 | ????????????????tx1.setText(tx1.getText().toString() + s.getType() +?" 未知傳感器"?+ tempString); |
4、連接真機Milestone,編譯并運行程序,顯示結果如下:
5、結合上面的程序我們做一些解釋。
Android所有的傳感器都歸傳感器管理器 SensorManager 管理,獲取傳感器管理器的方法很簡單:
String service_name = Context.SENSOR_SERVICE;
SensorManager sensorManager = (SensorManager)getSystemService(service_name);
現階段Android支持的傳感器有8種,它們分別是:
| 傳感器類型常量 | 內部整數值 | 中文名稱 |
| Sensor.TYPE_ACCELEROMETER | 1 | 加速度傳感器 |
| Sensor.TYPE_MAGNETIC_FIELD | 2 | 磁力傳感器 |
| Sensor.TYPE_ORIENTATION | 3 | 方向傳感器 |
| Sensor.TYPE_GYROSCOPE | 4 | 陀螺儀傳感器 |
| Sensor.TYPE_LIGHT | 5 | 環境光照傳感器 |
| Sensor.TYPE_PRESSURE | 6 | 壓力傳感器 |
| Sensor.TYPE_TEMPERATURE | 7 | 溫度傳感器 |
| Sensor.TYPE_PROXIMITY | 8 | 距離傳感器 |
從傳感器管理器中獲取其中某個或者某些傳感器的方法有如下三種: 第一種:獲取某種傳感器的默認傳感器
Sensor defaultGyroscope = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
第二種:獲取某種傳感器的列表
List<Sensor> pressureSensors = sensorManager.getSensorList(Sensor.TYPE_PRESSURE);
第三種:獲取所有傳感器的列表,我們這個例子就用的第三種
List<Sensor> allSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
對于某一個傳感器,它的一些具體信息的獲取方法可以見下表:
| 方法 | 描述 |
| getMaximumRange() | 最大取值范圍 |
| getName() | 設備名稱 |
| getPower() | 功率 |
| getResolution() | 精度 |
| getType() | 傳感器類型 |
| getVentor() | 設備供應商 |
| getVersion() | 設備版本號 |
三、實例:窈窈錄音器
通過上面的例子我們學會了如何獲得某種類型的傳感器,下面我通過一個實例來學會如何使用某一個類型的傳感器。我們這里使用加速度傳感器來實現這樣一個功能:開啟我們的錄音程序放在你的口袋或者提包里,需要錄音的時候把衣服整理一下,或者把提包挪動個位置,那么此時手機就會感受到變化從而開始錄音。由此達到神不知鬼不覺的錄音效果。說起來似乎有點神,其實做起來很簡單,讓我們開始吧。
簡單的錄音程序已經在第28講的時候做過了,我們在28講程序的基礎上寫本講的代碼。
1、新建一個項目 Lesson37_YYRecorder , 主文件叫 MainActivity.java ,具體信息都可以參見第二十八講的“窈窈錄音”的例子。
2、這里只貼出于28講不同的 MainActivity.java? 的代碼,請注意看注釋:
| 001 | package?basic.android.lesson37; |
| 004 | import?java.io.IOException; |
| 005 | import?java.util.Calendar; |
| 006 | import?java.util.Locale; |
| 008 | import?android.app.Activity; |
| 009 | import?android.content.Context; |
| 010 | import?android.hardware.Sensor; |
| 011 | import?android.hardware.SensorEvent; |
| 012 | import?android.hardware.SensorEventListener; |
| 013 | import?android.hardware.SensorManager; |
| 014 | import?android.media.MediaRecorder; |
| 015 | import?android.os.Bundle; |
| 016 | import?android.text.format.DateFormat; |
| 017 | import?android.view.View; |
| 018 | import?android.widget.Button; |
| 019 | import?android.widget.TextView; |
| 020 | import?android.widget.Toast; |
| 022 | public?class?MainActivity?extends?Activity { |
| 025 | ????private?Button recordButton; |
| 026 | ????private?Button stopButton; |
| 029 | ????private?long?initTime =?0; |
| 030 | ????private?long?lastTime =?0; |
| 031 | ????private?long?curTime =?0; |
| 032 | ????private?long?duration =?0; |
| 034 | ????private?float?last_x =?0.0f; |
| 035 | ????private?float?last_y =?0.0f; |
| 036 | ????private?float?last_z =?0.0f; |
| 038 | ????private?float?shake =?0.0f; |
| 039 | ????private?float?totalShake =?0.0f; |
| 042 | ????private?MediaRecorder mr; |
| 045 | ????private?boolean?isRecoding =?false; |
| 048 | ????public?void?onCreate(Bundle savedInstanceState) { |
| 049 | ????????super.onCreate(savedInstanceState); |
| 050 | ????????setContentView(R.layout.main); |
| 053 | ????????recordButton = (Button)?this.findViewById(R.id.Button01); |
| 054 | ????????stopButton = (Button)?this.findViewById(R.id.Button02); |
| 055 | ????????final?TextView tx1 = (TextView)this.findViewById(R.id.TextView01); |
| 058 | ????????recordButton.setOnClickListener(new?View.OnClickListener() { |
| 061 | ????????????public?void?onClick(View v) { |
| 062 | ????????????????//如果沒有在錄音,那么點擊按鈕可以開始錄音 |
| 063 | ????????????????if(!isRecoding){ |
| 064 | ????????????????????startRecord(); |
| 070 | ????????stopButton.setOnClickListener(new?View.OnClickListener() { |
| 073 | ????????????public?void?onClick(View v) { |
| 074 | ????????????????initShake(); |
| 075 | ????????????????//如果正在錄音,那么可以停止錄音 |
| 076 | ????????????????if?(mr !=?null) { |
| 077 | ????????????????????mr.stop(); |
| 078 | ????????????????????mr.release(); |
| 079 | ????????????????????mr =?null; |
| 080 | ????????????????????recordButton.setText("錄音"); |
| 081 | ????????????????????Toast.makeText(getApplicationContext(),?"錄音完畢", Toast.LENGTH_LONG).show(); |
| 082 | ????????????????????isRecoding =?false; |
| 089 | ????????SensorManager sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE); |
| 091 | ????????Sensor acceleromererSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); |
| 094 | ????????SensorEventListener acceleromererListener =?newSensorEventListener() { |
| 097 | ????????????public?void?onAccuracyChanged(Sensor sensor,?int?accuracy) { |
| 098 | ????????????????//什么也不干 |
| 101 | ????????????//傳感器數據變動事件 |
| 103 | ????????????public?void?onSensorChanged(SensorEvent event) {??? |
| 105 | ????????????????//如果沒有開始錄音的話可以監聽是否有搖動事件,如果有搖動事件可以開始錄音 |
| 106 | ????????????????if(!isRecoding){ |
| 107 | ????????????????????//獲取加速度傳感器的三個參數 |
| 108 | ????????????????????float?x = event.values[SensorManager.DATA_X]; |
| 109 | ????????????????????float?y = event.values[SensorManager.DATA_Y]; |
| 110 | ????????????????????float?z = event.values[SensorManager.DATA_Z]; |
| 112 | ????????????????????//獲取當前時刻的毫秒數 |
| 113 | ????????????????????curTime = System.currentTimeMillis(); |
| 115 | ????????????????????//100毫秒檢測一次 |
| 116 | ????????????????????if?((curTime - lastTime) >?100) { |
| 118 | ????????????????????????duration = (curTime - lastTime); |
| 120 | ????????????????????????// 看是不是剛開始晃動 |
| 121 | ????????????????????????if?(last_x ==?0.0f && last_y ==?0.0f && last_z ==0.0f) { |
| 122 | ????????????????????????????//last_x、last_y、last_z同時為0時,表示剛剛開始記錄 |
| 123 | ????????????????????????????initTime = System.currentTimeMillis(); |
| 124 | ????????????????????????}?else?{ |
| 125 | ????????????????????????????// 單次晃動幅度 |
| 126 | ????????????????????????????shake = (Math.abs(x - last_x) + Math.abs(y - last_y) + Math.abs(z - last_z)) / duration *?100; |
| 127 | ????????????????????????} |
| 129 | ????????????????????????//把每次的晃動幅度相加,得到總體晃動幅度 |
| 130 | ????????????????????????totalShake += shake; |
| 132 | ????????????????????????// 判斷是否為搖動,這是我自己寫的標準,不準確,只是用來做教學示例,別誤會了^_^ |
| 133 | ????????????????????????if?(totalShake >?10?&& totalShake / (curTime - initTime) *?1000?>?10) { |
| 134 | ????????????????????????????startRecord(); |
| 135 | ????????????????????????????initShake(); |
| 136 | ????????????????????????} |
| 138 | ????????????????????????tx1.setText("總體晃動幅度="+totalShake+?"\n平均晃動幅度="+totalShake / (curTime - initTime) *?1000?); |
| 141 | ????????????????????last_x = x; |
| 142 | ????????????????????last_y = y; |
| 143 | ????????????????????last_z = z; |
| 144 | ????????????????????lastTime = curTime; |
| 150 | ????????//在傳感器管理器中注冊監聽器 |
| 151 | ????????sm.registerListener(acceleromererListener, acceleromererSensor, SensorManager.SENSOR_DELAY_NORMAL); |
| 156 | ????public?void?startRecord() { |
| 158 | ????????isRecoding =?true; |
| 160 | ????????File file =?new?File("/sdcard/"?+?"YY" |
| 161 | ????????????????+?new?DateFormat().format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA)) +?".amr"); |
| 163 | ????????Toast.makeText(getApplicationContext(),?"正在錄音,錄音文件在"?+ file.getAbsolutePath(), Toast.LENGTH_LONG).show(); |
| 166 | ????????mr =?new?MediaRecorder(); |
| 169 | ????????mr.setAudioSource(MediaRecorder.AudioSource.DEFAULT); |
| 172 | ????????mr.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); |
| 175 | ????????mr.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); |
| 178 | ????????mr.setOutputFile(file.getAbsolutePath()); |
| 182 | ????????????file.createNewFile(); |
| 184 | ????????????mr.prepare(); |
| 185 | ????????}?catch?(IllegalStateException e) { |
| 186 | ????????????e.printStackTrace(); |
| 187 | ????????}?catch?(IOException e) { |
| 188 | ????????????e.printStackTrace(); |
| 192 | ????????recordButton.setText("錄音中……"); |
| 196 | ????public?void?initShake() { |
| 201 | ????????last_x =?0.0f; |
| 202 | ????????last_y =?0.0f; |
| 203 | ????????last_z =?0.0f; |
| 205 | ????????totalShake =?0.0f; |
3、連接真機Milestone,編譯并運行程序:
晃動機器,開始錄音
查看錄音文件,效果還可以:
4、我們小結一下:
到Android2.2版本為止,系統并沒有給開發者提供多少可用的包裝好的傳感器信息,只是提供了傳感器發出的原始數據,這些原始數據存放在? event.values 的數組里,開發人員需要從這些裸數據總自行發掘有用的信息,譬如從加速度傳感器的3維裸數據中獲得搖動的判斷(我的搖動判斷很弱智,有時間再改吧……)。
好了本講就先到這里,關于傳感器有機會我們展開再談,下次再見吧。
轉載于:https://www.cnblogs.com/java-time/archive/2011/05/25/tt150.html
總結
以上是生活随笔為你收集整理的Android传感器编程入门的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。