Android 摇一摇之双甩功能
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 摇一摇之双甩功能的更多相关文章
- Android仿iPhone晃动撤销输入功能(微信摇一摇功能)
重力传感器微信摇一摇SensorMannager自定义alertdialogSensorEventListener 很多程序中我们可能会输入长文本内容,比如短信,写便笺等,如果想一次性撤销所有的键入内 ...
- android 实现摇一摇功能
实现“摇一摇”功能,其实很简单,就是检测手机的重力感应,具体实现代码如下: 一.在 AndroidManifest.xml 中添加操作权限 二.实现代码 package com.xs.test; im ...
- android 摇一摇功能的实现
将这个功能封装成了一个类,这样今后方便调用 package com.bobo.myyaoyiyaotest; import android.R.bool; import android.content ...
- Android 摇一摇功能的注意事项
/**开始重力传感器的检测*/ public void start() { // 获得传感器管理器 sensorManager = (SensorManager) mContext.getSystem ...
- Android 使用加速度传感器实现摇一摇功能及优化
如有转载,请声明出处: 时之沙: http://blog.csdn.net/t12x3456 目前很多应用已经实现了摇一摇功能,这里通过讲解该功能的原理及实现回顾一下加速度传感器的使用: 1.首先获得 ...
- 【WP开发】实现“摇一摇”功能
尽管我的微信是每八个月登录一次,但我相信各位玩得比我多.微信有一个“摇一摇”功能,这个功能其实是利用了加速度传感器来实现的,这个传感器,我估计再低端的手机都会有的,这是严重基本的传感器. 重力加速度既 ...
- 利用HTML5的一个重要特性 —— DeviceOrientation来实现手机网站上的摇一摇功能
介绍之前做两个声明: 以下代码可以直接运行,当然你别忘了引用jQuery才行. <script> // DeviceOrientation将底层的方向传感器和运动传感器进行了高级封装, ...
- html5实现微信摇一摇功能
在HTML5中,DeviceOrientation特性所提供的DeviceMotion事件封装了设备的运动传感器时间,通过改时间可以获取设备的运动状态.加速度等数据(另还有deviceOrientat ...
- 用HTML5实现手机摇一摇的功能(转)
在百度开发者大会上我介绍过HTML5另外一个重要特性就是DeviceOrientation,它将底层的方向传感器和运动传感器进行了高级封装,提供了DOM事件的支持.这个特性包括两种事件: 1.devi ...
随机推荐
- [Unity3D][Vuforia][ios]使用vuforia的unity3d库在ios中摄像头只显示黑色,不显示摄像头,NO CAMERA的解决方案
注:我使用的是Vuforia 4.0SDK Unity3D5.0版本,跑的ios系统为8.1 我在Vuforia官方讨论贴子中看到这其实是新手都会遇到的问题 贴子地址: https://develop ...
- js笔记---封装自己的Ajax方法
//地址 成功方法 失败方法function Ajax(url, funsucc, funfial) { var oAjax = null; if (window.XMLHttpRequest) { ...
- php编译器
WordPress http://pan.baidu.com/s/1eQnOnv0 epp3: http://pan.baidu.com/s/1pJKFOD1 配合xampp: http://pan. ...
- Java学习之路(五)
1:补充: 使用super也可以调用父类的成员函数 格式 : super.函数名(); 2:抽象类与抽象函数 抽象函数的定义: 只有函数的定义,没有函数体的函数被称为抽象函数 抽象类的定义: 使用 ...
- Python学习笔记-Day2-Python基础之元组操作
元组的常用操作包括但不限于以下操作: 元组的索引,计数等 这里将对列表的内置操作方法进行总结归纳,重点是以示例的方式进行展示. 使用type获取创建对象的类 type(tuple) 使用dir获取类的 ...
- 谈EXPORT_SYMBOL使用
EXPORT_SYMBOL只出现在2.6内核中,在2.4内核默认的非static 函数和变量都会自动导入到kernel 空间的, 都不用EXPORT_SYMBOL() 做标记的.2.6就必须用EXPO ...
- Log4net使用指南
请在这里下载示例代码 1 简介 1.1 Log4net的优点: 几乎所有的大型应用都会有自己的用于跟踪调试的API.因为一旦程序被部署以后,就不太可能再利用专门的 ...
- Flume+kafka+storm+hdfs
摘自:http://www.aboutyun.com/thread-6855-1-1.html
- .Net连接数据库-曾,删,改,查(AOD.Net)
连接数据库 static void Main(string[] args) { //SqlConnection conn = new SqlConnection();//实例化 //conn.Conn ...
- SQL将金额转换为汉子
-- ============================================= -- Author: 苟安廷 -- Create date: 2008-8-13 -- Descrip ...