Android传感器开发(上)

作者: 惜梦哥哥_ | 来源:发表于2017-06-28 14:36 被阅读200次

    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

    相关文章

      网友评论

      • eec1c01d1dc7:写的不错,加油,对于安卓初学者很有帮助

      本文标题:Android传感器开发(上)

      本文链接:https://www.haomeiwen.com/subject/eyeecxtx.html