古人学问无遗力,少壮工夫老始成。纸上得来终觉浅,绝知此事要躬行。
——陆游《冬夜读书示子聿》
小弟初学安卓,该文算是小弟的学习过程,课后笔记与一些自己的思考,希望在自己的自学路上留下印记,也许有一些自己想的不对的地方,希望各位前辈斧正。
一、安卓手机上的传感器
传感器是一种检测装置,能感受到我们需要测量的信息,并通过一些方式反馈给我们。对于一台安卓设备,可能有以下传感器(API 24):
- 加速度传感器
- 磁场传感器
-
方向传感器(高版本已弃用,改由上面两个传感器搭配完成方向传感器效果) - 陀螺仪
- 光照传感器
- 压力传感器
- 温度传感器
- 近距离传感器
- 重力传感器
- 线性加速度传感器
- 旋转矢量传感器
......
其中像温度传感器、压力传感器这种我们一般的安卓手机应该不会有(压力传感器是用来测压强的)。
二、简单使用光照传感器
光照传感器基本目前出的手机都带有了(一般在手机头部,与听筒、前置摄像头在一排的一个椭圆形),它最常见的使用就是手机屏幕亮度的自动调节,它能根据房间或室外的光照强度来调节屏幕亮度(然而我觉得一点儿也不好用),还有一种使用就是当我们接电话时,手机屏幕靠近耳朵,此时光照较小,它能帮我们熄屏省电(这个还挺好)。
安卓传感器在使用上大体相同,不论如何,第一步都是获取 SensorManager 的实例,这会需要用到系统服务:
SensorManager senserManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
然后我们就可以利用这个传感器管理者实例来获取我们需要的传感器实例了,要获取光照传感器:
private Sensor mLightSensor;
......
mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
getDefaultSensor方法中所填的参数就代表我们要获取的传感器类型,具体有哪些参数可以进入源码中查看。
我们手机使用传感器,当然并不是只想知道传感器测量出的那个值是多少啦,我们需要的是通过这个值来在手机上能够进行相应的操作,比如游戏中赛车转个向什么的,所以我们就需要用到传感器事件监听器SensorEventListener:
private SensorEventListener mSensorEventListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_LIGHT) {
float value = event.values[0];
mTextView.setText(String.format("光照强度为:%slx", value));
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
这个监听器中需要实现接口中两个方法,onSensorChanged和onAccuracyChanged,当传感器检测数值变化会调用前者,当传感器精度发生变化则调用后者(前者检测数值的报告精度)。这段监听器代码就是为了在TextView显示光照强度值,首先我们用if语句判断事件所属传感器是不是光照传感器,再执行的操作。这里,event.value[]数组就是传感器检测到的各项数据,比如加速度传感器会获取X.Y.Z轴的数据,就会各在数组中有一个下标元素。光照传感器为什么是用value[0]呢,这里需要看源码的注释:
{@link android.hardware.Sensor#TYPE_LIGHT Sensor.TYPE_LIGHT}:
values[0]: Ambient light level in SI lux units //没错它只有一个值
这时,我们的应用还无法使用传感器,我们还需要先将传感器注册才可以:
mSensorManager.registerListener(mSensorEventListener, mLightSensor, SensorManager.SENSOR_DELAY_GAME);
其中第三个参数代表传感器的反应延迟,有四个值:
/** get sensor data as fast as possible */
public static final int SENSOR_DELAY_FASTEST = 0;
/** rate suitable for games */
public static final int SENSOR_DELAY_GAME = 1;
/** rate suitable for the user interface */
public static final int SENSOR_DELAY_UI = 2;
/** rate (default) suitable for screen orientation changes */
public static final int SENSOR_DELAY_NORMAL = 3;
当我们不使用传感器的话,我们应该注销传感器监听器。
mSensorManager.unregisterListener(mSensorEventListener);
根据建议,注册和注销监听器,应该分别在onResume()和onPause()两个回调方法中,因为传感器是非常耗电的。
这里放一个自己做的一个用光照传感器做的小DEMO:
package com.rmaple.android.easysensordemo;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private SensorManager mSensorManager;
private TextView mTextView;
private Sensor mLightSensor;
private ImageView mFanImageView;
private float mFromDegrees = 0F;
private float mDegrees;
private int mNowGears = 0;
private TextView mGearsTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.textView);
mGearsTextView = (TextView) findViewById(R.id.textView_gears);
mFanImageView = (ImageView) findViewById(R.id.fan_imageView);
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
}
private SensorEventListener mSensorEventListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_LIGHT) {
float value = event.values[0];
mTextView.setText(String.format("光照强度为:%slx", value));
if (value == 0F) {
mNowGears = 0;
mGearsTextView.setText("关");
mFanImageView.clearAnimation();
}
if (value > 0F && value <= 3F && mNowGears != 1) {
mNowGears = 1;
spinning(360F, mNowGears);
}
if (value > 3F && value <= 7F && mNowGears != 2) {
mNowGears = 2;
spinning(720F, mNowGears);
}
if (value > 15 && mNowGears != 3) {
mNowGears = 3;
spinning(900F, mNowGears);
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
private void spinning(float increaseDegrees, int nowGears) {
mGearsTextView.setText(String.format("现在档位: %s档", nowGears));
mDegrees += increaseDegrees;
RotateAnimation rotateAnimation = new RotateAnimation(mFromDegrees, mDegrees, Animation.RELATIVE_TO_SELF, 0.5F, Animation.RELATIVE_TO_SELF, 0.5F);
rotateAnimation.setDuration(500);
rotateAnimation.setInterpolator(new LinearInterpolator());
rotateAnimation.setRepeatCount(-1);
mFanImageView.startAnimation(rotateAnimation);
mFromDegrees = mDegrees;
}
@Override
protected void onResume() {
super.onResume();
mSensorManager.registerListener(mSensorEventListener, mLightSensor, SensorManager.SENSOR_DELAY_GAME);
}
@Override
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(mSensorEventListener);
}
@Override
protected void onDestroy() {
super.onDestroy();
// Log.i("MainActivity-", "onDestroy");
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.rmaple.android.easysensordemo.MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:textSize="24sp"
tools:text="123"/>
<TextView
android:id="@+id/textView_gears"
android:layout_width="wrap_content"
android:layout_marginTop="10dp"
android:layout_height="wrap_content"
android:layout_below="@id/textView"
android:layout_centerHorizontal="true"
android:textSize="20sp"
tools:text="123"/>
<ImageView
android:id="@+id/fan_imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/fan"/>
</RelativeLayout>
利用视图动画做了个伪光照电风扇(啊哈哈哈),GIF太大上传不了,蛋疼。