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. [Ogre]纹理设置

    MaterialPtr material= MaterialManager::getSingleton().create("name",“ResourcesGroupName”); ...

  2. 八大排序算法之六--交换排序—快速排序(Quick Sort)

    基本思想: 1)选择一个基准元素,通常选择第一个元素或者最后一个元素, 2)通过一趟排序讲待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小.另一部分记录的 元素值比基准值大. 3 ...

  3. 转 python range 用法

    详细记录python的range()函数用法   使用python的人都知道range()函数很方便,今天再用到他的时候发现了很多以前看到过但是忘记的细节.这里记录一下range(),复习下list的 ...

  4. 杭电1005-Number Sequence

    问题描述 A number sequence is defined as follows:f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2) ...

  5. Poj(1273),最大流,EK

    Drainage Ditches Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 69355   Accepted: 2687 ...

  6. 好玩的代码之C++实现CPU满载

    #include <windows.h> #include <iostream> #include <cstdlib> using namespace std; D ...

  7. BZOJ 2879 美食节(费用流-动态加边)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2879 题意:有n道菜,每道菜需要b[i]份,m个厨师,第j个厨师做第i道菜需要时间a[i ...

  8. [Unity3D]开发视图中的标记 - Gizmos

    这个类用来做自己的组件很不错,比如下面这个图的路径点,他其实是个Empty Object,可以自己加脚本让他带上标记.官方解释还可以用来做帮助提示的-.- 大游戏场景的制作时候,你可以用这个在地图上写 ...

  9. Sql合并两个select查询

    现有2个查询,需要将每个查询的结果合并起来(注意不是合并结果集,因此不能使用union),可以将每个查询的结果作为临时表,然后再从临时表中select所需的列,示例如下:   SELECT get.d ...

  10. Highlighting Text Item On Entry In Oracle Forms

    Highlight a Text Item in Oracle Forms With Visual Attribute It is very necessary to highlight the cu ...