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>