Android 摇一摇之双甩功能

最近做一个摇一摇的功能 网上相关代码很多 但是这次的需求有点奇葩 要求是摇两次才生效

看起来好像很简单 但真正要做遇到的问题还是很多 时间限制 机型灵敏性 摇动的方式 弄了一周多 做出的效果算一般吧

原理介绍

其实就是加速度传感器的使用 开发传感器应用的步骤如下

1 调用Context的getSystemService(Context.SENSOR_SERVICE)方法获取 SensorManager对象

SensorManager代表系统的传感器管理服务2 调用SensorManager的getDefaultSensor(int type)获取指定类型的传感器

3 在Activity的onResume()方法中调用SensorManager的registerListener()为指定传感器注册监听

程序通过实现监听器可获取传感器传回来的数据

registerListener(SensorEventListener listener, Sensor sensor, int rateUs)

listener 监听传感器事件的监听器 该监听需要实现SensorEventListener接口

sensor 传感器对象

rateUs 获取传感器数据的频率 支持4个频率值

SENSOR_DELAY_FASTEST 最快 延迟小 耗电

SENSOR_DELAY_GAME 适合游戏

SENSOR_DELAY_UI 正常频率

SENSOR_DELAY_NORMAL 省电 延迟大

上代码

public class AccelerometerTest extends Activity
implements SensorEventListener
{
// 定义系统的Sensor管理器
SensorManager sensorManager;
EditText etTxt1; @Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取程序界面上的文本框组件
etTxt1 = (EditText) findViewById(R.id.txt1);
// 获取系统的传感器管理服务
sensorManager = (SensorManager) getSystemService(
Context.SENSOR_SERVICE); //①
} @Override
protected void onResume()
{
super.onResume();
// 为系统的加速度传感器注册监听器
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_GAME); //②
} @Override
protected void onStop()
{
// 取消注册
sensorManager.unregisterListener(this);
super.onStop();
} // 以下是实现SensorEventListener接口必须实现的方法
// 当传感器的值发生改变时回调该方法
@Override
public void onSensorChanged(SensorEvent event)
{
float[] values = event.values;
StringBuilder sb = new StringBuilder();
sb.append("X方向上的加速度:");
sb.append(values[0]);
sb.append("\nY方向上的加速度:");
sb.append(values[1]);
sb.append("\nZ方向上的加速度:");
sb.append(values[2]);
etTxt1.setText(sb.toString());
} // 当传感器精度改变时回调该方法。
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy)
{
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/tip" />
<EditText
android:id="@+id/txt1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:editable="false"
android:cursorVisible="false" />
</LinearLayout>

返回的三个值分别代表在X Y Z三个方向上的加速度

X轴沿屏幕向左

Y轴沿屏幕向上

Z轴垂直于屏幕向里

下面给出双甩功能的代码 主要原理是判断速度阀值 并加入时间限制

MainActivity

public class MainActivity extends Activity{

  EditText etTxt1;
private ShakeListener mShakeListener; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etTxt1 = (EditText) findViewById(R.id.txt1);
} @Override
protected void onResume() {
super.onResume();
//注册
mShakeListener = new ShakeListener(this);
mShakeListener.setOnShakeListener(new ShakeListener.OnShakeListener() { @Override
public void onShake() {
Log.i("TAG", "震动震动震动震动震动震动震动震动震动震动震动震动震动震动震动震动震动震动震动震动");
Vibrator vVi = (Vibrator)getSystemService(Service.VIBRATOR_SERVICE);
vVi.vibrate(400); StringBuilder sb = new StringBuilder();
sb.append(mShakeListener.getSpeed());
etTxt1.setText(sb.toString());
}
}); } @Override
protected void onStop() {
super.onStop();
// 取消注册
mShakeListener.stop();
} }

ShakeListener

public class ShakeListener implements SensorEventListener {

  private Context mContext;
private Sensor sensor; // 传感器
private SensorManager sensorManager; // 传感器管理器
private OnShakeListener onShakeListener; // 手机上一个位置时重力感应坐标
private float lastX;
private float lastY;
private float lastZ;
private double speed; private long lastUpdateTime;
int UPTATE_INTERVAL_TIME = 70;// 两次检测的时间间隔
int SPEED_SHRESHOLD = 3000;// 速度阈值 // 双甩
int count = 0;
int timeSlice = 0; // 时间片 final int GET_SUCC = 0;
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case GET_SUCC:
count = 0;
timeSlice = 0;
break;
}
}
}; public ShakeListener(Context mContext) {
super();
this.mContext = mContext;
start();
} //开始
public void start() {
// 获得传感器管理器
sensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
if (sensorManager != null) {
// 获得重力传感器
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
// 注册
if (sensor != null) {
sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST);
} }
//停止
public void stop() {
sensorManager.unregisterListener(this);
} // 设置重力感应监听器
public void setOnShakeListener(OnShakeListener listener) {
onShakeListener = listener;
} @Override
public void onSensorChanged(SensorEvent event) { long currentUpdateTime = System.currentTimeMillis(); // 现在检测时间
long timeInterval = currentUpdateTime - lastUpdateTime; // 两次检测的时间间隔
if (timeInterval < UPTATE_INTERVAL_TIME) // 判断是否达到了检测时间间隔
return;
lastUpdateTime = currentUpdateTime; // 现在的时间变成last时间 float[] values = event.values;
// 获得x,y,z坐标
float x = event.values[0];
float y = event.values[1];
float z = event.values[2]; // 获得x,y,z的变化值
float deltaX = x - lastX;
float deltaY = y - lastY;
float deltaZ = z - lastZ; // 将现在的坐标变成last坐标
lastX = x;
lastY = y;
lastZ = z; speed = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) * 10000 / timeInterval;
Log.i("TAG", "speed" + speed);
Log.i("TAG", "count---" + count);
Log.i("TAG", "timeSlice---" + timeSlice); //限制两次摇动在1S的时间内
if (count == 1) {
timeSlice++;
if (timeSlice * UPTATE_INTERVAL_TIME > 1000) {
count = 0;
timeSlice = 0;
}
} if (speed > SPEED_SHRESHOLD) {
Log.i("TAG", " 摇一摇---------------------------------------------------------------------------------------------------摇一摇"); count++; if (count == 2) { count = 0;
//如果两次触发在300毫秒之内 只能算一次
if (timeSlice * UPTATE_INTERVAL_TIME < 300) {
count = 1;
} else {
onShakeListener.onShake(); handler.removeMessages(GET_SUCC);
handler.sendEmptyMessageDelayed(GET_SUCC, 300);
} timeSlice = 0;
}
} } @Override
public void onAccuracyChanged(Sensor sensor, int accuracy) { } public interface OnShakeListener {
public void onShake();
} public double getSpeed() {
return speed;
} }

activity_main

<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.example.accelerometertest.MainActivity" > <EditText
android:id="@+id/txt1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/> </RelativeLayout>

加速度传感器Demo https://github.com/huanyi0723/Accelerometer/

双甩功能Demo https://github.com/huanyi0723/AccelerometerTest/

Android 摇一摇之双甩功能的更多相关文章

  1. Android仿iPhone晃动撤销输入功能(微信摇一摇功能)

    重力传感器微信摇一摇SensorMannager自定义alertdialogSensorEventListener 很多程序中我们可能会输入长文本内容,比如短信,写便笺等,如果想一次性撤销所有的键入内 ...

  2. android 实现摇一摇功能

    实现“摇一摇”功能,其实很简单,就是检测手机的重力感应,具体实现代码如下: 一.在 AndroidManifest.xml 中添加操作权限 二.实现代码 package com.xs.test; im ...

  3. android 摇一摇功能的实现

    将这个功能封装成了一个类,这样今后方便调用 package com.bobo.myyaoyiyaotest; import android.R.bool; import android.content ...

  4. Android 摇一摇功能的注意事项

    /**开始重力传感器的检测*/ public void start() { // 获得传感器管理器 sensorManager = (SensorManager) mContext.getSystem ...

  5. Android 使用加速度传感器实现摇一摇功能及优化

    如有转载,请声明出处: 时之沙: http://blog.csdn.net/t12x3456 目前很多应用已经实现了摇一摇功能,这里通过讲解该功能的原理及实现回顾一下加速度传感器的使用: 1.首先获得 ...

  6. 【WP开发】实现“摇一摇”功能

    尽管我的微信是每八个月登录一次,但我相信各位玩得比我多.微信有一个“摇一摇”功能,这个功能其实是利用了加速度传感器来实现的,这个传感器,我估计再低端的手机都会有的,这是严重基本的传感器. 重力加速度既 ...

  7. 利用HTML5的一个重要特性 —— DeviceOrientation来实现手机网站上的摇一摇功能

      介绍之前做两个声明: 以下代码可以直接运行,当然你别忘了引用jQuery才行. <script> // DeviceOrientation将底层的方向传感器和运动传感器进行了高级封装, ...

  8. html5实现微信摇一摇功能

    在HTML5中,DeviceOrientation特性所提供的DeviceMotion事件封装了设备的运动传感器时间,通过改时间可以获取设备的运动状态.加速度等数据(另还有deviceOrientat ...

  9. 用HTML5实现手机摇一摇的功能(转)

    在百度开发者大会上我介绍过HTML5另外一个重要特性就是DeviceOrientation,它将底层的方向传感器和运动传感器进行了高级封装,提供了DOM事件的支持.这个特性包括两种事件: 1.devi ...

随机推荐

  1. JAVA基础知识之网络编程——-使用Proxy创建连接

    在前面的HTTP网络通信的例子中,使用了URLConnection conn = url.openConnection();连接网络, 如果改用URLConnection conn = url.ope ...

  2. EasyUI的DataGrid 打印导出

    EasyUI的DataGrid 打印导出   一直在Winform和WPF的项目,偶尔接触Web都是网上下个模板修修改改就成了,学习的不太深入. 今日遇到一个打印导出datagrid的问题,做桌面项目 ...

  3. unicode下char*和CString和一些数据之间的转换

    首先mfc下字符串只有两种数据:char(一个字节)和wchar_t(两个字节),很多其他数据类型如TCHAR,WCHAR等都是这个两个基本类型的宏定义,BYTE是uchar 1.对话框打印char* ...

  4. 获取或者设置时,无后缀和A后缀和W后缀的区别

    SetWindowTextW表示设置的字符串是WCHAR (双字节字符 )SetWindowTextA表示设置的字符串是CHAR (单字节字符 )SetWindowText表示设置的字符串是自动匹配当 ...

  5. xtrabackup 安装、备份、还原及错误处理 教程

    xtrabackup 是MYSQL的一个备份软件 Xtrabackup是一个对InnoDB做数据备份的工具,支持在线热备份(备份时不影响数据读写),是商业备份工具InnoDB Hotbackup的一个 ...

  6. UVA 11552 四 Fewest Flops

    Fewest Flops Time Limit:2000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Statu ...

  7. 命令行运行R语言脚本(代码)

    1 Windows: 键入 cd C:\Program Files\R\R-3.2.0\bin   工作目录切换到R的核心程序目录 键入 R BATCH F:\Test.R 或 Rscript F:\ ...

  8. Django 过滤器 实例

    实例1 safe让Html标签以及一些特殊符号(如<)生效,下面以例子说明: # value = '<b>CPT</b>' # 那么输出的时候,CPT就是加粗的,如果不加 ...

  9. spring引入实体类映射文件

    由于spring对hibernate配置文件hibernate.cfg.xml的集成相当好  LocalSessionFactoryBean有好几个属性用来查找hibernate映射文件:  mapp ...

  10. 二叉树hdu1710

    学习二叉树,看了两天也不明白,唉!acm之路让我体验到要付出巨大的努力,废话不多说,看我网上找到的代码: 此题题意很明确,给你先序遍历,中序遍历,求后序遍历.但代码就让我找不到东西了. http:// ...