Android搖一搖振動效果Demo

前言

在微信剛流行的時候,在搖一搖還能用來那啥的時候,我也曾深更半夜的拿著手機晃一晃。當時想的最多的就是,我靠,為神馬搖一下需要用這麼大的力度,當時我想可能騰訊覺得那是個人性的設計,後來才發覺尼馬重力加速度設得太高瞭吧。扯多瞭,最近項目裡需要解決一個振動的問題,因此在學習振動實現的過程中,寫瞭個demo實現瞭搖一搖振動的效果,這裡記錄一下。

原理

搖一搖功能的基本原理就是:利用手機的加速度傳感器,當加速度到達某個值時,觸發某個事件,例如手機振動、UI改變等。這裡要實現該功能,首先需要瞭解一下Android傳感器的使用。

Android傳感器Sensor使用

Android中有多種傳感器,目前Android SDK支持的傳感器包括:加速度傳感器、光線傳感器、陀螺儀傳感器、重力傳感器、方向傳感器、磁場傳感器、壓力傳感器等。但是並不是所有手機都具有這些傳感器的,因為傳感器需要money,因此廉價的手機會選擇常用的傳感器來添加,而且一些高端機型則基本上具有大多數傳感器。

Sensor使用步驟

Android傳感器的使用步驟大致可分為三步:
1. 獲取傳感器管理服對象 SensorManager。
2. 創建傳感器事件監聽類,該類必須實現android.hardware.SensorEventListener接口。
3. 使用SensorManager.registerListener方法註冊指定的傳感器。

傳感器事件接口

SensorEventListener接口,該接口的onSensorChanged()和onAccuracyChanged()方法用於處理相應的傳感器事件。

public interface SensorEventListener {

    /**
     * Called when sensor values have changed.
     * 

See {@link android.hardware.SensorManager SensorManager} * for details on possible sensor types. *

See also {@link android.hardware.SensorEvent SensorEvent}. * *

NOTE: The application doesn't own the * {@link android.hardware.SensorEvent event} * object passed as a parameter and therefore cannot hold on to it. * The object may be part of an internal pool and may be reused by * the framework. * * @param event the {@link android.hardware.SensorEvent SensorEvent}. */ public void onSensorChanged(SensorEvent event); /** * Called when the accuracy of a sensor has changed. *

See {@link android.hardware.SensorManager SensorManager} * for details. * * @param accuracy The new accuracy of this sensor */ public void onAccuracyChanged(Sensor sensor, int accuracy); }

Android振動實現

Android振動效果實現主要是依靠Vibrator服務,具體調用方法如下代碼所示:

import android.app.Activity;
import android.app.Service;
import android.os.Vibrator;

public class VibratorHelper {
	public static void Vibrate(final Activity activity, long milliseconds) {
		Vibrator vibrator = (Vibrator) activity
				.getSystemService(Service.VIBRATOR_SERVICE);
		vibrator.vibrate(milliseconds);
	}

	public static void Vibrate(final Activity activity, long[] pattern,
			boolean isRepeat) {
		Vibrator vibrator = (Vibrator) activity
				.getSystemService(Service.VIBRATOR_SERVICE);
		vibrator.vibrate(pattern, isRepeat ? 1 : -1);
	}
}

同時,還需要在AndroidManifest.xml裡增加振動權限:

    

解釋一下Vibrate方法的參數:
1. long milliseconds:振動的時長,單位是毫秒。
2. long[] pattern:自定義振動模式。數組中數字的含義依次是[靜止時長, 振動時長, 靜止時長, 振動時長, ……]。振動時長的單位是毫秒。
3. repeat:是否重復振動,1為重復,-1為隻振動一次。

搖一搖振動Demo實現

好瞭,瞭解瞭搖一搖需要借助加速度傳感器,振動需要借助Vibrator服務,那就直接來寫代碼瞭。MainActivity類實現如下:

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

public class MainActivity extends Activity {
	private SensorManager sensorManager;
	private SensorEventListener shakeListener;
	private AlertDialog.Builder dialogBuilder;

	private boolean isRefresh = false;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
		shakeListener = new ShakeSensorListener();

		dialogBuilder = new AlertDialog.Builder(this);
		dialogBuilder.setPositiveButton("確定", new OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				isRefresh = false;
				dialog.cancel();
			}
		}).setMessage("搖到瞭一個漂亮妹子!").create();
	}

	@Override
	protected void onResume() {
		sensorManager.registerListener(shakeListener,
				sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
				SensorManager.SENSOR_DELAY_FASTEST);
		super.onResume();
	}

	@Override
	protected void onPause() {
		// acitivity後臺時取消監聽
		sensorManager.unregisterListener(shakeListener);

		super.onPause();
	}

	private class ShakeSensorListener implements SensorEventListener {
		private static final int ACCELERATE_VALUE = 20;

		@Override
		public void onSensorChanged(SensorEvent event) {

//			Log.e("zhengyi.wzy", "type is :" + event.sensor.getType());

			// 判斷是否處於刷新狀態(例如微信中的查找附近人)
			if (isRefresh) {
				return;
			}

			float[] values = event.values;

			/**
			 * 一般在這三個方向的重力加速度達到20就達到瞭搖晃手機的狀態 x : x軸方向的重力加速度,向右為正 y :
			 * y軸方向的重力加速度,向前為正 z : z軸方向的重力加速度,向上為正
			 */
			float x = Math.abs(values[0]);
			float y = Math.abs(values[1]);
			float z = Math.abs(values[2]);

			Log.e("zhengyi.wzy", "x is :" + x + " y is :" + y + " z is :" + z);
			
			if (x >= ACCELERATE_VALUE || y >= ACCELERATE_VALUE
					|| z >= ACCELERATE_VALUE) {
				Toast.makeText(
						MainActivity.this,
						"accelerate speed :"
								+ (x >= ACCELERATE_VALUE ? x
										: y >= ACCELERATE_VALUE ? y : z),
						Toast.LENGTH_SHORT).show();

				VibratorHelper.Vibrate(MainActivity.this, 300);
				isRefresh = true;
				dialogBuilder.show();
			}

		}

		@Override
		public void onAccuracyChanged(Sensor sensor, int accuracy) {
			// TODO Auto-generated method stub
		}

	}

}

效果圖:

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。