最近項目需要各種手機(jī)傳感器内列,于是就此來寫個總結(jié),以此留痕恩够。
在Android開發(fā)中卒落,會用到各種傳感器,但不一定每個真機(jī)都支持這些傳感器蜂桶。所以相關(guān)開發(fā)還要根據(jù)真機(jī)的實際情況來做開發(fā)儡毕。
1 獲取手機(jī)的傳感器
通過實例化SensorManager可以獲取到手機(jī)的傳感器集合
//實例化
mSensorManger= (SensorManager) getSystemService(Context.SENSOR_SERVICE);
List<Sensor> sensorList = mSensorManger.getSensorList(Sensor.TYPE_ALL);
獲取到的傳感器名稱:
Accelerometer 加速計
Magnetometer 磁力計
Gyroscope 陀螺儀
Proximity Sensor 近距離傳感器
Ambient Light Sensor 環(huán)境光傳感器
Barometer Sensor 氣壓計
Temperature Sensor 溫度傳感器
Gravity 重力
Linear Acceleration 線性加速度
Rotation Vector 旋轉(zhuǎn)矢量
Step Detector 步數(shù)探測器
Step Counter 計步器
Significant Motion Detector 運動檢測器
Game Rotation Vector 游戲旋轉(zhuǎn)矢量
Geomagnetic Rotation Vector 地磁旋轉(zhuǎn)矢量
Orientation 方向
Basic Gestures 基本手勢
Motion Accel 運動加速度
Android傳感器按大方向劃分大致有這么三類傳感器:動作(Motion)傳感器、環(huán)境(Environmental)傳感器扑媚、位置(Position)傳感器腰湾。
(1)動作傳感器
這類傳感器在三個軸(x、y疆股、z)上測量加速度和旋轉(zhuǎn)角度费坊。包括如下幾個傳感器:
加速(accelerometer)傳感器、重力(gravity)傳感器旬痹、陀螺儀(gyroscope)傳感器附井、旋轉(zhuǎn)向量(rotational vector )傳感器
下面來看一下傳感器世界的坐標(biāo)系:
[圖片上傳失敗...(image-a8a3de-1567500246575)]
(2)環(huán)境傳感器
這類傳感器可以測量不同環(huán)境的參數(shù),例如两残,周圍環(huán)境的空氣溫度和壓強(qiáng)永毅、光照強(qiáng)度和濕度。包括如下幾個傳感器:
濕度(barometer)傳感器人弓、光線(photometer)傳感器卷雕、溫度(thermometer)傳感器
(3)位置傳感器
這類傳感器可以測量設(shè)備的物理位置。包括如下幾個傳感器:
方向(orientation)傳感器票从、磁力(magnetometer)傳感器
了解后我們就開始進(jìn)入傳感器的編程工作了漫雕,接下來我們看一下Android為我們提供的傳感器框架(Android sensor framework,簡稱ASF)峰鄙。
2.Android傳感器框架
Android SDK為我們提供了ASF浸间,可以用來訪問當(dāng)前Android設(shè)備內(nèi)置的傳感器。ASF提供了很多類和接口吟榴,幫助我們完成各種與傳感器有關(guān)的任務(wù)魁蒜。例如:
1)確定當(dāng)前Android設(shè)備內(nèi)置了哪些傳感器。
2)確定某一個傳感器的技術(shù)指標(biāo)吩翻。
3)獲取傳感器傳回來的數(shù)據(jù)兜看,以及定義傳感器回傳數(shù)據(jù)的精度。
4)注冊和注銷傳感器事件監(jiān)聽器狭瞎,這些監(jiān)聽器用于監(jiān)聽傳感器的變化细移,通常從傳感器回傳的數(shù)據(jù)需要利用這些監(jiān)聽器完成。
ASF允許我們訪問很多傳感器類型熊锭,這些傳感器有一些是基于硬件的傳感器弧轧,還有一些是基于軟件的傳感器雪侥。基于硬件的傳感器就是直接以芯片形式嵌入到Android設(shè)備中精绎,這些傳感器直接從外部環(huán)境獲取數(shù)據(jù)速缨。基于軟件的傳感器并不是實際的硬件芯片代乃,基于軟件的傳感器傳回的數(shù)據(jù)本質(zhì)上也來自于基于硬件的傳感器旬牲,只是這些數(shù)據(jù)通常會經(jīng)過二次加工。所以基于軟件的傳感器也可以稱為虛擬(virtual)傳感器或合成(synthetic)傳感器搁吓。
Android對每個設(shè)備的傳感器都進(jìn)行了抽象引谜,其中SensorManger類用來控制傳感器,Sensor用來描述具體的傳感器擎浴,SensorEventListener用來監(jiān)聽傳感器值的改變员咽。
(1)SensorManager類
用于創(chuàng)建sensor service的實例。該類提供了很多用于訪問和枚舉傳感器贮预,注冊和注銷傳感器監(jiān)聽器的方法贝室。而且還提供了與傳感器精度、掃描頻率仿吞、校正有關(guān)的常量滑频。
(2)Sensor類
Sensor類為我們提供了一些用于獲取傳感器技術(shù)參數(shù)的方法。如版本唤冈、類型峡迷、生產(chǎn)商等。例如所有傳感器的TYPE類型如下:
注意:1-8是硬件傳感器你虹,9是軟件傳感器绘搞,其中方向傳感器的數(shù)據(jù)來自重力和磁場傳感器,10-12是硬件或軟件傳感器傅物。
序號|傳感器|Sensor類中定義的TYPE常量
|:-- :|:--:| :-----:| :--:|
啊|as|as
序號 | 傳感器 | 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 | 旋轉(zhuǎn)向量傳感器 | TYPE_ROTATION_VECTOR |
(3)SensorEvent類
系統(tǒng)使用該類創(chuàng)建傳感器事件對象夯辖。該對象可以提供與傳感器事件有關(guān)的信息。傳感器事件對象包括的信息有原始的傳感器回傳數(shù)據(jù)董饰、傳感器類型蒿褂、數(shù)據(jù)的精度以及觸發(fā)事件的時間。
(4)SensorEventListener接口
該接口包含兩個回調(diào)方法卒暂,當(dāng)傳感器的回傳值或精度發(fā)生變化時啄栓,系統(tǒng)會調(diào)用這兩個回調(diào)方法。
/**
* 傳感器精度變化時回調(diào)
*/
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
/**
* 傳感器數(shù)據(jù)變化時回調(diào)
*/
@Override
public void onSensorChanged(SensorEvent event) {
}
到了這里也祠,我們就可以進(jìn)行傳感器開發(fā)工作了昙楚。
3.獲取傳感器技術(shù)參數(shù)
下來我們編寫代碼來獲取一下自己手機(jī)的傳感器技術(shù)參數(shù)。
TextView tvSensors = (TextView) findViewById(R.id.tv_sensors);
//獲取傳感器SensorManager對象
SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
for (Sensor sensor : sensors) {
tvSensors.append(sensor.getName() + "\n");
}
先運行一下看看效果:
[圖片上傳失敗...(image-a87622-1567500246575)]
貌似我的手機(jī)傳感器還不少齿坷,哈哈桂肌。注意此處必須用實體機(jī)測試哦。
下來我們分別看一下動作傳感器永淌、環(huán)境傳感器和位置傳感器的組成及使用方法崎场。
4.動作傳感器的組成及使用方法
所有的動作傳感器都會返回三個浮點數(shù)的值(通過長度為3的數(shù)組返回),但對于不同的傳感器遂蛀,這三個只是意義不同谭跨。例如,對于加速傳感器李滴,會返回三個坐標(biāo)軸的數(shù)據(jù)螃宙。對于陀螺儀傳感器,會返回三個坐標(biāo)軸的旋轉(zhuǎn)角速度所坯。
注意:動作傳感器本身一般并不會用于監(jiān)測設(shè)備的位置谆扎,關(guān)于設(shè)備的位置需要用其他類型的傳感器進(jìn)行監(jiān)測,例如芹助,磁場傳感器堂湖。
(1)加速度傳感器
加速度傳感器需要結(jié)合重力傳感器使用,以減少加速度受重力的影響状土。首先需要實現(xiàn)SensorEventListener接口无蜂,添加回調(diào)方法,然后獲取傳感器SensorManager對象蒙谓,注冊傳感器斥季,然后我們就可以監(jiān)聽傳感器的變化了。示例代碼如下:
public class SensorActivity extends AppCompatActivity implements SensorEventListener {
private TextView tvAccelerometer;
private SensorManager mSensorManager;
private float[] gravity = new float[3];
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sensor);
tvAccelerometer = (TextView) findViewById(R.id.tv_accelerometer);
//獲取傳感器SensorManager對象
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
}
/**
* 傳感器精度變化時回調(diào)
*/
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
/**
* 傳感器數(shù)據(jù)變化時回調(diào)
*/
@Override
public void onSensorChanged(SensorEvent event) {
//判斷傳感器類別
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER: //加速度傳感器
final float alpha = (float) 0.8;
gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];
String accelerometer = "加速度傳感器\n" + "x:"
+ (event.values[0] - gravity[0]) + "\n" + "y:"
+ (event.values[1] - gravity[1]) + "\n" + "z:"
+ (event.values[2] - gravity[2]);
tvAccelerometer.setText(accelerometer);
//重力加速度9.81m/s^2累驮,只受到重力作用的情況下酣倾,自由下落的加速度
break;
case Sensor.TYPE_GRAVITY://重力傳感器
gravity[0] = event.values[0];//單位m/s^2
gravity[1] = event.values[1];
gravity[2] = event.values[2];
break;
default:
break;
}
}
/**
* 界面獲取焦點,按鈕可以點擊時回調(diào)
*/
protected void onResume() {
super.onResume();
//注冊加速度傳感器
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),//傳感器TYPE類型
SensorManager.SENSOR_DELAY_UI);//采集頻率
//注冊重力傳感器
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY),
SensorManager.SENSOR_DELAY_FASTEST);
}
/**
* 暫停Activity谤专,界面獲取焦點灶挟,按鈕可以點擊時回調(diào)
*/
@Override
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
}
我們將手機(jī)水平正面朝上放置于桌子上,看一下效果圖:
[圖片上傳失敗...(image-9ac78f-1567500246575)]
我們可以看到正值和負(fù)值毒租,那什么情況是正值稚铣?什么情況是負(fù)值呢?
設(shè)備沿x軸正方向推動墅垮,x軸加速度為正值惕医。
設(shè)備沿y軸正方向推動,y軸加速度為正值算色。
如果沿z軸正方向推動抬伺,此時手機(jī)相對于桌子水平正面朝上放置,z軸加速度為正值灾梦。由底部朝著頂部以a m/s^2的加速度推動峡钓,那么z軸的加速度為a + 9.81妓笙,所以如果計算實際的加速度(抵消重力加速度),需要減9.81能岩。
5.位置傳感器的組成及使用方法
Android提供了磁場傳感器和方向傳感器用于確定設(shè)備的位置寞宫,還提供了測量設(shè)備正面到某一個鄰近物體距離的傳感器(鄰近傳感器)。
鄰近傳感器在手機(jī)中很常見拉鹃。像接聽電話時手機(jī)屏幕滅屏就是使用的鄰近傳感器辈赋。方向傳感器是基于軟件的,該傳感器的回傳數(shù)據(jù)來自加速度傳感器和磁場傳感器膏燕。
位置傳感器對于確定設(shè)備在真實世界中的物理位置非常有用钥屈。例如,可以組合磁場傳感器和加速度傳感器測量設(shè)備相對于地磁北極的位置坝辫,還可以利用方向傳感器確定當(dāng)前設(shè)備相對于自身參照系的位置篷就。
磁場傳感器和方向傳感器都返回值3個值(SensorEvent.values),而鄰近傳感器只返回1個值近忙。
下面我們具體看一下他們的返回值:
方向傳感器:
- SensorEvent.values[0]:繞著Z軸旋轉(zhuǎn)的角度腻脏。如果Y軸(正常拿手機(jī)的方向)正對著北方,該值是0银锻,如果Y軸指向南方永品,改值是180,Y軸指向東方击纬,該值是90鼎姐,如果Y軸指向西方,該值是270更振。
- SensorEvent.values[1]:繞著X軸旋轉(zhuǎn)的度數(shù)炕桨。當(dāng)從Z軸正方向朝向Y軸正方向,改值為正值肯腕。反之献宫,為負(fù)值祠汇。該值在180至-180之間變動顷窒。
- SensorEvent.values[2]:繞著Y軸旋轉(zhuǎn)的度數(shù)。當(dāng)從Z軸正方向朝向X軸正方向硼讽,改值為正值知态。反之捷兰,為負(fù)值。該值在180至-180之間變動负敏。
磁場傳感器: - SensorEvent.values[0]:沿著X軸的磁力(μT贡茅,millitesla)
- SensorEvent.values[1]:沿著Y軸的磁力(μT,millitesla)
- SensorEvent.values[2]:沿著Y軸的磁力(μT,millitesla)
鄰近傳感器:
SensorEvent.values[0]:手機(jī)正面距離鄰近物理的距離(CM)
(1)臨近傳感器
這里以臨近傳感器作為示例工程實現(xiàn)一下顶考,其他傳感器實現(xiàn)大同小異赁还。
public class SensorActivity extends AppCompatActivity implements SensorEventListener {
private TextView tvProximity;
private SensorManager mSensorManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_motion_sensor);
tvProximity = (TextView) findViewById(R.id.tv_proximity);
//獲取傳感器SensorManager對象
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
}
/**
* 傳感器精度變化時回調(diào)
*/
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
/**
* 傳感器數(shù)據(jù)變化時回調(diào)
*/
@Override
public void onSensorChanged(SensorEvent event) {
//判斷傳感器類別
switch (event.sensor.getType()) {
case Sensor.TYPE_PROXIMITY://臨近傳感器
tvProximity.setText(String.valueOf(event.values[0]));
break;
default:
break;
}
}
/**
* 界面獲取焦點,按鈕可以點擊時回調(diào)
*/
protected void onResume() {
super.onResume();
//注冊臨近傳感器
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY),
SensorManager.SENSOR_DELAY_UI);
}
/**
* 暫停Activity驹沿,界面獲取焦點艘策,按鈕可以點擊時回調(diào)
*/
@Override
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
}
運行程序,我間斷的擋住臨近傳感器甚负,看一下效果圖:
[圖片上傳失敗...(image-d6c0ff-1567500246575)]
0.0是我擋住臨近傳感器時候的值柬焕,8.0是我將手移開時的值审残。
下面我們再來看一個比較叼的傳感器梭域,與自然息息相關(guān)。
6.環(huán)境傳感器的組成及使用方法
Android提供了用于檢測不同的外部環(huán)境的傳感器搅轿。例如病涨,可以檢測周圍空氣的濕度、光線璧坟、空氣的壓強(qiáng)和溫度既穆,這些傳感器都是基于硬件的傳感器。除了光線傳感器外雀鹃,其他傳感器在普通的Android設(shè)備中很少見幻工。所以如果使用環(huán)境傳感器,最好運行時對當(dāng)前Android設(shè)備所支持的傳感器進(jìn)行檢測黎茎。
(1)環(huán)境傳感器的返回值
大多數(shù)動作傳感器和位置傳感器都返回多個值囊颅,而所有的環(huán)境傳感器都只返回一個值:
傳感器 | Type值 | 返回值 | 單位 |
---|---|---|---|
溫度傳感器 | TYPE_AMBIENT_TEMPERATURE | event.values[0] | °C |
壓力傳感器 | TYPE_PRESSURE | event.values[0] | hPa |
光線傳感器 | TYPE_LIGHT | event.values[0] | lx |
濕度傳感器 | TYPE_RELATIVE_HUMIDITY | event.values[0] | RH(%) |
注意:環(huán)境傳感器返回的值很少受到雜音的干擾,而動作和位置傳感器經(jīng)常需要消除雜音的影響傅瞻。例如踢代,加速度傳感器要消除重力對其回傳值的影響。
(2)光線傳感器回傳數(shù)據(jù)
//最強(qiáng)的光線強(qiáng)度(估計只有沙漠地帶才能達(dá)到這個值)
public static final float LIGHT_SUNLIGHT_MAX = 120000.0f;
//萬里無云時陽光直射的強(qiáng)度
public static final float LIGHT_SUNLIGHT = 110000.0f;
//有陽光嗅骄,但被云彩抵消了部分光線時的強(qiáng)度
public static final float LIGHT_SHADE = 20000.0f;
//多云時的光線強(qiáng)度
public static final float LIGHT_OVERCAST = 10000.0f;
//太陽剛剛升起時(日出)的光線強(qiáng)度
public static final float LIGHT_SUNRISE = 400.0f;
//在陰雨天胳挎,沒有太陽時的光線強(qiáng)度
public static final float LIGHT_CLOUDY = 100.0f;
//夜晚有月亮?xí)r的光線強(qiáng)度
public static final float LIGHT_FULLMOON = 0.25f;
//夜晚沒有月亮?xí)r的光線強(qiáng)度(當(dāng)然,也不能有路燈溺森,就是漆黑一片)
public static final float LIGHT_NO_MOON = 0.001f;
環(huán)境傳感器的使用方法與動作慕爬、位置傳感器大同小異,在次不再贅述屏积。
相信通過本篇文章的學(xué)習(xí),大家都會有所提高澡罚。碼字不易,喜歡點贊