关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » 安卓开发 »Android传感器编程实例源码

    Android传感器编程实例源码

    2014-11-22 00:00:00 出处:oschina
    分享

    一、前言

    我很喜欢电脑,可是笔记本还是太大,笔记本电脑再小还是要弄个小包背起来的,智能手机则不同,它完全就是一个手机,可以随意装在一个口袋里随身携带。因此我在2002年左右时最喜欢玩装备是Dell的PDA,2007年的时候最喜欢玩的是N73,而在2010年最喜欢玩的则是Milestone。眼见着手机的功能越来越强,时至今日智能手机甚至在某些方面已经强过了台式机和笔记本。本节课讲的就是智能手机强过台式机和笔记本的地方:传感器。

    2008年的时候我很喜欢我的小白笔记本Macbook,喜欢玩它的一个小软件,一拍桌子,笔记本感受到了震动,它就转换了一个桌面出来,这让我像个小孩子一样没事就拍拍桌子。这一功能这得益于苹果笔记本内置有传感器。

    我不知道iPhone手机是不是第一个把各种各样的传感器运用在手机上的,不过我知道iPhone是把传感器运用在手机上最成功的第一个。随后的Android系统也内置了大量的传感器,这让Android系统手机和普通的诺基亚智能机和Windows CE智能机相比牛气了许多,在拥有了Milestone之后,我的N73就被仍在抽屉的角落里了。

    从Android1.5开始,系统内置了对多达八种传感器的支持,他们分别是:加速度传感器(accelerometer)、陀螺仪(gyroscope)、环境光照传感器(light)、磁力传感器(magnetic field)、方向传感器(orientation)、压力传感器(pressure)、距离传感器(proximity)和温度传感器(temperature)。

    利用这些传感器我们可以制作出各种有趣的应用程序和游戏。譬如在口袋里晃一晃手机,手机就开始神不知鬼不觉的录音,不要着急这个很容易做,我们在本文的结尾就一起制作这个小应用。

    本讲的学习方式还是在实战中学习,需要提醒的是模拟器中无法模拟传感器,因此你需要准备一款Android真机才能运行本讲的例子。

    二、实例:手机传感器清单

    我们还是先看程序后解释。

    1、创建一个项目 Lesson37_HelloSensor ,主Activity名字叫 mainActivity.java。

    2、UI布局文件main.xml的内容如下:
    XML/HTML代码

    < xml version="1.0" encoding="utf-8" >   
    <linearlayout android:layout_height="fill_parent" android:layout_width="fill_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android">   
    <textview android:layout_height="wrap_content" android:layout_width="fill_parent" android:text="" android:id="@+id/TextView01">   
    </textview></linearlayout>

    3、mainActivity.java的内容如下:

    代码

    package basic.android.lesson37;    
    
    import java.util.List;    
    
    import android.app.Activity;    
    import android.content.Context;    
    import android.hardware.Sensor;    
    import android.hardware.SensorManager;    
    import android.os.Bundle;    
    import android.widget.TextView;    
    
    public class MainActivity extends Activity {    
    
            /** Called when the activity is first created. */   
            @Override   
            public void onCreate(Bundle savedInstanceState) {    
                    super.onCreate(savedInstanceState);    
                    setContentView(R.layout.main);    
    
                    //准备显示信息的UI组建    
                    final TextView tx1 = (TextView) findViewById(R.id.TextView01);    
    
                    //从系统服务中获得传感器管理器    
                    SensorManager sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);    
    
                    //从传感器管理器中获得全部的传感器列表    
                    List<sensor> allSensors = sm.getSensorList(Sensor.TYPE_ALL);    
    
                    //显示有多少个传感器    
                    tx1.setText("经检测该手机有" + allSensors.size() + "个传感器,他们分别是:n");    
    
                    //显示每个传感器的具体信息    
                    for (Sensor s : allSensors) {    
    
                            String tempString = "n" + "  设备名称:" + s.getName() + "n" + "  设备版本:" + s.getVersion() + "n" + "  供应商:"   
                                            + s.getVendor() + "n";    
    
                            switch (s.getType()) {    
                            case Sensor.TYPE_ACCELEROMETER:    
                                    tx1.setText(tx1.getText().toString() + s.getType() + " 加速度传感器accelerometer" + tempString);    
                                    break;    
                            case Sensor.TYPE_GYROSCOPE:    
                                    tx1.setText(tx1.getText().toString() + s.getType() + " 陀螺仪传感器gyroscope" + tempString);    
                                    break;    
                            case Sensor.TYPE_LIGHT:    
                                    tx1.setText(tx1.getText().toString() + s.getType() + " 环境光线传感器light" + tempString);    
                                    break;    
                            case Sensor.TYPE_MAGNETIC_FIELD:    
                                    tx1.setText(tx1.getText().toString() + s.getType() + " 电磁场传感器magnetic field" + tempString);    
                                    break;    
                            case Sensor.TYPE_ORIENTATION:    
                                    tx1.setText(tx1.getText().toString() + s.getType() + " 方向传感器orientation" + tempString);    
                                    break;    
                            case Sensor.TYPE_PRESSURE:    
                                    tx1.setText(tx1.getText().toString() + s.getType() + " 压力传感器pressure" + tempString);    
                                    break;    
                            case Sensor.TYPE_PROXIMITY:    
                                    tx1.setText(tx1.getText().toString() + s.getType() + " 距离传感器proximity" + tempString);    
                                    break;    
                            case Sensor.TYPE_TEMPERATURE:    
                                    tx1.setText(tx1.getText().toString() + s.getType() + " 温度传感器temperature" + tempString);    
                                    break;    
                            default:    
                                    tx1.setText(tx1.getText().toString() + s.getType() + " 未知传感器" + tempString);    
                                    break;    
                            }    
                    }    
    
            }    
    }

    4、连接真机Milestone,编译并运行程序,显示结果如下:

    5、结合上面的程序我们做一些解释。

    1)Android所有的传感器都归传感器管理器 SensorManager 管理,获取传感器管理器的方法很简单:

    String service_name = Context.SENSOR_SERVICE;

    SensorManager sensorManager = (SensorManager)getSystemService(service_name);

    2)现阶段Android支持的传感器有8种,它们分别是:

    3)从传感器管理器中获取其中某个或者某些传感器的方法有如下三种:

    第一种:获取某种传感器的默认传感器

    Sensor defaultGyroscope = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);

    第二种:获取某种传感器的列表

    List<Sensor> pressureSensors = sensorManager.getSensorList(Sensor.TYPE_PRESSURE);

    第三种:获取所有传感器的列表,我们这个例子就用的第三种

    List<Sensor> allSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);

    4)对于某一个传感器,它的一些具体信息的获取方法可以见下表:

    三、实例:窈窈录音器

    通过上面的例子我们学会了如何获得某种类型的传感器,下面我通过一个实例来学会如何使用某一个类型的传感器。我们这里使用加速度传感器来实现这样一个功能:开启我们的录音程序放在你的口袋或者提包里,需要录音的时候把衣服整理一下,或者把提包挪动个位置,那么此时手机就会感受到变化从而开始录音。由此达到神不知鬼不觉的录音效果。说起来似乎有点神,其实做起来很简单,让我们开始吧。

    简单的录音程序已经在第28讲的时候做过了,我们在28讲程序的基础上写本讲的代码。

    1、新建一个项目 Lesson37_YYRecorder ,主文件叫 MainActivity.java 。

    2、这里只贴出于28讲不同的 MainActivity.java 的代码,请注意看注释:

    Java代码

    package basic.android.lesson37;    
    
    import java.io.File;    
    import java.io.IOException;    
    import java.util.Calendar;    
    import java.util.Locale;    
    
    import android.app.Activity;    
    import android.content.Context;    
    import android.hardware.Sensor;    
    import android.hardware.SensorEvent;    
    import android.hardware.SensorEventListener;    
    import android.hardware.SensorManager;    
    import android.media.MediaRecorder;    
    import android.os.Bundle;    
    import android.text.format.DateFormat;    
    import android.view.View;    
    import android.widget.Button;    
    import android.widget.TextView;    
    import android.widget.Toast;    
    
    public class MainActivity extends Activity {    
    
            //录音和停止按钮    
            private Button recordButton;    
            private Button stopButton;    
    
            //检测摇动相关变量    
            private long initTime = 0;    
            private long lastTime = 0;    
            private long curTime = 0;    
            private long duration = 0;    
    
            private float last_x = 0.0f;    
            private float last_y = 0.0f;    
            private float last_z = 0.0f;    
    
            private float shake = 0.0f;    
            private float totalShake = 0.0f;    
    
            //媒体录音器对象    
            private MediaRecorder mr;    
    
            //是否正在录音    
            private boolean isRecoding = false;    
    
            @Override   
            public void onCreate(Bundle savedInstanceState) {    
                    super.onCreate(savedInstanceState);    
                    setContentView(R.layout.main);    
    
                    // UI组件    
                    recordButton = (Button) this.findViewById(R.id.Button01);    
                    stopButton = (Button) this.findViewById(R.id.Button02);    
                    final TextView tx1 = (TextView) this.findViewById(R.id.TextView01);    
    
                    // 录音按钮点击事件    
                    recordButton.setOnClickListener(new View.OnClickListener() {    
    
                            @Override   
                            public void onClick(View v) {    
                                    //假如没有在录音,那么点击按钮可以开始录音    
                                    if(!isRecoding){    
                                            startRecord();    
                                    }    
                            }    
                    });    
    
                    // 停止按钮点击事件    
                    stopButton.setOnClickListener(new View.OnClickListener() {    
    
                            @Override   
                            public void onClick(View v) {    
                                    initShake();    
                                    //假如正在录音,那么可以停止录音    
                                    if (mr != null) {    
                                            mr.stop();    
                                            mr.release();    
                                            mr = null;    
                                            recordButton.setText("录音");    
                                            Toast.makeText(getApplicationContext(), "录音完毕", Toast.LENGTH_LONG).show();    
                                            isRecoding = false;    
    
                                    }    
                            }    
                    });    
    
                    // 获取传感器管理器    
                    SensorManager sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);    
                    // 获取加速度传感器    
                    Sensor acceleromererSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);    
    
                    // 定义传感器事件监听器    
                    SensorEventListener acceleromererListener = new SensorEventListener() {    
    
                            @Override   
                            public void onAccuracyChanged(Sensor sensor, int accuracy) {    
                                    //什么也不干    
                            }    
    
                            //传感器数据变动事件    
                            @Override   
                            public void onSensorChanged(SensorEvent event) {            
    
                                    //假如没有开始录音的话可以监听是否有摇动事件,假如有摇动事件可以开始录音    
                                    if(!isRecoding){    
                                            //获取加速度传感器的三个参数    
                                            float x = event.values[SensorManager.DATA_X];    
                                            float y = event.values[SensorManager.DATA_Y];    
                                            float z = event.values[SensorManager.DATA_Z];    
    
                                            //获取当前时刻的毫秒数    
                                            curTime = System.currentTimeMillis();    
    
                                            //100毫秒检测一次    
                                            if ((curTime - lastTime) > 100) {    
    
                                                    duration = (curTime - lastTime);    
    
                                                    // 看是不是刚开始晃动    
                                                    if (last_x == 0.0f && last_y == 0.0f && last_z == 0.0f) {    
                                                            //last_x、last_y、last_z同时为0时,表示刚刚开始记录    
                                                            initTime = System.currentTimeMillis();    
                                                    } else {    
                                                            // 单次晃动幅度    
                                                            shake = (Math.abs(x - last_x) + Math.abs(y - last_y) + Math.abs(z - last_z)) / duration * 100;    
                                                    }    
    
                                                    //把每次的晃动幅度相加,得到总体晃动幅度    
                                                    totalShake += shake;    
    
                                                    // 判断是否为摇动,这是我自己写的标准,不准确,只是用来做教学示例,别误会了^_^    
                                                    if (totalShake > 10 && totalShake / (curTime - initTime) * 1000 > 10) {    
                                                            startRecord();    
                                                            initShake();    
                                                    }    
    
                                                    tx1.setText("总体晃动幅度="+totalShake+ "n平均晃动幅度="+totalShake / (curTime - initTime) * 1000 );    
                                            }    
    
                                            last_x = x;    
                                            last_y = y;    
                                            last_z = z;    
                                            lastTime = curTime;    
                                    }    
                            }    
    
                    };    
    
                    //在传感器管理器中注册监听器    
                    sm.registerListener(acceleromererListener, acceleromererSensor, SensorManager.SENSOR_DELAY_NORMAL);    
    
            }    
    
            // 开始录音    
            public void startRecord() {    
                    //把正在录音的标志设为真    
                    isRecoding = true;    
                    //存放文件    
                    File file = new File("/sdcard/" + "YY"   
                                    + new DateFormat().format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA)) + ".amr");    
    
                    Toast.makeText(getApplicationContext(), "正在录音,录音文件在" + file.getAbsolutePath(), Toast.LENGTH_LONG).show();    
    
                    // 创建录音对象    
                    mr = new MediaRecorder();    
    
                    // 从麦克风源进行录音    
                    mr.setAudioSource(MediaRecorder.AudioSource.DEFAULT);    
    
                    // 设置输出格式    
                    mr.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);    
    
                    // 设置编码格式    
                    mr.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);    
    
                    // 设置输出文件    
                    mr.setOutputFile(file.getAbsolutePath());    
    
                    try {    
                            // 创建文件    
                            file.createNewFile();    
                            // 准备录制    
                            mr.prepare();    
                    } catch (IllegalStateException e) {    
                            e.printStackTrace();    
                    } catch (IOException e) {    
                            e.printStackTrace();    
                    }    
                    // 开始录制    
                    mr.start();    
                    recordButton.setText("录音中……");    
            }    
    
            //摇动初始化    
            public void initShake() {    
                    lastTime = 0;    
                    duration = 0;    
                    curTime = 0;    
                    initTime = 0;    
                    last_x = 0.0f;    
                    last_y = 0.0f;    
                    last_z = 0.0f;    
                    shake = 0.0f;    
                    totalShake = 0.0f;    
            }    
    }

    4、我们小结一下:到Android2.2版本为止,系统并没有给开发者提供多少可用的包装好的传感器信息,只是提供了传感器发出的原始数据,这些原始数 据存放在 event.values 的数组里,开发人员需要从这些裸数据总自行发掘有用的信息,譬如从加速度传感器的3维裸数据中获得摇动的判断(我的摇动判断很弱智,有时间再改吧……)。 好了本讲就先到这里,关于传感器有机会我们展开再谈,下次再见吧。

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    电脑屏幕不小心竖起来了?别慌,快捷键搞定

    Destoon 模板存放规则及语法参考

    Destoon系统常量与变量

    Destoon系统目录文件结构说明

    Destoon 系统安装指南

    Destoon会员公司主页模板风格添加方法

    Destoon 二次开发入门

    Microsoft 将于 2026 年 10 月终止对 Windows 11 SE 的支持

    Windows 11 存储感知如何设置?了解Windows 11 存储感知开启的好处

    Windows 11 24H2 更新灾难:系统升级了,SSD固态盘不见了...

    IT头条

    Synology 更新 ActiveProtect Manager 1.1 以增强企业网络弹性和合规性

    00:43

    新的 Rubrik Agent Cloud 加速了可信的企业 AI 代理部署

    00:34

    宇树科技 G1人形机器人,拉动一辆重达1.4吨的汽车

    00:21

    Cloudera 调查发现,96% 的企业已将 AI 集成到核心业务流程中,这表明 AI 已从竞争优势转变为强制性实践

    02:05

    投资者反对马斯克 1 万亿美元薪酬方案,要求重组特斯拉董事会

    01:18

    技术热点

    大型网站的 HTTPS 实践(三):基于协议和配置的优化

    ubuntu下右键菜单添加新建word、excel文档等快捷方式

    Sublime Text 简明教程

    用户定义SQL Server函数的描述

    怎么在windows 7开始菜单中添加下载选项?

    SQL Server 2016将有哪些功能改进?

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。