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/

时间: 2024-10-22 10:03:39

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

Android加速度传感器的使用:摇一摇功能的实现

一.原理介绍: Android手机中摇一摇的功能已经很常见了,最近接触到了这个功能,原理很简单:使用加速度传感器,在晃动手机时,监听加速度在各个方向的变化,当加速度值超过设定的灵敏度时,则触发摇一摇功能. 二.使用到的类: SensorManager SensorEventListener 三.功能实现: 1.摇一摇功能:我将摇一摇功能封装成了一个类ShakeUtils,在使用时按照注释中的说明使用即可,ShakeUtils.java如下(差的包请CTRL+SHIFT+O导入): /** * 摇

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

如有转载,请声明出处: 时之沙: http://blog.csdn.net/t12x3456 目前很多应用已经实现了摇一摇功能,这里通过讲解该功能的原理及实现回顾一下加速度传感器的使用: 1.首先获得传感器管理器的实例 sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); 2.通过传感器管理器获得加速传感器 accelerateSensor = getSensorManager(cont

Android 微信摇一摇功能实现

开发之前 今天学习了一下传感器, 脑子里就蹦出了微信的摇一摇, 于是鼓了鼓勇气抽空写了出来, 本人菜鸟一枚, 希望大神们多多指点 开发环境 Android Studio 2.2.1 JDK1.7 API 24 Gradle 2.2.1 相关知识点 加速度传感器 补间动画 手机震动 (Vibrator) 较短 声音/音效 的播放 (SoundPool) 开始开发 案例预览 案例分析 我们接下来分析一下这个案例, 当用户晃动手机时, 会触发加速传感器, 此时加速传感器会调用相应接口供我们使用, 此时

Android摇一摇功能的实现

Android利用传感器实现类似摇一摇功能 1.基本原理 摇一摇功能基本原理是利用手机加速度传感器,当加速度到达某个值时,触发某个事件,如UI改变,手机震动,播放声音,获取数据等事件. 2.传感器原理和使用 传感器原理和使用,可以参见上一篇博客,Android中传感器Sensor的使用 3.声音事件 获取对象MediaPlay类  mediaPlayer=MediaPlayer.create(getApplicationContext(), R.raw.music); 事件触发:mediaPla

android传感器;摇一摇抽签功能

package com.kane.sensortest; import java.util.Random; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Bundle; import android.ap

Android实现摇一摇功能

做过一个小项目,其中实现了摇一摇功能和刮一刮功能还有播放背景音乐等 摇一摇功能主要用到加速度传感器:Sensor.TYPE_ACCELEROMETER 摇一摇功能主要是监听手机加速度变化,当超过设定的某一值时,即触发事件. /** * FileName: MainActivity.java * @desc 该类是用于显示摇一摇界面 * @author HTP * @Date 20140311 * @version 1.00 */ public class MainActivity extends

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

重力传感器微信摇一摇SensorMannager自定义alertdialogSensorEventListener 很多程序中我们可能会输入长文本内容,比如短信,写便笺等,如果想一次性撤销所有的键入内容,很多手机需要一直按住退格键逐字逐句的删除,稍稍麻烦,不过 在iPhone上,有个人性化的功能,当我们想要去撤销刚刚输入的所有内容的时候,可以轻轻晃动手机,会弹出提示框,点击确定就可以清空内容,如下图: 在 android中,一般手机貌似没有定制这个功能,不过我们可以自己去实现这样的功能,放置在我

Android实战简易教程-第三十一枪(基于加速度传感器的摇一摇功能实例)

下面我们来看一下微信摇一摇功能的模拟实现,我们是基于手机加速度传感器实现该功能,实现方法比较简单. MainActivity.java: MainActivity.java: package com.location.activity; import android.app.Activity; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; i

android 实现摇一摇功能

实现"摇一摇"功能,其实很简单,就是检测手机的重力感应,具体实现代码如下: 一.在 AndroidManifest.xml 中添加操作权限 <uses-permission android:name="android.permission.VIBRATE"/> 二.实现代码 [java] view plaincopy package com.xs.test; import android.app.Activity; import android.hard