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. Piggy-Bank

    Piggy-Bank Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Su ...

  2. Encoding 分类: HDU 2015-06-25 21:56 9人阅读 评论(0) 收藏

    Encoding Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  3. Java学习之路(三)

    1:面向对象

  4. 转载-python学习笔记之常用模块用法分析

    内置模块(不用import就可以直接使用)   常用内置函数   help(obj) 在线帮助, obj可是任何类型 callable(obj) 查看一个obj是不是可以像函数一样调用 repr(ob ...

  5. 反射获取类中的属性和set属性

    package framework.base; import java.beans.IntrospectionException; import java.beans.PropertyDescript ...

  6. [Python]如何使用HtmlTestRunner让自动化测试报告内容更丰富

    简述 使用selenium webdriver + Python做自动化测试,执行完成后要生成测试报告,Python我们使用的HTMLtestrunner 进行生成,但是默认提供的生成报告内容,并不能 ...

  7. 静态方法和类成员方法(Python)

    静态方法和成员方法分别在创建时分别被装入Staticmethod 类型和 Classmethod类型的对象中.静态方法的定义没有 self参数,且能够被类本身直接调用,类方法在定义时需要名为 cls的 ...

  8. linux--基础学习笔记--软件安装

  9. Infragistics UltraGrid的使用

    OL SDK:http://help.infragistics.com/ 资料参考:http://blog.csdn.net/andy_212/article/details/4019895 http ...

  10. 【Java】List集合按数量分组

    有时候,我们需要将大的集合按指定的数量分割成若干个小集合.(比如:集合作为SQL中IN的参数,而SQL又有长度限制,所以需要分批分几次进行查询) 虽然此需求感觉不常见,但偶也写过几次类似的方法,故记录 ...