Android传感器开发(上)

Android传感器简介

最近单位项目遇到了摇一摇功能,正好把以前的笔记翻出来,整合到一起,发个文章,来吧,互相伤害吧.
<br />
本文代码已上传至Github:https://github.com/Xxxxxxyk/SensorDev
<br />
你真的了解我们日常使用的手机么? 平常你在玩微信摇一摇,手电筒,计步器的时候有没有想过这些是怎么实现的呢?其实这些都归功于手机内部的各种硬件传感器.

image.png

认识传感器

在我们开始玩传感器之前,我们先来看下我们的手机中都有什么传感器.

//获取手机基本状态及所有传感器
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_hardlist);
        TextView tv_brand = (TextView) findViewById(R.id.tv_brand);

        //手机号码不一定能获取到
        TelephonyManager tm = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
        tv_brand.setText("品牌: " + Build.BRAND + "\n" + "型号: " + Build.MODEL + "\n" + "Android版本: "
                + android.os.Build.VERSION.RELEASE + "\n" + "IMEI: " + tm.getDeviceId()
                + "\n" + "IMSI: " + tm.getSubscriberId() + "\n" + "手机号码: " + tm.getLine1Number() + "\n"
                + "运营商: " + tm.getSimOperatorName() + "\n");

        sm = (SensorManager) getSystemService(SENSOR_SERVICE);
        List<Sensor> allSensors = sm.getSensorList(Sensor.TYPE_ALL);// 获得传感器列表
        RecyclerView rl_list = (RecyclerView) findViewById(R.id.rv_list);
        rl_list.setLayoutManager(new LinearLayoutManager(this));
        rl_list.setAdapter(new SensorAdapter(this,allSensors));
    }

适配器:

public class SensorAdapter extends RecyclerView.Adapter<SensorAdapter.SensorViewHolder> {

    private final Context context;
    private final List<Sensor> sensors;

    public SensorAdapter(Context context, List<Sensor> sensors) {
        this.context = context;
        this.sensors = sensors;
    }

    @Override
    public SensorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        SensorViewHolder viewHolder = new SensorViewHolder(LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, null));
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(SensorViewHolder holder, int position) {
        holder.mTv_text.setText("类型:" + getChineseName(sensors.get(position).getType()) + "\n" + "设备名称:" + sensors.get(position).getName() + "\n设备版本" + sensors.get(position).getVersion() + "\n");
    }

    @Override
    public int getItemCount() {
        return sensors == null ? 0 : sensors.size();
    }

    class SensorViewHolder extends RecyclerView.ViewHolder {

        private final TextView mTv_text;

        public SensorViewHolder(View itemView) {
            super(itemView);
            mTv_text = (TextView) itemView.findViewById(android.R.id.text1);
        }
    }

    public String getChineseName(int type) {
        switch (type) {
            case Sensor.TYPE_ACCELEROMETER:
                return "加速度传感器";
            case Sensor.TYPE_GYROSCOPE:
                return "陀螺仪传感器";
            case Sensor.TYPE_LIGHT:
                return "环境光线传感器";
            case Sensor.TYPE_MAGNETIC_FIELD:
                return "电磁场传感器";
            case Sensor.TYPE_ORIENTATION:
                return "方向传感器";
            case Sensor.TYPE_PRESSURE:
                return "压力传感器";
            case Sensor.TYPE_PROXIMITY:
                return "距离传感器";
            case Sensor.TYPE_TEMPERATURE:
                return "温度传感器";
            case Sensor.TYPE_GRAVITY:
                return "重场传感器";
            case Sensor.TYPE_LINEAR_ACCELERATION:
                return "线性加速度传感器";
            case Sensor.TYPE_ROTATION_VECTOR:
                return "旋转矢量传感器";
            case Sensor.TYPE_RELATIVE_HUMIDITY:
                return "湿度传感器";
            case Sensor.TYPE_AMBIENT_TEMPERATURE:
                return "温度传感器";
            case Sensor.TYPE_GAME_ROTATION_VECTOR:
                return "游戏旋转矢量传感器";
            case Sensor.TYPE_STEP_COUNTER:
                return "计步器";
            case Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR:
                return "地磁旋转矢量传感器";
            case Sensor.TYPE_SIGNIFICANT_MOTION:
                return "特殊动作触发传感器";
            default:
                return "未知传感器";
        }
    }
}

写好之后我们来运行试一下:

Screenshot_2017-06-27-16-07-52.jpg

楼主用自己手机进行测试的,华为荣耀8(吐槽一句,真难用),基本所有的传感器都被识别了,没有识别的两个一个是霍尔传感器(HALL),另一个是电话传感器(PhoneCall).

传感器开发

震动传感器

官方文档:https://developer.android.google.cn/reference/android/os/Vibrator.html
震动传感器,顾名思义,手机振动全靠它,那么我们如何控制我们的手机震动呢,上代码:

public class VibratorUtils {

    private final Vibrator mVibrator;

    //震动传感器
    public VibratorUtils(Context context){
        //获取系统服务
        mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
    }

    //震动,time为震动时间
    public void shock(long time){
        mVibrator.vibrate(time);
    }
}

很简单,两句代码搞定,调用时只需要传入时间即可,单位是s.(如果我们把时间调成好多好多秒,会不会有什么神奇的事情发生呢,我这么纯洁肯定不知道)

image.png
闪光灯

官方文档:https://developer.android.google.cn/reference/android/hardware/camera2/CameraManager.html
好了好了,不开车,接下来我们看看我们平常使用的手电筒是怎么实现的,需要注意的是,以下代码只运行在API21以上,并且你有闪光灯:

public class FlashLampUtils {

    //闪光灯
    private final CameraManager mSystemService;

    public FlashLampUtils(Context context) {
        //获取系统服务
        mSystemService = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
    }

    @TargetApi(Build.VERSION_CODES.M)
    public void openLamp(){
        if(!isLOLLIPOP()){
            return;
        }
        try {
            mSystemService.setTorchMode("0", true);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    @TargetApi(Build.VERSION_CODES.M)
    public void closeLamp(){
        if(!isLOLLIPOP()){
            return;
        }
        try {
            mSystemService.setTorchMode("0", false);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 判断Android系统版本
     *
     * @return boolean
     */
    private boolean isLOLLIPOP() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            return true;
        } else {
            return false;
        }
    }
}

只需要调用,闪光灯就可以亮起来了,除此之外,很多手机中都有手电筒的SOS功能,其实也非常简单,大家可以自行尝试.

image.png
指纹传感器

官方文档:https://developer.android.google.cn/reference/android/support/v4/hardware/fingerprint/package-summary.html
Google在API 23之后在官方API中加入了指纹API,方便用户进行指纹的一系列操作,那么我们怎么给我们自己的APP加入指纹功能呢,代码如下:

public class FingerPrintUtils {

    //指纹传感器
    public static final String TAG = "惜梦哥哥_";
    private final FingerprintManagerCompat mManagerCompat;

    public FingerPrintUtils(Context context) {
        mManagerCompat = FingerprintManagerCompat.from(context);
    }

    public void checkFingerPrint(){
        /**
         * 检查是否支持指纹识别
         */
        if(mManagerCompat.hasEnrolledFingerprints()){
            mManagerCompat.authenticate(null, 0, null, new FingerprintManagerCompat.AuthenticationCallback() {
                /**
                 *  出现错误回调,多次尝试失败也会调用
                 */
                @Override
                public void onAuthenticationError(int errMsgId, CharSequence errString) {
                    Log.e(TAG,errMsgId + "--------" + errString.toString());
                }

                /**
                 *  错误信息提示
                 */
                @Override
                public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
                    Log.e(TAG,helpMsgId + "--------" + helpString.toString());
                }

                /**
                 *  当验证的指纹成功时会回调此函数,然后取消监听
                 */
                @Override
                public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
                    Log.e(TAG,"验证成功");
                }

                /**
                 * 指纹验证失败
                 */
                @Override
                public void onAuthenticationFailed() {
                    Log.e(TAG,"验证失败");;
                }
            }, null);
        };
    }
}

这里验证的指纹就是你在系统中设置的指纹,可以在回调中进行不同操作.

image.png
光线传感器

官方文档:https://developer.android.google.cn/reference/android/hardware/Sensor.html#TYPE_LIGHT
光线传感器是用来感应手机周围的亮度的,我们的手机上的自动调整亮度功能离不开这个传感器,让我们来看下你的周围的亮度有多少吧

public class LightUtils {
    private final Sensor mDefaultSensor;
    private final SensorManager mSystemService;

    //光线传感器

    public LightUtils(Context context) {
        mSystemService = (SensorManager) context.getSystemService(SENSOR_SERVICE);
        mDefaultSensor = mSystemService.getDefaultSensor(Sensor.TYPE_LIGHT);

    }

    public void getLightNum(SensorEventListener sensorEventListener) {
        mSystemService.registerListener(sensorEventListener, mDefaultSensor, SensorManager.SENSOR_DELAY_UI);
    }
}

调用时需要传入SensorEventListener 对象,这个对象中有两个方法,当传感器的值发生变化时,会调用onSensorChanged方法,当传感器的精度发生变化时,会调用onAccuracyChanged,这里我们只需要在onSensorChanged方法中处理我们的操作就可以

 @Override
    public void onSensorChanged(SensorEvent sensorEvent) {
        mBtn_light.setText("当前亮度" + sensorEvent.values[0]);
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int i) {

    }
image.png
加速传感器

官方文档:https://developer.android.google.cn/reference/android/hardware/Sensor.html#TYPE_ACCELEROMETER
加速传感器,就是我们平常进行摇(YUE)一(PAO)摇时采用的传感器,手动脸红.

//SensorManager代表了各类传感器的集合
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
if (mSensorManager != null) {
    //加速传感器
    mMSensorManagerDefaultSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    if (mMSensorManagerDefaultSensor != null) {
        mSensorManager.registerListener(this, mMSensorManagerDefaultSensor, SensorManager.SENSOR_DELAY_UI);
    }
}

加载完成传感器之后在回调方法中进行操作

private static final int UPTATE_INTERVAL_TIME = 50;
//灵敏度调节
private static final int SPEED_SHRESHOLD = 30;
private long lastUpdateTime;
private float lastX;
private float lastY;
private float lastZ;

........

@Override
public void onSensorChanged(SensorEvent sensorEvent) {
    long currentUpdateTime = System.currentTimeMillis();
    long timeInterval = currentUpdateTime - lastUpdateTime;
    if (timeInterval < UPTATE_INTERVAL_TIME) {
        return;
    }
    lastUpdateTime = currentUpdateTime;
    // 传感器信息改变时执行该方法
    float[] values = sensorEvent.values;
    float x = values[0]; // x轴方向的重力加速度,向右为正
    float y = values[1]; // y轴方向的重力加速度,向前为正
    float z = values[2]; // z轴方向的重力加速度,向上为正
    float deltaX = x - lastX;
    float deltaY = y - lastY;
    float deltaZ = z - lastZ;

    lastX = x;
    lastY = y;
    lastZ = z;
    double speed = (Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) / timeInterval) * 100;
    if (speed >= SPEED_SHRESHOLD) {
        mVibrator.vibrate(300);
        Toast.makeText(this, "摇一摇震动", Toast.LENGTH_SHORT).show();
    }
}

@Override
public void onAccuracyChanged(Sensor sensor, int i) {

}

这里有个坑,大家要注意啦:

注册监听器的时候需要在onStart方法中注册,取消监听器需在onPause方法中取消,原因是因为Activity的生命周期问题,避免按Home键之后感应依旧存在,造成不必要的Bug.
@Override
protected void onStart() {
    super.onStart();
    shake();
}

@Override
protected void onPause() {
    if (mSensorManager != null) {
        mSensorManager.unregisterListener(this);
    }
    super.onPause();
}
image.png

结尾

好了,本次就介绍这个5个传感器吧,希望大家可以尝试一下,因为这个真的很好玩哟.最后再推荐一首歌,英文歌,但是真的很好听:

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,277评论 25 707
  • afinalAfinal是一个android的ioc,orm框架 https://github.com/yangf...
    passiontim阅读 15,383评论 2 44
  • JQuery源码分析 我们通过对jQuery1.4.2版本的分析,了解jQuery原理 最外层 将代码放到匿名函数...
    whitsats阅读 1,661评论 0 2
  • 我曾在林中送走夕阳, 却不曾在花间迎你; 今天我看了白雪纷纷, 却感受不到你的冷暖。 柔软的雪地, 我写下你, 共...
    纳人阅读 622评论 13 17
  • 昨天从家出发的时候,我与父亲在外边等车,父亲在嘱咐我一些事情,明显可以感觉到他心里的不舍。他说一年到头才回来,没钱...
    语书阅读 139评论 0 2