关闭 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维裸数据中获得摇动的判断(我的摇动判断很弱智,有时间再改吧……)。 好了本讲就先到这里,关于传感器有机会我们展开再谈,下次再见吧。

    上一篇返回首页 下一篇

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

    别人在看

    正版 Windows 11产品密钥怎么查找/查看?

    还有3个月,微软将停止 Windows 10 的更新

    Windows 10 终止支持后,企业为何要立即升级?

    Windows 10 将于 2025年10 月终止技术支持,建议迁移到 Windows 11

    Windows 12 发布推迟,微软正全力筹备Windows 11 25H2更新

    Linux 退出 mail的命令是什么

    Linux 提醒 No space left on device,但我的空间看起来还有不少空余呢

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    IT头条

    公安部:我国在售汽车搭载的“智驾”系统都不具备“自动驾驶”功能

    02:03

    液冷服务器概念股走强,博汇、润泽等液冷概念股票大涨

    01:17

    亚太地区的 AI 驱动型医疗保健:2025 年及以后的下一步是什么?

    16:30

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    技术热点

    SQL汉字转换为拼音的函数

    windows 7系统无法运行Photoshop CS3的解决方法

    巧用MySQL加密函数对Web网站敏感数据进行保护

    MySQL基础知识简介

    Windows7和WinXP下如何实现不输密码自动登录系统的设置方法介绍

    windows 7系统ip地址冲突怎么办?windows 7系统IP地址冲突问题的

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

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