android学习笔记---47-android_手势识别技术的实现,手势库的创建

2013年5月9日
47_手势识别
--------------------
第一步:建立手势库
使用SDK自带例子GestureBuilder建立手势库(位置:android-sdk-windows\samples\android-8\GestureBuilder)。使用GestureBuilder之前,你需要恢复其到开发环境,然后进行编绎并部署到手机上。此时,就可以使用GestureBuilder建立手势库,生成的手势库文件在SCDard上,默认文件名称为:gestures

第二步:在应用中加载手势库文件,然后开发手势识别代码。
把手势库文件gestures文件拷贝到项目的res/raw目录下。然后在布局文件中添加用于手势绘制的View:
 <android.gesture.GestureOverlayView
    android:id="@+id/gestures"
    android:layout_width="fill_parent“ android:layout_height="0dip"
    android:layout_weight="1.0"
    />
大多数情况下,手势都是通过一笔完成。然而有一些特别的需求就需要通过多个笔画来实现,这时可以使用gestureStrokeType属性进行设置:Multiple:1

手势识别代码见ppt下方
public class MainActivity extends Activity {
    private GestureOverlayView gestureOverlayView;
    private GestureLibrary mLibrary;
    private boolean state;
    private EditText addressText;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        addressText = (EditText)this.findViewById(R.id.address);
        gestureOverlayView = (GestureOverlayView)this.findViewById(R.id.gestures);
        //当用户完成一次Gesture绘制后,系统将自动调用Listener对象的onGesturePerformed()方法
        gestureOverlayView.addOnGesturePerformedListener(new GestureListener());
        mLibrary = GestureLibraries.fromRawResource(this, R.raw.gestures);
        state = mLibrary.load();//加载手势库
    }
   
    private final class GestureListener implements GestureOverlayView.OnGesturePerformedListener{
  @Override
  public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
   if(state){
    List<Prediction> predictions = mLibrary.recognize(gesture);//从手势库中查询匹配的内容,匹配的结果可能包括多个相似的结果,匹配度高的结果放在最前面
    if(!predictions.isEmpty()){
     Prediction prediction = predictions.get(0);
     //prediction的score属性代表了与手势的相似程度
     //prediction的name代表手势对应的字母
     if(prediction.score > 1){
      addressText.setText(prediction.name);
     }
    }
   }
  }
    }
}
---------------------------------------
2.相关理解:手势识别其实就是图形识别,当用户画出图形后,由程序识别然后按照识别的结果进行执行。
----------------------------------------------------------------------------------------------------
3.导入一个android项目到eclipse工作workspace中的方法:
  a.在已经workspace已经存在的android项目中拷贝.classpath,.project,project.properties(这里应该是default.properties文件)到
    需要导入的项目中
  b.然后直接导入项目到eclipse中就可以了
  ---------------------------------------------------------
4.a、这里要实现的功能是,当用户画出一个对勾后,关闭该应用。
  b、当用户画一个L后,就给李德伟打电话
  ------------------------------------------------------
5.首先要建立手势库,手势识别的时候会从手势库中查找,如果找到就执行相应的业务功能
----------------------------------------------------------------
6.WARNING: Application does not specify an API level requirement!
[2009-12-27 16:51:33 - Tank] WARNING: Application does not specify an API level requirement!
[2009-12-27 16:51:33 - Tank] Device API version is 3 (Android 1.5)
网上一查是由于没有指定users sdk的缘故,修改AndroidManifest.xml文件.
加入:
<uses-sdk android:minSdkVersion="3"></uses-sdk>
加在<manifest> </manifest> 之间.
------------------------------------------------------
7.2013/5/10
----------------
8.[2013-05-10 22:54:48 - GestureBuilder] Re-installation failed due to different application signatures.
[2013-05-10 22:54:48 - GestureBuilder] You must perform a full uninstall of the application. WARNING: This will remove the application data!
[2013-05-10 22:54:48 - GestureBuilder] Please execute 'adb uninstall com.android.gesture.builder' in a shell.
[2013-05-10 22:54:48 - GestureBuilder] Launch canceled!
这时先运行android模拟机,进入命令行,当然你要定位adb.exe的目录,我是放在E:\android\android-sdk-windows\platform-tools 下
 E:\android\android-sdk-windows\platform-tools> adb uninstall com.android.gesture.builder.
 重新运行就可以了
 --------------------------------------------------
9.这里建立手势库的时候,用的是android自带的一个例子:
  这个例子可以在这里找到:
  G:\李鹏视频\andoid程序学习及开发\3G手机Android应用开发\3G手机Android应用开发开发资料\开发资料\android-sdk_r06-windows\android-sdk-windows\samples\android-8
  就是这个项目:GestureBuilder
  ---------------------------------------
10.如果出现问题按照上面的方法进行解决
   运行该例子程序后:点击Add gesture进行手势添加,也就是添加用户自己画的图片
   添加的时候,只要在空白区域画出手势,在Name中输入手势名称就,然后点击Done就
   可以添加一个手势了
-------------------------------
11.当添加完手势后,可以查看在sdcard根目录下,有gestures这个文件,这个就是手势库文件
   也是一个数据库文件,这时候就可以在这个手势库的基础上进行手势的查找识别了。
   ---------------------------------------------------------------------------------------
   11-1:做的时候首先将上一步生成的手势库文件gestures复制到:/gesture/res/raw/gestures这个路径下,当查不到的时候需要关闭应用
   11-2:关闭应用的方法:
          当应用不再使用时,通常需要关闭应用,可以使用以下两种方法关闭android应用:

第一种方法:首先获取当前进程的id,然后杀死该进程。 (建议使用)
android.os.Process.killProcess(android.os.Process.myPid())

第二种方法:终止当前正在运行的Java虚拟机,导致程序终止
System.exit(0);

第三种方法:强制关闭与该包有关联的一切执行
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);   
manager.restartPackage(getPackageName());
<uses-permission android:name="android.permission.RESTART_PACKAGES" />
----------------------------------------------------------------------------------------
12.下面是手势识别实例的所有源码:
   屏幕布局:
   --------------
   整个屏幕都是供用户绘制手势
   在屏幕右下角有个识别按钮
---------------------------------
  a.新建android项目:gesture
  b./gesture/src/com/credream/gesture/GestureActivity.java
    package com.credream.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.GestureOverlayView.OnGestureListener;
import android.gesture.GestureOverlayView.OnGesturePerformedListener;
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 GestureActivity extends Activity {
 private static final String TAG = "GestureActivity";
    private  GestureLibrary library;
 private Gesture mgesture;
    private GestureOverlayView overlayView;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //fromRawResource从raw这个手势库文件中得到手势对象
        library = GestureLibraries.fromRawResource(this, R.raw.gestures);
        //加载手势对象
        library.load();
        //获取overlayView,也就是用户识别手势的画板。
        overlayView = (GestureOverlayView) this.findViewById(R.id.gestures);
        //只针对单笔手势:overlayView.addOnGesturePerformedListener(new GesturePerformedListener());
        //当用户绘制完手势之后,就会触发一个事件
        //overlayView.addOnGesturePerformedListener(new GesturePerformedListener());
        //注意这里GesturePerformedListener这个方法只是针对单笔手势的,用户画多笔的时候会没有响应
        overlayView.addOnGestureListener(new GestureListener());
        //addOnGestureListener,这个方法,既可以实现单笔手势,也可以实现多笔手势
    }
    // ②.在这个方法中识别手势
    public void find(View v){
     recognize(mgesture);
     //②.1 识别完之后,清除。
     overlayView.clear(true);
    }
    //②.下面这个方法可以识别单笔,也可以识别多笔。
    private final class GestureListener implements OnGestureListener{
 
     public void onGestureStarted(GestureOverlayView overlay, MotionEvent event) {
   Log.i(TAG, "onGestureStarted()");
   //可以打印到控制台,得到这三个方法的调用顺序。
   //-----------------------------------------
   /*这三个方法的调用顺序是,当用户画第一笔的时候,调用onGestureStarted方法
    * 当用户在画第一笔的过程中不断调用onGesture这个方法
    * 当用户画完第一笔的时候调用onGestureEnded这个方法
    * 当用户开始画第二笔的时候调用onGestureStarted这个方法,一次循环。。
    * */
   //-------------------------------------------
  }
  public void onGesture(GestureOverlayView overlay, MotionEvent event) {
   Log.i(TAG, "onGesture()");
  }
  public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) {
   Log.i(TAG, "onGestureEnded()");
   //因为这个方法是最后调用的,所以在这个方法里得到用户最后画完的手势
   mgesture = overlay.getGesture();
   //取得用户最后画完的手势
  }
  public void onGestureCancelled(GestureOverlayView overlay, MotionEvent event) {
   Log.i(TAG, "onGestureCancelled()");
  }
    }
    //①.以下方法只识别单笔绘图。
  //当用户绘制完手势之后,就会触发一个事件,就会调用这个方法,把用户绘制完的手势传进来
    private final class GesturePerformedListener implements OnGesturePerformedListener{
  //overlay这个参数其实就是取得用户绘制所用的那个画板,这里是overlayView
     public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
   //在这个方法中就来识别用户画出的手势,也就是把用户绘制的手势在手势库中查找,查找到就是
      //代表可以识别。
      //这时候把导出的手势库文件gesture,添加到
      ///gesture/res/raw这个路径中,注意这里raw是新建的文件夹
      //然后查看R文件就可以看到下面这些:
      //public static final int gestures=0x7f040000;
      //识别手势, recognize(gesture)这个方法会在手势库中查找,如果找到匹配项
      //会以集合的形式返回
      
     //ArrayList<Prediction> predictions=library.recognize(gesture);
     //这个集合中的元素排序原则是最匹配的在最上边,其次是不怎么匹配的。
     //这个方法会把所有匹配的记录查询出来,并且把最匹配的在最上边
       recognize(gesture);
  }  
    }
   
    private void recognize(Gesture gesture) {
     //这个集合中的元素排序原则是最匹配的在最上边,其次是不怎么匹配的。
     //这个方法会把所有匹配的记录查询出来,并且把最匹配的在最上边
     ArrayList<Prediction> predictions = library.recognize(gesture);
  if(!predictions.isEmpty()){//当结果集合不是空的时候,就说明有匹配
   //得到最匹配的那个,也就是第一条记录
   Prediction prediction = predictions.get(0);
   //prediction.score>0-10这个是匹配值,范围:prediction.score>0-10
   //这个值为10的时候,代表手势库中的图和用户绘制的图有10%的匹配度
   if(prediction.score >= 6){
    //这里要求匹配度要在60%以上
    //如果名称为李德伟lidewei
    if("lidewei".equals(prediction.name)){
     //调用打电话意图,
     Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:1350505050"));
     //通过意图调用打电话的activity,这里需要有拨号权限
     startActivity(intent);
    }else if("close".equals(prediction.name)){
     finish();//关闭Activity,也就是关闭窗口
    //当activity关闭的时候,其实应用还存在,这里需要关闭应用
     //当activity关闭的时候,会调用onDestroy方法,在这个方法里
     //可以直接杀掉进程
    }
   }else{
    //匹配度不够6的时候,提示匹配度太低
    Toast.makeText(getApplicationContext(), R.string.low, 1).show();
   }
  }else{
   //没有匹配的记录
   Toast.makeText(getApplicationContext(), R.string.notfind, 1).show();
  }
 }
 @Override
 protected void onDestroy() {
  super.onDestroy();
  //这里直接杀掉进程:首先取得当前进程的id,然后调用killProcess杀掉进程
          android.os.Process.killProcess(android.os.Process.myPid());//关闭应用
 }
}
-----------------------------------------------------------
c./gesture/res/values/strings.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="low">匹配度太低</string>
    <string name="recognize">识别</string>
</resources>
--------------------------------------------------
d./gesture/AndroidManifest.xml
  <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.credream.gesture"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:label="@string/app_name"
            android:name=".GestureActivity" >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
<!-- 由于识别成功后会给李德伟拨打电话,所以这里需要这个权限 -->
<uses-permission android:name="android.permission.CALL_PHONE"/>
       
</manifest>
-----------------------------------------------------
e./gesture/res/layout/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:id="@+id/gestures"
     android:layout_width="fill_parent"
     android:layout_height="0dp"
     android:layout_weight="1"
     android:gestureStrokeType="multiple"
     />
 <!-- ①.1 android:layout_height="0dp",设置用户绘制手势界面的高度
 ①.2 android:layout_weight="1",设置定义测量的优先级别,0的优先级最高,0>1>2...
       按钮的话,android:layout_weight="1"这个默认值是0
 ①.3 系统首先测量按钮的高度,因为按钮的优先级高。
 ④.4 只要这样设置就可以实现用窗口的高度,减去按钮的高度,剩余的,就是用户绘制手势的高度
  -->
 <!-- android:gestureStrokeType="multiple"注意加上这一句就可以进行多笔画识别
 以前只可以写一笔,现在可以写好几笔画。
  -->
<!-- ①. android:layout_weight="0"这里要求让这个按钮显示在屏幕的最下方
  这里采取的方法是,用窗口的高度,减去按钮的高度,剩余的,就是用户绘制手势的高度 -->
 <Button
 android:layout_weight="0"
  android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/recognize"
    android:onClick="find"
    />
</LinearLayout>
------------------------------------------------------------------------------------
13.这个功能可以做成,用户输入密码。
   手势识别,可以用于软件的快捷方式。比如用户想打开某个应用画个o就可以。
   使用手势识别可以实现解锁功能。
----------------------------------------------------------------------------

 

你可能感兴趣的:(Android学习)