Android Gusture 手勢識別小案例
Step1: 生成一個Android Gusture Builder程序用于畫Gusture然后存儲起來用于其它的項目
首先導入 android SDK \android-sdk-windows\samples\android-8\ 目錄下的GestureBuilder項目,用于生成Gusture類庫
導入過程中要加入幾個文件才能導入到Eclipse中,如下圖所示: 這幾個文件可以從任意android項目中copy
.classpath .project default.properties 3個文件
導入之后生成項目如下圖所示: 將該項目安裝到模擬器中,如下圖所示:

step2:應用此程序生成我們需要的手勢,點擊 Add gesture按鈕添加手勢,隨便添加幾個手勢之后
然后會在sdcard中生成一個gusture文件 如圖所示

step2:將此gusture文件導出到桌面,然后再復制到新建的項目中去
step3:新建項目Gusture,并將剛才的gusture文件導入到/res/raw目錄下 ,如下圖所示

step4: 設計應用的UI界面,main.xml
<?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">
<android.gesture.GestureOverlayView
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/gesture"
android:gestureStrokeType="multiple"/><!-- 多筆手勢 -->
<!-- android:layout_weight="0" 值越低越先賦值
所以先對Button賦值再對android.gesture.GestureOverlayView賦值 -->
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:text="@string/recognize"
android:onClick="findGesture" />
</LinearLayout>
string.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, MainActivity!</string>
<string name="app_name">手勢識別</string>
<string name="notfind">手勢不匹配</string>
<string name="notfull">手勢匹配度太低</string>
<string name="recognize">識別</string>
</resources>
step5:MainActivity.java
package cn.roco.gesture;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Intent;
import android.gesture.Gesture;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;
import android.gesture.GestureOverlayView;
import android.gesture.Prediction;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity {
private static final String TAG="MainActivity";
private GestureLibrary library;
private Gesture mygesture;
private GestureOverlayView gestureOverlayView ;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
/** 根據放入到res/raw/目錄下的gestures文件生成GestureLibrary手勢庫 */
library = GestureLibraries.fromRawResource(this, R.raw.gestures);
/**加載手勢庫*/
library.load();
gestureOverlayView = (GestureOverlayView) this
.findViewById(R.id.gesture);
/**只能監聽單筆手勢*/
/* gestureOverlayView
.addOnGesturePerformedListener(new MyGesturePerformedListener());*/
/**可以監聽單筆手勢也可以監聽多筆手勢*/
gestureOverlayView.addOnGestureListener(new MyGestureListener());
}
/**
* 處理按鈕響應的方法
* 點擊識別按鈕 開始識別手勢
*/
public void findGesture(View view){
recognizeGesture(mygesture);
//清除畫出的手勢
gestureOverlayView.clear(true);
}
private final class MyGestureListener implements android.gesture.GestureOverlayView.OnGestureListener{
@Override
public void onGestureStarted(GestureOverlayView overlay,
MotionEvent event) {
Log.i(TAG, "onGestureStarted");
}
@Override
public void onGesture(GestureOverlayView overlay, MotionEvent event) {
Log.i(TAG, "onGesture");
}
@Override
public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) {
Log.i(TAG, "onGestureEnded");
/**取得用戶最后畫完后的手勢*/
mygesture=overlay.getGesture();
}
@Override
public void onGestureCancelled(GestureOverlayView overlay,
MotionEvent event) {
Log.i(TAG, "onGestureCancelled");
}
}
/**
* 用戶繪制完手勢后響應
*/
private final class MyGesturePerformedListener implements
android.gesture.GestureOverlayView.OnGesturePerformedListener {
@Override
public void onGesturePerformed(GestureOverlayView overlay,
Gesture gesture) {
recognizeGesture(gesture);
}
}
/**識別手勢*/
private void recognizeGesture(Gesture gesture) {
/**
* 從手勢庫中查詢匹配的內容, 匹配結果可能包含多個相似的內容,
* 匹配度高的結果放在最前面 */
ArrayList<Prediction> predictions = library.recognize(gesture);
if (!predictions.isEmpty()) {
Prediction prediction=predictions.get(0);
if (prediction.score>=6) { //匹配度大于等于60%
if ("ouyang".equals(prediction.name)) {
/**調用手機撥號程序*/
Intent intent=new Intent(Intent.ACTION_CALL,Uri.parse("tel:15245474568"));
startActivity(intent);
}else if("close".equals(prediction.name)){
finish();//關閉Activity 會引發onDestory方法
}
}else{
//手勢匹配度太低
Toast.makeText(getApplicationContext(), R.string.notfull, 1)
.show();
}
} else {
//不匹配
Toast.makeText(getApplicationContext(), R.string.notfind, 1)
.show();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
/** 殺掉本應用的進程
* 第一種方法:首先獲取當前進程的id,如何殺死該進程
*/
android.os.Process.killProcess(android.os.Process.myPid());//關閉應用
/**
* 關閉應用還有2種方法
*
* 第二種方法:終止當前正在運行的Java虛擬機,導致程序終止
* System.exit(0);
*
*
* 第三種方法:強制關閉與該包有關聯的一切執行
* android.app.ActivityManager manager=(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
manager.restartPackage(getPackageName());
還要添加權限才行
<uses-permission android:name="android.permission.CALL_PHONE"/>
*
*/
}
}
step6:AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.roco.gesture"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<!-- 撥打電話的權限 -->
<uses-permission android:name="android.permission.CALL_PHONE"/>
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
step7:將項目部署到模擬器中,如果所示界面:

然后畫手勢 點擊“識別”按鈕進行識別 上面的時候一點擊 就退出了此應用
然后畫手勢 點擊“識別”按鈕進行識別 就激活了撥號程序進行撥號

然后畫手勢 點擊“識別”按鈕進行識別 顯示匹配度太低
附注:自己寫一個添加手勢的應用
AddGesture.java
package cn.roco.gesture;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.gesture.Gesture;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;
import android.gesture.GestureOverlayView;
import android.gesture.GestureOverlayView.OnGesturePerformedListener;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
/**
* 添加手勢
*/
public class AddGesture extends Activity {
EditText editText;
GestureOverlayView gestureOverlayView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.addgesture);
// 獲取文本編輯器
editText = (EditText) findViewById(R.id.gesture_name);
// 獲取手勢編輯視圖
gestureOverlayView = (GestureOverlayView) findViewById(R.id.gesture);
// 設置手勢的繪制顏色
gestureOverlayView.setGestureColor(Color.RED);
// 設置手勢的繪制寬度
gestureOverlayView.setGestureStrokeWidth(4);
// 為 gesture的手勢完成事件綁定事件監聽器
gestureOverlayView
.addOnGesturePerformedListener(new OnGesturePerformedListener() {
@Override
public void onGesturePerformed(GestureOverlayView overlay,
final Gesture gesture) {
// 加載save.xml界面布局代表的視圖
View saveDialog = getLayoutInflater().inflate(
R.layout.save, null);
// 獲取 saveDialog里的ImageView組件
ImageView imageView = (ImageView) saveDialog
.findViewById(R.id.show);
// 獲取 saveDialog里的 EditText組件
final EditText gestureName = (EditText) saveDialog
.findViewById(R.id.gesture_name);
// 根據 Gesture包含的手勢創建一個位圖
Bitmap bitmap = gesture.toBitmap(128, 128, 10,
0xFFFF0000);
imageView.setImageBitmap(bitmap);
// 使用對話框顯示saveDialog組件
new AlertDialog.Builder(AddGesture.this)
.setView(saveDialog)
.setPositiveButton("保存", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
// 獲取指定的文件對應的手勢庫
GestureLibrary gestureLibrary = GestureLibraries
.fromFile("/sdcard/gestures");
// 添加手勢
gestureLibrary.addGesture(gestureName
.getText().toString(), gesture);
// 保存手勢庫
gestureLibrary.save();
Toast.makeText(getApplicationContext(), "保存成功", 1).show();
}
})
.setNegativeButton("取消", null)
.show();
}
});
}
}addgesture.xml
<?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:text="請在下面屏幕上繪制手勢" android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<!-- 使用手勢繪制組件 -->
<android.gesture.GestureOverlayView
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_weight="1" android:id="@+id/gesture"
android:gestureStrokeType="multiple" /><!-- 多筆手勢 -->
</LinearLayout>save.xml
<?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">
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<TextView android:text="請輸入保存的手勢名稱"
android:layout_marginRight="8dip" android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!-- 定義一個文本框來讓用戶輸入手勢名 -->
<EditText android:layout_width="fill_parent"
android:layout_height="wrap_content" android:id="@+id/gesture_name" />
</LinearLayout>
<ImageView android:id="@+id/show" android:layout_marginTop="10dp"
android:layout_width="128dp" android:layout_height="128dp " />
</LinearLayout>
