Android開(kāi)發(fā)高級(jí)進(jìn)階——傳感器

Android系統(tǒng)提供了對(duì)傳感器的支持障涯,如果手機(jī)設(shè)備的硬件提供了這些傳感器罐旗,Android應(yīng)用可以通過(guò)傳感器來(lái)獲取設(shè)備的外界條件,包括手機(jī)設(shè)備的運(yùn)行狀態(tài)唯蝶、當(dāng)前擺放方向九秀、外界的磁場(chǎng)、溫度和壓力等粘我。Android系統(tǒng)提供了驅(qū)動(dòng)程序去管理這些傳感器硬件鼓蜒,當(dāng)傳感器感知到外部環(huán)境發(fā)生改變時(shí),Android系統(tǒng)負(fù)責(zé)管理這些傳感器數(shù)據(jù)征字。

一. Android中11中常見(jiàn)的傳感器


  1. 加速度傳感器:SENSOR_TYPE_ACCELEROMETER
  • 磁力傳感器:SENSOR_TYPE_FIELD
  • 方向傳感器:SENSOR_TYPE_ORIENTATION
  • 陀螺儀傳感器:SENSOR_TYPE_GYROSCOPE
  • 光線感應(yīng)傳感器:SENSOR_TYPE_LIGHT
  • 壓力傳感器:SENSOR_TYPE_PRESSURE
  • 溫度傳感器:SENSOR_TYPE_TEMPERATURE
  • 接近傳感器:SENSOR_TYPE_PROXIMITY
  • 重力傳感器:SENSOR_TYPE_GRAVITY
  • 線性加速度傳感器:SENSOR_TYPE_LINEAR_ACCELERATION
  • 旋轉(zhuǎn)矢量傳感器:SENSOR_TYPE_ROTATION_VECTOR

二. 使用傳感器


使用傳感器的步驟分為5步:

  1. 獲取SensorManager對(duì)象
    調(diào)用Context的getSystemService(Context.SENSOR_SERVICE)方法獲取SensorManager對(duì)象都弹,SensorManager對(duì)象代表系統(tǒng)的傳感器管理服務(wù)。
  2. 獲取Sensor對(duì)象
    調(diào)用SensorManager的getDefaultSensor(int type)方法獲取指定類型的傳感器匙姜。
  3. 注冊(cè)Sensor對(duì)象
    在Activity的onResume()方法中調(diào)用SensorManager的registerListener()方法為指定的傳感器注冊(cè)監(jiān)聽(tīng)器畅厢,程序通過(guò)實(shí)現(xiàn)監(jiān)聽(tīng)器即可獲取傳感器傳來(lái)的數(shù)據(jù)。
  4. 重寫(xiě)onAccuracyChanged搁料,onSensorChanged方法
    當(dāng)傳感器的精度和數(shù)據(jù)發(fā)送變化時(shí)或详,在這兩個(gè)方法中做相應(yīng)的操作。
  5. 注銷Sensor對(duì)象
    在Activity的onPause()方法中調(diào)用SensorManager的unregisterListener()方法注銷指定的傳感器監(jiān)聽(tīng)器郭计。

SensorManager提供的注冊(cè)傳感器的方法為registerListener(SensorEventListener listener, Sensor sensor, int rate)霸琴,該方法的三個(gè)參數(shù)說(shuō)明如下:

  • listener:監(jiān)聽(tīng)傳感器事件的監(jiān)聽(tīng)器。該監(jiān)聽(tīng)器需要實(shí)現(xiàn)SensorEventListener接口昭伸。
  • sensor:傳感器對(duì)象梧乘。
  • rate:指定獲取傳感器數(shù)據(jù)的頻率。rate有以下幾個(gè)頻率值:
    • SensorManager.SENSOR_DELAY_FASTEST:最快庐杨。延遲最小选调,只有特別依賴于傳感器數(shù)據(jù)的應(yīng)用推薦采用這種頻率,這種模式可能造成手機(jī)電量大量消耗灵份。
    • SensorManager.SENSOR_DELAY_GAME:適合游戲的頻率仁堪。一般有實(shí)時(shí)性要求的應(yīng)用適合使用這種頻率。
    • SensorManager.SENSOR_DELAY_NORMAL:正常頻率填渠。一般對(duì)實(shí)時(shí)性要求不是特別高的應(yīng)用適合使用這種頻率弦聂。
    • SensorManager.SENSOR_DELAY_UI:適合普通用戶界面的頻率鸟辅。這種模式比較省電,而且系統(tǒng)開(kāi)銷也很小莺葫,但延遲較大匪凉。

三. 讀取傳感器數(shù)據(jù)


在onSensorChanged(SensorEvent event)方法中有一個(gè)參數(shù)event,通過(guò)event可以獲取傳感器的類型以及傳感器的數(shù)據(jù)捺檬。

  • 獲取傳感器的類型:event.sensor.getType()
  • 獲取傳感器的數(shù)據(jù):event.values[i]再层,i為0,1,2...,不同傳感器堡纬,event.values[i]對(duì)應(yīng)的數(shù)據(jù)不同聂受,下面以加速度傳感器為例,解釋values[i]的含義烤镐。
* <h4>{@link android.hardware.Sensor#TYPE_ACCELEROMETER
     * Sensor.TYPE_ACCELEROMETER}:</h4> All values are in SI units (m/s^2)
     * <ul>
     * <li> values[0]: Acceleration minus Gx on the x-axis </li>
     * <li> values[1]: Acceleration minus Gy on the y-axis </li>
     * <li> values[2]: Acceleration minus Gz on the z-axis </li>
     * </ul>
     * <p>
     * A sensor of this type measures the acceleration applied to the device
     * (<b>Ad</b>). Conceptually, it does so by measuring forces applied to the
     * sensor itself (<b>Fs</b>) using the relation:
     * </p>
     * <b><center>Ad = - &#8721;Fs / mass</center></b>
     * <p>
     * In particular, the force of gravity is always influencing the measured
     * acceleration:
     * </p>
     * <b><center>Ad = -g - &#8721;F / mass</center></b>
     * <p>
     * For this reason, when the device is sitting on a table (and obviously not
     * accelerating), the accelerometer reads a magnitude of <b>g</b> = 9.81
     * m/s^2
     * </p>
     * <p>
     * Similarly, when the device is in free-fall and therefore dangerously
     * accelerating towards to ground at 9.81 m/s^2, its accelerometer reads a
     * magnitude of 0 m/s^2.
     * </p>
     * <p>
     * It should be apparent that in order to measure the real acceleration of
     * the device, the contribution of the force of gravity must be eliminated.
     * This can be achieved by applying a <i>high-pass</i> filter. Conversely, a
     * <i>low-pass</i> filter can be used to isolate the force of gravity.
     * </p>
     * <pre class="prettyprint">
     *     public void onSensorChanged(SensorEvent event)
     *     {
     *          // alpha is calculated as t / (t + dT)
     *          // with t, the low-pass filter's time-constant
     *          // and dT, the event delivery rate
     *          final float alpha = 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];
     *          linear_acceleration[0] = event.values[0] - gravity[0];
     *          linear_acceleration[1] = event.values[1] - gravity[1];
     *          linear_acceleration[2] = event.values[2] - gravity[2];
     *     }
     * </pre>
     * <p>
     * <u>Examples</u>:
     * <ul>
     * <li>When the device lies flat on a table and is pushed on its left side
     * toward the right, the x acceleration value is positive.</li>
     * <li>When the device lies flat on a table, the acceleration value is
     * +9.81, which correspond to the acceleration of the device (0 m/s^2) minus
     * the force of gravity (-9.81 m/s^2).</li>
     * <li>When the device lies flat on a table and is pushed toward the sky
     * with an acceleration of A m/s^2, the acceleration value is equal to
     * A+9.81 which correspond to the acceleration of the device (+A m/s^2)
     * minus the force of gravity (-9.81 m/s^2).</li>
     * </ul>

從加速度傳感器源代碼中可以看出饺饭,values[0]表示x軸上的加速度,values[1]表示y軸上的加速度职车,values[2]表示z軸上的加速度。

四. 針對(duì)是否有傳感器功能優(yōu)化


因?yàn)椴⒎撬惺謾C(jī)都支持所有傳感器鹊杖,不用系統(tǒng)引入的傳感器不同悴灵,所以在使用之前有必要判斷一下,骂蓖、從而提高性能积瞒。

判斷是否有傳感器有兩種方法:

  1. 運(yùn)行時(shí)檢測(cè)
SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
if (sensor != null){
          //傳感器存在
}else{
          //傳感器不存在
}
  1. 使用Android Market過(guò)濾器來(lái)限定目標(biāo)設(shè)備必須帶有指定傳感器配置。
<use-feature 
       name = "android.hardware.sensor.orientation"
       android:required = "true"/>

五. 方向傳感器小Demo


利用方向傳感器登下,界面中的圖片向手機(jī)旋轉(zhuǎn)的反方向旋轉(zhuǎn)茫孔。代碼如下:

public class MainActivity extends AppCompatActivity implements SensorEventListener{

    private ImageView mIvSensor;
    private Sensor mSensor;
    private SensorManager mSensorManager;
    private float mDegress = 0f;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mIvSensor = (ImageView) findViewById(R.id.iv_sensor);

        mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);

    }

    @Override
    protected void onResume() {
        super.onResume();
        mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_UI); //rate suitable for the user interface
    }

    @Override
    protected void onPause() {
        super.onPause();
        mSensorManager.unregisterListener(this);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() == Sensor.TYPE_ORIENTATION){
            float degree = - event.values[0];
            RotateAnimation rotateAnimation = new RotateAnimation(mDegress, degree, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
            rotateAnimation.setDuration(100);
            mIvSensor.startAnimation(rotateAnimation);
            mDegress = degree;
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        //TODO:當(dāng)傳感器精度發(fā)生變化時(shí)
    }
}

演示效果:

orientation_sensor_demo.gif

六. 注意


  1. 別忘記注銷。
  2. 不要阻塞onSensorChanged方法被芳。
  3. 避免使用過(guò)時(shí)的方法或傳感器類型缰贝。
  4. 在使用前先驗(yàn)證傳感器是否存在。
  5. 謹(jǐn)慎選擇傳感器延時(shí)畔濒。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末剩晴,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子侵状,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件预侯,死亡現(xiàn)場(chǎng)離奇詭異翻具,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)艇潭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門拼窥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)戏蔑,“玉大人,你說(shuō)我怎么就攤上這事闯团⌒岭” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵房交,是天一觀的道長(zhǎng)彻舰。 經(jīng)常有香客問(wèn)我,道長(zhǎng)候味,這世上最難降的妖魔是什么刃唤? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮白群,結(jié)果婚禮上尚胞,老公的妹妹穿的比我還像新娘。我一直安慰自己帜慢,他們只是感情好笼裳,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著粱玲,像睡著了一般躬柬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上抽减,一...
    開(kāi)封第一講書(shū)人閱讀 49,764評(píng)論 1 290
  • 那天允青,我揣著相機(jī)與錄音,去河邊找鬼卵沉。 笑死颠锉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的史汗。 我是一名探鬼主播琼掠,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼停撞!你這毒婦竟也來(lái)了眉枕?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤怜森,失蹤者是張志新(化名)和其女友劉穎速挑,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體副硅,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡姥宝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了恐疲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腊满。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡套么,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出碳蛋,到底是詐尸還是另有隱情胚泌,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布肃弟,位于F島的核電站玷室,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏笤受。R本人自食惡果不足惜穷缤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望箩兽。 院中可真熱鬧津肛,春花似錦、人聲如沸汗贫。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)落包。三九已至掀亥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間妥色,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工遏片, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嘹害,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓吮便,卻偏偏與公主長(zhǎng)得像笔呀,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子髓需,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Android傳感器定義 Android 傳感器相關(guān)術(shù)語(yǔ)微機(jī)電傳感器(MEMS)MEMS 通常制作在規(guī)格很小的硅芯...
    Jannonx閱讀 4,323評(píng)論 0 1
  • 傳感器 傳感器Sensor是一種檢測(cè)裝置许师,能感受到被測(cè)量的信息,并能將感受到的信息僚匆,按一定規(guī)律變換成為電信號(hào)或其他...
    Reathin閱讀 6,317評(píng)論 0 5
  • 先說(shuō)一下這篇文章里面的內(nèi)容:TCP 客戶端, 自定義對(duì)話框, 自定義按鈕, ProgressBar豎直顯示, 重力...
    楊奉武閱讀 3,283評(píng)論 0 3
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理微渠,服務(wù)發(fā)現(xiàn),斷路器咧擂,智...
    卡卡羅2017閱讀 134,629評(píng)論 18 139
  • 短似詞語(yǔ)的創(chuàng)作逞盆,今天并不稀奇,或許有些粗鄙松申,有些無(wú)聊云芦,甚至到了廣告詞一樣“瘟疫”的目的俯逾。好的方面,詞語(yǔ)的或音節(jié)的“...
    卜生閱讀 664評(píng)論 0 3