【Android】灵云手写离线识别使用说明

注册

使用灵云的手写识别功能需要先在官网上进行注册应用。官网地址

注册比较简单,就不做过多介绍了,注册完应用以后,在后台创建自己的应用,创建完应用以后需要给应用开通对应的手写功能。
【Android】灵云手写离线识别使用说明_第1张图片

capKey说明:

  • hwr.cloud.letter 云端单字识别功能
  • hwr.cloud.freewrite 云端多字识别功能
  • hwr.local.letter 本地单字识别功能
  • hwr.local.freestylus 本地多字识别功能
  • hwr.local.associateword 本地联想词功能

集成

下载灵云的Android版本手写识别功能,下载地址
如果使用在线功能,下载对应的SDK,里面有jar包和so,就可以满足需求了。如果要使用离线的手写识别功能,还需要下载灵云资源文件

资源文件列表:

这里写图片描述

如果是在android平台上使用,需要修改一下名字,修改为如下,并加入到libs/armeabi目录下
这里写图片描述

源码

Github

灵云离线手写识别功能

需要加入的so和jar包有:

  • libhci_curl.so
  • libhci_sys.so
  • libhci_sys_jni.so
  • libhci_hwr.so
  • libhci_hwr_hwr_jni.so
  • libhci_hwr_local_recog.so
  • libletter.conf.so
  • libletter.dic.so

需要使用的权限

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

加载配置类

package com.miao.util;

/**
 * 灵云配置信息
 * Created by 10048 on 2016/12/3.
 */
public class ConfigUtil {
    /**
     * 灵云APP_KEY
     */
    public static final String APP_KEY = "c85d54f1";

    /**
     * 开发者密钥
     */
    public static final String DEVELOPER_KEY = "712ddd892cf9163e6383aa169e0454e3";

    /**
     * 灵云云服务的接口地址
     */
    public static final String CLOUD_URL = "test.api.hcicloud.com:8888";

    /**
     * 需要运行的灵云能力
     */
    //云端多字识别功能
    public static final String CAP_KEY_HWR_CLOUD_FREETALK = "hwr.cloud.freetalk";
    //云端单字识别功能
    public static final String CAP_KEY_HWR_CLOUD_LETTER = "hwr.cloud.letter";
    //离线单字识别功能
    public static final String CAP_KEY_HWR_LOCAL_LETTER = "hwr.local.letter";
    //离线多字识别功能
    public static final String CAP_KEY_HWR_LOCAL_FREESTYLUS = "hwr.local.freestylus";
    //离线联想功能
    public static final String CAP_KEY_HWR_LOCAL_ASSOCIATE_WORD = "hwr.local.associateword";
    //离线笔形功能
    public static final String CAP_KEY_HWR_LOCAL_PENSCRIPT = "hwr.local.penscript";
}

封装灵云系统的初始化功能

package com.example.sinovoice.util;

import android.content.Context;
import android.os.Environment;
import android.util.Log;

import com.sinovoice.hcicloudsdk.api.HciCloudSys;
import com.sinovoice.hcicloudsdk.common.AuthExpireTime;
import com.sinovoice.hcicloudsdk.common.HciErrorCode;
import com.sinovoice.hcicloudsdk.common.InitParam;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
 * Created by miaochangchun on 2016/11/28.
 */
public class HciCloudSysHelper {
    private static final String TAG = HciCloudSysHelper.class.getSimpleName();
    private static HciCloudSysHelper mHciCloudSysHelper = null;

    private HciCloudSysHelper(){
    }

    public static HciCloudSysHelper getInstance() {
        if (mHciCloudSysHelper == null) {
            return  new HciCloudSysHelper();
        }
        return  mHciCloudSysHelper;
    }

    /**
     * 初始化函数
     * @param context
     * @return
     */
    public int init(Context context){
        //配置串参数
        String strConfig = getInitParam(context);
        int errCode = HciCloudSys.hciInit(strConfig, context);
        if (errCode != HciErrorCode.HCI_ERR_NONE){
            Log.e(TAG, "hciInit Failed and return errcode = " + errCode);
            return errCode;
        }

        errCode = checkAuthAndUpdateAuth();
        if (errCode != HciErrorCode.HCI_ERR_NONE) {
            Log.e(TAG, "checkAuthAndUpdateAuth Failed and return errcode = " + errCode);
            return errCode;
        }
        return HciErrorCode.HCI_ERR_NONE;
    }

    /**
     * 获取授权
     * @return
     */
    private int checkAuthAndUpdateAuth() {
        // 获取系统授权到期时间
        AuthExpireTime objExpireTime = new AuthExpireTime();
        int initResult = HciCloudSys.hciGetAuthExpireTime(objExpireTime);
        if (initResult == HciErrorCode.HCI_ERR_NONE) {
            // 显示授权日期,如用户不需要关注该值,此处代码可忽略
            Date date = new Date(objExpireTime.getExpireTime() * 1000);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
            Log.i(TAG, "expire time: " + sdf.format(date));

            if (objExpireTime.getExpireTime() * 1000 > System.currentTimeMillis()) {
                // 已经成功获取了授权,并且距离授权到期有充足的时间(>7天)
                Log.i(TAG, "checkAuth success");
                return initResult;
            }
        }

        // 获取过期时间失败或者已经过期
        initResult = HciCloudSys.hciCheckAuth();
        if (initResult == HciErrorCode.HCI_ERR_NONE) {
            Log.i(TAG, "checkAuth success");
            return initResult;
        } else {
            Log.e(TAG, "checkAuth failed: " + initResult);
            return initResult;
        }
    }

    /**
     * 获取配置传参数
     * @param context
     * @return
     */
    private String getInitParam(Context context) {
        InitParam initParam = new InitParam();
        //灵云云服务的接口地址,此项必填
        initParam.addParam(InitParam.AuthParam.PARAM_KEY_APP_KEY, ConfigUtil.APP_KEY);
        //灵云云服务的接口地址,此项必填
        initParam.addParam(InitParam.AuthParam.PARAM_KEY_DEVELOPER_KEY, ConfigUtil.DEVELOPER_KEY);
        //灵云云服务的接口地址,此项必填
        initParam.addParam(InitParam.AuthParam.PARAM_KEY_CLOUD_URL, ConfigUtil.CLOUD_URL);

        String authPath = context.getFilesDir().getAbsolutePath();
        //授权文件所在路径,此项必填
        initParam.addParam(InitParam.AuthParam.PARAM_KEY_AUTH_PATH, authPath);

        //日志数目,默认保留多少个日志文件,超过则覆盖最旧的日志
        initParam.addParam(InitParam.LogParam.PARAM_KEY_LOG_FILE_COUNT, "5");
        String logPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator
                + "sinovoice" + File.separator
                + context.getPackageName() + File.separator
                + "log" + File.separator;
        File file = new File(logPath);
        if (!file.exists()) {
            file.mkdirs();
        }
        //日志的路径,可选,如果不传或者为空则不生成日志
        initParam.addParam(InitParam.LogParam.PARAM_KEY_LOG_FILE_PATH, logPath);
        Log.d(TAG, "logPath = " + logPath);
        //日志大小,默认一个日志文件写多大,单位为K
        initParam.addParam(InitParam.LogParam.PARAM_KEY_LOG_FILE_SIZE, "1024");
        //日志等级,0=无,1=错误,2=警告,3=信息,4=细节,5=调试,SDK将输出小于等于logLevel的日志信息
        initParam.addParam(InitParam.LogParam.PARAM_KEY_LOG_LEVEL, "5");

        return initParam.getStringConfig();
    }

    /**
     * 反初始化
     * @return
     */
    public int release(){
        return HciCloudSys.hciRelease();
    }
}

封装灵云手写识别功能

package com.miao.util;

import android.content.Context;
import android.util.Log;

import com.sinovoice.hcicloudsdk.api.hwr.HciCloudHwr;
import com.sinovoice.hcicloudsdk.common.HciErrorCode;
import com.sinovoice.hcicloudsdk.common.Session;
import com.sinovoice.hcicloudsdk.common.hwr.HwrAssociateWordsResult;
import com.sinovoice.hcicloudsdk.common.hwr.HwrConfig;
import com.sinovoice.hcicloudsdk.common.hwr.HwrInitParam;
import com.sinovoice.hcicloudsdk.common.hwr.HwrRecogResult;
import com.sinovoice.hcicloudsdk.common.hwr.HwrRecogResultItem;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * Created by miaochangchun on 2016/11/1.
 */
public class HciCloudHwrHelper {
    public static final String TAG = HciCloudHwrHelper.class.getSimpleName();
    private static HciCloudHwrHelper mHciCloudHwrHelper = null;

    private HciCloudHwrHelper(){

    }

    public static HciCloudHwrHelper getInstance(){
        if (mHciCloudHwrHelper == null) {
            return new HciCloudHwrHelper();
        }
        return  mHciCloudHwrHelper;
    }

    /**
     * 手写功能初始化
     * @param context   上下文
     * @param capkey    使用的capkey,手写单字识别为hwr.local.letter,多字识别为hwr.local.freestylus,联想功能为hwr.local.associateword
     * @return  返回0为成功,其他为失败
     */
    public int initHwr(Context context, String capkey){
        String strConfig = getHwrInitParam(context, capkey);
        Log.d(TAG, "strConfig = " + strConfig);
        int errorCode = HciCloudHwr.hciHwrInit(strConfig);
        return errorCode;
    }

    /**
     * 手写识别函数
     * @param data  笔迹坐标
     * @param capkey    使用的capkey,手写单字识别为hwr.local.letter,多字识别为hwr.local.freestylus,联想功能为hwr.local.associateword
     * @return  返回识别的结果
     */
    public String recog(short[] data, String capkey){
        Session session = new Session();
        String sessionConfig = getHwrSessionParam(capkey);
        Log.d(TAG, "sessionConfig = " + sessionConfig);
        //sessionStart开启一个session
        int errorCode = HciCloudHwr.hciHwrSessionStart(sessionConfig, session);
        if (errorCode != HciErrorCode.HCI_ERR_NONE) {
            Log.e(TAG, "hciHwrSessionStart failed and return " + errorCode);
            HciCloudHwr.hciHwrSessionStop(session);
            return null;
        }
        //识别结果类进行初始化
        HwrRecogResult recogResult = new HwrRecogResult();
        //识别的配置串参数可以设置为空,默认就使用sessionConfig配置串参数

        errorCode = HciCloudHwr.hciHwrRecog(session, data, "", recogResult);
        if (errorCode != HciErrorCode.HCI_ERR_NONE) {
            Log.e(TAG, "hciHwrRecog failed and return " + errorCode);
            return null;
        }

        //关闭Session
        errorCode = HciCloudHwr.hciHwrSessionStop(session);
        if (errorCode != HciErrorCode.HCI_ERR_NONE) {
            Log.e(TAG, "hciHwrSessionStop failed and return " + errorCode);
            return null;
        }
        //返回识别结果
        StringBuilder sb = new StringBuilder();
        List lists = recogResult.getResultItemList();
        Iterator iterator = lists.iterator();
        while (iterator.hasNext()) {
            HwrRecogResultItem item = iterator.next();
            sb.append(item.getResult()).append(" , ");
        }
        return sb.toString();
//        return recogResult.getResultItemList().get(0).getResult();
    }

    /**
     * 联想词功能,对str进行联想,返回联想结果
     * @param str   需要联想的字符串
     * @param assCapkey 联想功能对应的capkey。
     * @return
     */
    public String associateWord(String str, String assCapkey){
        Session session = new Session();
        String sessionConfig = getAssociateWordSessionParam(assCapkey);
        int errorCode = HciCloudHwr.hciHwrSessionStart(sessionConfig, session);
        if (errorCode != HciErrorCode.HCI_ERR_NONE) {
            Log.e(TAG, "HciCloudHwr.hciHwrSessionStart failed and return " + errorCode);
        }
        HwrAssociateWordsResult hwrAssociateWordsResult = new HwrAssociateWordsResult();
        errorCode = HciCloudHwr.hciHwrAssociateWords(session, str, "", hwrAssociateWordsResult);
        if (errorCode != HciErrorCode.HCI_ERR_NONE) {
            Log.e(TAG, "HciCloudHwr.hciHwrAssociateWords failed and return " + errorCode);
        }
        errorCode = HciCloudHwr.hciHwrSessionStop(session);
        if (errorCode != HciErrorCode.HCI_ERR_NONE) {
            Log.e(TAG, "HciCloudHwr.hciHwrSessionStop failed and return " + errorCode);
        }
        ArrayList lists = hwrAssociateWordsResult.getResultList();
        StringBuilder sb = new StringBuilder();
        Iterator iterator = lists.iterator();
        while (iterator.hasNext()) {
            String string = iterator.next();
            sb.append(string).append(",");
        }
        return  sb.toString();
    }

    /**
     * 设置联想词的配置参数
     * @param assCapkey 联想词功能所需的capkey,需要设置为 assCapkey=hwr.local.associateword
     * @return  联想词配置的字符串
     */
    private String getAssociateWordSessionParam(String assCapkey) {
        HwrConfig hwrConfig = new HwrConfig();
        hwrConfig.addParam(HwrConfig.SessionConfig.PARAM_KEY_CAP_KEY, assCapkey);
        return hwrConfig.getStringConfig();
    }

    /**
     * 获取手写识别的配置参数
     * @param hwrCapkey    使用的capkey,手写单字识别为hwr.local.letter,多字识别为hwr.local.freestylus
     * @return  返回配置串
     */
    private String getHwrSessionParam(String hwrCapkey) {
        HwrConfig hwrConfig = new HwrConfig();
        hwrConfig.addParam(HwrConfig.SessionConfig.PARAM_KEY_CAP_KEY, hwrCapkey);
        //设置识别结果的候选个数
        hwrConfig.addParam(HwrConfig.ResultConfig.PARAM_KEY_CAND_NUM, "10");
        //设置识别结果的范围
        hwrConfig.addParam(HwrConfig.ResultConfig.PARAM_KEY_RECOG_RANGE, "gbk");
        return hwrConfig.getStringConfig();
    }

    /**
     * 获取手写的初始化配置参数
     * @param context   上下文
     * @param initCapkeys    使用的capkey,手写单字识别为hwr.local.letter,
     *                       多字识别为hwr.local.freestylus,
     *                       联想功能为hwr.local.associateword
     *                       可以设置多个,中间以分号隔开
     * @return  返回配置串
     */
    private String getHwrInitParam(Context context, String initCapkeys) {
        HwrInitParam hwrInitParam = new HwrInitParam();
        hwrInitParam.addParam(HwrInitParam.PARAM_KEY_INIT_CAP_KEYS, initCapkeys);
        hwrInitParam.addParam(HwrInitParam.PARAM_KEY_FILE_FLAG, "android_so");
        String dataPath = context.getFilesDir().getAbsolutePath().replace("files", "lib");
        hwrInitParam.addParam(HwrInitParam.PARAM_KEY_DATA_PATH, dataPath);
        return hwrInitParam.getStringConfig();
    }

    /**
     * 手写反初始化功能
     * @return  返回0为成功,其他为失败
     */
    public int releaseHwr(){
        return HciCloudHwr.hciHwrRelease();
    }
}

在MainActivity中使用手写识别的功能

package com.miao.hwrtest;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import android.widget.EditText;
import android.widget.Toast;

import com.miao.util.ConfigUtil;
import com.miao.util.HciCloudHwrHelper;
import com.miao.util.HciCloudSysHelper;
import com.sinovoice.hcicloudsdk.common.HciErrorCode;

public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback{

    private static final int MAX_POINT = 2048;
    private SurfaceHolder surfaceHolder;
    private SurfaceView surface;
    private Paint paint;
    private Path path;
    private int top;
    private int bottom;
    private boolean isRunning = true;
    private Canvas canvas;
    private String TAG = MainActivity.class.getSimpleName();
    private boolean start = true;
    private long init;
    private long now;
    private int mCurX, mCurY;
    private int mCurIndex;
    private short[] mPoints = null;
    private boolean mEnd;
    private HciCloudSysHelper mHciCloudSysHelper;
    private HciCloudHwrHelper mHciCloudHwrHelper;
    private EditText myEditText;

    private Handler myHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.arg1) {
                case 0:
                    Bundle bundle = msg.getData();
                    String result = bundle.getString("result");
                    myEditText.setText(result);
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        initView();
        initSinovoice();
    }

    private void initView() {
        surface = (SurfaceView) findViewById(R.id.surface);
        myEditText = (EditText) findViewById(R.id.text);

        surfaceHolder = surface.getHolder();        // 获得SurfaceHolder对象
        surface.setZOrderOnTop(true);               //使surface可见
        surfaceHolder.setFormat(PixelFormat.TRANSPARENT);   //设置背景透明
        surfaceHolder.addCallback(this);          // 为SurfaceView添加状态监听

        paint = new Paint();          // 创建一个画笔对象
        path = new Path();

        mPoints = new short[MAX_POINT * 2];
        mCurIndex = 0;
    }

    /**
     * 灵云系统初始化
     */
    private void initSinovoice() {
        mHciCloudSysHelper = HciCloudSysHelper.getInstance();
        mHciCloudHwrHelper = HciCloudHwrHelper.getInstance();
        int errorCode = mHciCloudSysHelper.init(this);
        if (errorCode != HciErrorCode.HCI_ERR_NONE) {
            Toast.makeText(this, "系统初始化失败,错误码=" + errorCode, Toast.LENGTH_SHORT).show();
            return;
        }
        errorCode = mHciCloudHwrHelper.initHwr(this, ConfigUtil.CAP_KEY_HWR_LOCAL_LETTER);
        if (errorCode != HciErrorCode.HCI_ERR_NONE) {
            Toast.makeText(this, "手写初始化失败,错误码=" + errorCode, Toast.LENGTH_SHORT).show();
            return ;
        }
    }

    /**
     *  把坐标添加到short数组
     * @param x
     * @param y
     * @return
     */
    private boolean addStroke(short x, short y) {
        if (mCurX >= 0 && mCurY >= 0) {
            if ((mCurIndex / 2) < (MAX_POINT - 2)) {
                mPoints[mCurIndex] = x;
                mCurIndex++;
                mPoints[mCurIndex] = y;
                mCurIndex++;
                return true;
            } else if ((mCurIndex / 2) == (MAX_POINT - 2)) {
                mPoints[mCurIndex] = -1;
                mCurIndex++;
                mPoints[mCurIndex] = 0;
                mCurIndex++;
                return true;
            }
        }
        return false;
    }

    /**
     * 最后一笔添加坐标(-1,-1)
     */
    public void addLastStrokePoint() {
        if(mCurIndex < 2 ||(mPoints[mCurIndex-1] == -1 && mPoints[mCurIndex-2] == -1))
        {
            return;
        }
        mPoints[mCurIndex] = -1;
        mCurIndex++;
        mPoints[mCurIndex] = -1;
        mCurIndex++;
    }

    /**
     * 每次抬笔添加坐标(-1,0)
     */
    private void addStrokeEnd() {
        mPoints[mCurIndex] = -1;
        mCurIndex++;
        mPoints[mCurIndex] = 0;
        mCurIndex++;
    }

    /**
     * 重置笔迹点数据
     */
    private void resetStroke() {
        mPoints = new short[MAX_POINT * 2];
        mCurIndex = 0;
    }

    /**
     * 获取笔迹点数组
     * @return 笔迹点数组
     */
    public short[] getStroke() {
        mEnd = true;
        addStrokeEnd();
        addLastStrokePoint();
        short[] stroke = new short[mCurIndex];
        System.arraycopy(mPoints, 0, stroke, 0, mCurIndex);

        return stroke;
    }

    /**
     * 当SurfaceView创建的时候,调用此函数
     * @param holder
     */
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        int[] location = new int[2];
        surface.getLocationOnScreen(location);
        top = location[1];
        Log.d(TAG, "top = " + top);
        bottom = top + surface.getHeight();
        Log.d(TAG, "bottom = " + bottom);
        //开启一个绘画线程
        new Thread(wlineThread).start();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getY() >= top && event.getY() <= bottom) {
            start = true;
            init = now;
            now = System.currentTimeMillis();
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    if (now - init >= 100 && now - init <= 1000) {      //抬笔操作,加上(-1,0)
//                        Log.d(TAG, "X坐标=" + "-1" + "\tY坐标=" + "0");
                        addStrokeEnd();
                    }
                    path.moveTo(event.getX(), event.getY() - top);
//                    Log.d(TAG, "X坐标=" + event.getX() + "\tY坐标=" + event.getY());
//                    addStroke((short) event.getX(), (short) event.getY());

                    break;
                case MotionEvent.ACTION_MOVE:
                    path.lineTo(event.getX(), event.getY() - top);
//                    Log.d(TAG, "X坐标=" + event.getX() + "\tY坐标=" + event.getY());
                    addStroke((short) event.getX(), (short) event.getY());

                    break;
                default:
                    break;
            }
        }
        return true;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            isRunning = false;
        }
        return super.onKeyDown(keyCode, event);
    }

    /**
     * 当SurfaceView的视图发生改变的时候,调用此函数
     * @param holder
     * @param format
     * @param width
     * @param height
     */
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    /**
     * 当SurfaceView销毁的时候,调用此函数
     * @param holder
     */
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        Log.d(TAG, "surface Destroyed");
        isRunning = false;
    }

    Runnable wlineThread =new Runnable(){

        @Override
        public void run() {
            while (isRunning) {
                drawView();
                if (start) {
                    long temp = System.currentTimeMillis() - now;
//                    Log.d(TAG, "temp=" + temp);
                    if (temp > 1000 && temp < 100000) {      //抬笔时间超过1秒,加上坐标(-1,-1),过滤第一次时间的计算
//                        Log.d(TAG, "X坐标=" + "-1" + "\tY坐标=" + "-1");

                        short[] data = getStroke();

                        String result = mHciCloudHwrHelper.recog(data, ConfigUtil.CAP_KEY_HWR_LOCAL_LETTER);
                        Message message = new Message();
                        message.arg1 = 0;
                        Bundle bundle = new Bundle();
                        bundle.putString("result", result);
                        message.setData(bundle);
                        myHandler.sendMessage(message);

                        start = false;

                        clearCanvas();
                    }
                }
            }
        }
    };

    /**
     * 清空Canvas上的笔迹
     */
    private void clearCanvas() {
        for (int i = 0; i < 4; i++) {
            try {
                if (surfaceHolder != null) {
                    canvas = surfaceHolder.lockCanvas();
                    canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
                    path.reset();
                    resetStroke();
                    mEnd = false;
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (canvas != null){
                    surfaceHolder.unlockCanvasAndPost(canvas);
                }
            }
        }
    }

    /**
     * 再Canvas上画
     */
    private void drawView() {
        try {
            if (surfaceHolder != null) {
                canvas = surfaceHolder.lockCanvas();
                canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
                paint.setColor(Color.RED);
                paint.setStyle(Paint.Style.STROKE);
                paint.setStrokeWidth(5);

                canvas.drawPath(path, paint);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (canvas != null) {
                surfaceHolder.unlockCanvasAndPost(canvas);
            }
        }
    }

    @Override
    protected void onDestroy() {
        releaseSinovoice();
        super.onDestroy();
    }

    /**
     * 灵云系统反初始化
     */
    private void releaseSinovoice() {
        if (mHciCloudHwrHelper != null) {
            mHciCloudHwrHelper.releaseHwr();
        }
        if (mHciCloudSysHelper != null) {
            mHciCloudSysHelper.release();
        }
    }
}

注:灵云的离线手写识别能力,第一次使用的时候也是需要有一个联网授权的过程,授权成功以后,即可在授权期内使用离线手写能力。

你可能感兴趣的:(灵云技术使用)