Android--Sensor傳感器


前言

  Android提供了對設備傳感器的支持,只要Android設備的硬件提供了這些傳感器,Android應用可以通過傳感器來獲取設備的外界條件,包括手機的運行狀態、當前擺放的方向等。Android系統還提供了驅動程序去管理這些傳感器硬件,可以通過監聽器的方式監聽傳感器硬件感知到的外部環境的變化。本篇博客主要講解如何簡單的使用Android下的傳感器,最后將以一個簡單的Demo演示。

 

開發傳感器應用步驟

  開發一個對於傳感器支持的應用十分簡單,開發人員只要在傳感器管理器SensorManager中為所要監聽的傳感器指定一個監聽器即可,當外部環境發生變化的時候,Android系統會通過傳感器獲取外部環境的數據,然后將數據傳遞給監聽器的監聽回調方法。具體步驟如下:

  1. 獲取傳感器服務
  2. 從傳感器服務中獲取到指定類型的傳感器
  3. 使用傳感器服務添加傳感器的監聽器
  4. 在使用完之后,注銷傳感器的監聽器

  

獲取傳感器服務

  Android中內置了很多系統級的服務,用於給開發人員使用,而傳感器也是通過傳感器服務,SensorManager來管理的。而在Android組件中獲取系統服務,使用方法Context.getSystemService(String)即可,它的參數均以static final的方式定義在Context中,而獲取SensorManager需要傳入Context.SENSOR_SERVICE。

1         manager=(SensorManager) getSystemService(SENSOR_SERVICE);

 

從傳感器服務中獲取到指定類型的傳感器

  傳感器服務管理設備上所有的傳感器,所以需要指定待監聽的傳感器。獲取待監聽的傳感器,需要使用SensorManager.getDefaultSensor()方法,它的完整簽名如下:

    Sensor getDefaultSensor(int type)

  Android中的傳感器需要Sensor支持,getDefaultSensor()方法通過指定的type參數獲取到相對應的傳感器。type參數被以static final的方式定義在Sensor內部,方便開發人員可以直接使用。下面介紹幾個常用傳感器的type:

  • Sensor.TYPE_ORIENTATION:方向傳感器。
  • Sensor.TYPE_ACCELEROMETER:重力傳感器。
  • Sensor.TYPE_LIGHT:光線傳感器。
  • Sensor.TYPE_MAGNETIC_FIELD:磁場傳感器。

 

使用傳感器服務添加傳感器的監聽器

  獲得SensorManager和Sensor對象之后,就可以為其Sensor注冊監聽器了。為傳感器注冊監聽器,使用SensorManager.registerListener()方法即可,它存在多個重載方法,但是有些方法已經過時了,下面提供一個常用的方法的簽名:

    boolean registerListener(SensorEventListener listener,Sensor sensor,int rateUs)

  上面方法參數的意義:listener:傳感器的監聽器、sensor:待監聽的傳感器、rateUs:傳感器的采樣率。

  從registerListener()方法可以看出,它需要傳遞一個SensorEventListener對象,它就是傳感器的監聽器,其中包含兩個方法,需要開發人員去實現它:

  • void onAccuracyChanged(Sensor sensor,int accuracy):當傳感器精度發生變化時回調。
  • void onSensorChanged(SensorEvent event):當傳感器感應的值發生變化時回調。

  對於上面兩個方法,傳感器的精度一般是不會發生改變的,所以我們一般主要的代碼量在onSensorChanged()中。

 

  registerListener()方法還有一個rateUs的參數,它表示監聽傳感器改變的采樣率,就是從傳感器獲取值的頻率。它被定義以static final的形式定義在SensorManager中,方便我們直接使用,它定義了如下幾個選項:

  • SensorManager.SENSOR_DELAY_FASTEST:最快,延遲最小。
  • SensorManager.SENSOR_DELAY_GAME:適合游戲的頻率。
  • SensorManager.SENSOR_DELAY_NORMAL:正常頻率。
  • SensorManager.SENSOR_DELAY_UI:適合普通用戶界面UI變化的頻率。

  Android為我們提供了這幾個采樣率的參數,方便我們使用。但對於選擇那種采樣率而言,並不是越快越好,要參照實際開發的應用的情況來說,采樣率越大,將越耗費資源,包括電量、CPU等,所以要根據實際情況選擇,畢竟再強大的應用,如果造成設備續航能力的降低,也是會被用戶所不喜的。

 

在使用完之后,注銷傳感器的監聽器

  當使用完傳感器之后,需要為其注銷監聽器,因為傳感器的監聽器並不會因為應用的結束而自行釋放資源,需要開發人員在適當的時候主動注銷。注銷傳感器監聽器使用SensorManager.unregisterListener()方法即可,和監聽器的注冊方法一樣,它也具有多個重載的方法,但是有一些已經被棄用了,下面介紹一個常用的完整簽名:

    void unregisterListener(SensorEventListener listener)

 

指南針Demo

  上面已經講解了在應用中使用傳感器的步驟以及具體內容,下面通過一個簡單的Demo來演示一下如何使用傳感器。在Demo中監聽方向傳感器,使其角度的變化改變來操作方向,模擬一個指南針的效果。

  重寫監聽器的onSensorChanged()方法,其中event獲取當當前監聽事件的參數,可以使用values[0]獲取到當前的方向傳感器感應到的角度。參照官方文檔,可以看出,它代表一個360°的角度,規則是: 0=North, 90=East, 180=South, 270=West。

  下面直接貼代碼了,注釋比較全,就不再贅述了,會用到補間動畫的內容,對補間動畫不了解的朋友,可以看看另外一篇博客:Android--Tween補間動畫。還有一點需要注意的是就是傳感器的Demo需要在真機上測試,因為模擬器上不存在傳感器硬件。

 1 package com.example.sensormanagerdemo;
 2 
 3 import android.hardware.Sensor;
 4 import android.hardware.SensorEvent;
 5 import android.hardware.SensorEventListener;
 6 import android.hardware.SensorManager;
 7 import android.os.Bundle;
 8 import android.view.animation.Animation;
 9 import android.view.animation.RotateAnimation;
10 import android.widget.ImageView;
11 import android.app.Activity;
12 
13 public class MainActivity extends Activity {
14     private ImageView iv_compass;
15     private SensorManager manager;
16     private float startDegree = 0f;
17 
18     @Override
19     protected void onCreate(Bundle savedInstanceState) {
20         super.onCreate(savedInstanceState);
21         setContentView(R.layout.activity_main);
22 
23         iv_compass = (ImageView) findViewById(R.id.iv_compass);
24         // 獲得傳感器管理器
25         manager = (SensorManager) getSystemService(SENSOR_SERVICE);
26 
27     }
28 
29     @Override
30     protected void onResume() {
31         super.onResume();
32         // 為方向傳感器注冊監聽器
33         manager.registerListener(listener,
34                 manager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
35                 SensorManager.SENSOR_DELAY_UI);
36 
37     }
38 
39     private SensorEventListener listener = new SensorEventListener() {
40 
41         @Override
42         public void onSensorChanged(SensorEvent event) {
43             if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
44                 // 獲取當前傳感器獲取到的角度
45                 float degree = -event.values[0];
46                 // 通過補間動畫旋轉角度 從上次的角度旋轉
47                 RotateAnimation ra = new RotateAnimation(startDegree, degree,
48                         Animation.RELATIVE_TO_SELF, 0.5f,
49                         Animation.RELATIVE_TO_SELF, 0.5f);
50                 ra.setDuration(200);
51                 iv_compass.startAnimation(ra);
52                 // 記錄當前旋轉后的角度
53                 startDegree = degree;
54             }
55         }
56 
57         @Override
58         public void onAccuracyChanged(Sensor sensor, int accuracy) {
59 
60         }
61     };
62 
63     @Override
64     protected void onStop() {
65         // 為傳感器注銷監聽器
66         manager.unregisterListener(listener);
67         super.onStop();
68     }
69 }

  效果展示:

 

  源碼下載

 

總結

  本篇博客講解了Android下如何使用傳感器,只是簡單的介紹了一下,對於傳感器獲取到的數值,都在event.values數組中,但是不同傳感器獲取到的值不同,具體情況具體分析,這里就不再深入討論了。 

 

 


免責聲明!

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



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