zoukankan      html  css  js  c++  java
  • 汉王云名片识别(SM)组件开发详解

    大家好,最近在DeviceOne平台上做了一个汉王云名片识别的功能组件。下面把我开发过程给大家做一个分享,希望可以帮助到大家。

    下面我把我的思路给大家讲解一下。
     
    1.找到我要集成的sdk,也就是汉王云名片的sdk下载(android和ios)和文档下载。
    2.阅读sdk的官方demo
    3.在deviceone上面创建组件
    4.编写组件的属性、事件、方法。
    5.下载组件的项目
    6.编码
    7.上传zip包
    8.编写示例进行调试
    9.完成。
     
    下面我就按照上面的顺序来依次讲解。
    1.找到我要集成的sdk,也就是汉王云名片的sdk下载(android和ios)和文档下载。
    打开http://developer.hanvon.com/,开发者中心,注册了一个账号,然后选择我要开发的sdk页面进行示例demo下载http://developer.hanvon.com/api/toAPIinfo.do?id=2。
    2.阅读sdk的官方demo并申请相关的android的key和ios的key
    下面我分两个平台给大家讲解下代码:
    Android:
    我们看下上面的图片,这个是官方给的例子,一共就一个类 ,这样我们直接看代码。

    public class MainActivity extends Activity {

     

    private Button button1;

    private Button button2;

    private ImageView iv_image;  

    private TextView testView;

    private ProgressDialog pd;

    private DiscernHandler discernHandler;

     

    String picPath = null;

    String result = null;

    private HWCloudManager hwCloudManagerBcard; 

     

    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    requestWindowFeature(Window.FEATURE_NO_TITLE); //remove title bar

    setContentView(R.layout.activity_main);

     

     

    /**

    * your_android_key  是您在开发者中心申请的android_key 并 申请了云身份证识别服务

    * 开发者中心:http://developer.hanvon.com/

    */

    hwCloudManagerBcard = new HWCloudManager(this"your_android_key");

     

     

     

    discernHandler = new DiscernHandler();

     

    button1 = (Button) findViewById(R.id.button1);

    button2 = (Button) findViewById(R.id.button2);

    iv_image = (ImageView) findViewById(R.id.iv_image);

    testView = (TextView) findViewById(R.id.result);

     

    button1.setOnClickListener(listener);

    button2.setOnClickListener(listener);

    }

     

    OnClickListener listener = new OnClickListener() {

            @Override

            public void onClick(View view) {

                switch (view.getId()) {

                case R.id.button1:

                // 激活系统图库,选择一张图片

                Intent intent = new Intent();

                intent.setAction(Intent.ACTION_PICK);

                intent.setType("image/*");

                startActivityForResult(intent, 0);

                break;

                

                case R.id.button2:

                //识别

                testView.setText("");

                ConnectionDetector connectionDetector = new ConnectionDetector(getApplication());

            if (connectionDetector.isConnectingTOInternet()) {

            if (null != picPath) {

            pd = ProgressDialog.show(MainActivity.this"", "正在识别请稍后......");

                        DiscernThread discernThread = new DiscernThread();

                        new Thread(discernThread).start();

            else {

        Toast.makeText(getApplication(), "请选择图片后再试", Toast.LENGTH_LONG).show();

        }

            else {

            Toast.makeText(getApplication(), "网络连接失败,请检查网络后重试!", Toast.LENGTH_LONG).show();

            }

                

                

                break;

                }

            }

    };

     

    public class DiscernThread implements Runnable{

     

    @Override

    public void run() {

    try {

    /**

    * 调用汉王云名片识别方法

    */

    result = hwCloudManagerBcard.cardLanguage("chns", picPath);

    // result = hwCloudManagerBcard.cardLanguage4Https("chns", picPath); 

    catch (Exception e) {

    // TODO: handle exception

    }

    Bundle mBundle = new Bundle();

    mBundle.putString("responce", result);

    Message msg = new Message();

    msg.setData(mBundle);

    discernHandler.sendMessage(msg);

    }

    }

     

    public class DiscernHandler extends Handler {

    @Override

    public void handleMessage(Message msg) {

    super.handleMessage(msg);

    pd.dismiss();

    Bundle bundle = msg.getData();

    String responce = bundle.getString("responce");

    testView.setText(responce);

    }

    }

     

    @Override  

        protected void onActivityResult(int requestCode, int resultCode, Intent data) {  

            if (data != null) {  

                Uri uri = data.getData();

                String[] proj = { MediaStore.Images.Media.DATA };

            Cursor cursor = getContentResolver().query(uri, proj, nullnullnull);

            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);

            cursor.moveToFirst();

            picPath = cursor.getString(column_index);

            System.out.println(picPath);

            

            final BitmapFactory.Options options = new BitmapFactory.Options();

        options.inJustDecodeBounds = true;

        BitmapFactory.decodeFile(picPath, options);

        options.inSampleSize = BitmapUtil.calculateInSampleSize(options, 1280, 720);

        options.inJustDecodeBounds = false;

        Bitmap bitmap = BitmapFactory.decodeFile(picPath, options);

            iv_image.setImageBitmap(bitmap);

            }  

            super.onActivityResult(requestCode, resultCode, data);  

        }

     

    }

    上面就是官方给的代码,我们可以看到,整个过程就是:首先后去一个图片,也就是名片的照片,然后就是通过云端去处理这个图片,然后返回一个json值,就是我们要的结果了。那么我们直接看部分代码解析。

    // 激活系统图库,选择一张图片

                Intent intent = new Intent();

                intent.setAction(Intent.ACTION_PICK);

                intent.setType("image/*");

                startActivityForResult(intent, 0);

    选择一个图片,并获取返回的地址。

    //识别

                testView.setText("");

                ConnectionDetector connectionDetector = new ConnectionDetector(getApplication());

            if (connectionDetector.isConnectingTOInternet()) {

            if (null != picPath) {

            pd = ProgressDialog.show(MainActivity.this"", "正在识别请稍后......");

                        DiscernThread discernThread = new DiscernThread();

                        new Thread(discernThread).start();

            else {

        Toast.makeText(getApplication(), "请选择图片后再试", Toast.LENGTH_LONG).show();

        }

            else {

            Toast.makeText(getApplication(), "网络连接失败,请检查网络后重试!", Toast.LENGTH_LONG).show();

            }

    进行识别。

    从上面两个代码我们可以看出,整个sdk的核心部分就是这两块,这样,我们就了解了整个sdk的核心东西了。

     

    IOS:

    下面我们看下ios的项目目录

    上面就是目录结构,非常简单。废话不多说,我们直接看代码。

    #import "ViewController.h"

    #import "HWCloudsdk.h"

    @interface ViewController ()

     

    @end

     

    @implementation ViewController

     

    - (void)viewDidLoad {

        [super viewDidLoad];

        HWCloudsdk *sdk = [[HWCloudsdk alloc]init];

        UIImage *cardImg = [UIImage imageNamed:@"cardimage.jpg"];

        

        //apiKey 需要您到developer.hanvon.com 自行申请

        NSString *apiKey = @"your - ios - key";

        

        [sdk cardLanguage:@"auto" cardImage:cardImg apiKey:apiKey successBlock:^(id responseObject) {

            NSLog(@"%@",responseObject);

        } failureBlock:^(NSError *error) {

            NSLog(@"%@",error);

        }];

        //    NSString *str = [sdk cardLanguage:@"chns" cardImage:cardImg apiKey:apiKey];

        //    NSLog(@"返回的结果是 : %@",str);

        // Do any additional setup after loading the view, typically from a nib.

     

    }

     

    - (void)didReceiveMemoryWarning {

        [super didReceiveMemoryWarning];

        // Dispose of any resources that can be recreated.

     

    }

    以上就是代码,非常的简单,就几句话。我们来分析一下。

    HWCloudsdk *sdk = [[HWCloudsdk alloc]init];

        UIImage *cardImg = [UIImage imageNamed:@"cardimage.jpg"];

        

        //apiKey 需要您到developer.hanvon.com 自行申请

        NSString *apiKey = @"your - ios - key";

        

        [sdk cardLanguage:@"auto" cardImage:cardImg apiKey:apiKey successBlock:^(id responseObject) {

            NSLog(@"%@",responseObject);

        } failureBlock:^(NSError *error) {

            NSLog(@"%@",error);

        }];

    上面这段代码就是整个核心,我们看一下,就是获取一个图片,然后通过图片去云端解析,更加简洁。

     

    这样我们就解读好了sdk的demo,也知道如何来使用了。

     

    3.在deviceone上面创建组件

    我觉得这个可以省略的,那我直接用文字来描述一下吧。

    创建账号-开发者中心-组件开发-创建组件-填写信息-保存。

    搞定。

     

    4.编写组件的属性、事件、方法。

    通过我们上面的阅读sdk的demo,我们可以非常清晰的知道了我们需要如何来调用,那么我就定义一个方法就可以了

    在这里面我定义的方法为getInfo方法,我给这个方法的一个参数为imgUrl,也就是需要一个图片的路径。

    下面我直接上图,给大家看看我的配置。

    这个就是我配置好的,供大家参考。

     

    5.下载组件的项目

    通过步骤4的编写,我们现在就可以去下载组件开发项目了。

     

    6.编码

    这个章节大家可能是最关心的一节,那我细一点讲解。我分两个平台讲解:

    Android:

    我们先看下载好的项目并且导入到我的ADT中(这个地方大家可以使用自己的eclipse开发),看下项目图

     

    上面就是我导入之后的项目目录,下面进行一下目录的讲解:

    doext文件下下面的所有文件都是官方生成好的,也是我们这次开发组件编写代码的文件夹。

    dotest.module这个文件夹是用于我们进行原生测试组件的属性、事件、方法的。这个后续会使用到,请继续往下看。

    我们接下来打开doext/implement/组件名_Model.java文件。(因为我们是一个sm组件,所以有这样一个文件。)

    我们下面来看看这个文件的代码:

    public class M1294_hwymp_Model extends DoSingletonModule implements M1294_hwymp_IMethod{

     

    public M1294_hwymp_Model() throws Exception {

    super();

    }

     

    /**

    同步方法,JS脚本调用该组件对象方法时会被调用,可以根据_methodName调用相应的接口实现方法;

    * @_methodName 方法名称

    * @_dictParas 参数(K,V),获取参数值使用API提供DoJsonHelper类;

    * @_scriptEngine 当前Page JS上下文环境对象

    * @_invokeResult 用于返回方法结果对象

    */

    @Override

    public boolean invokeSyncMethod(String _methodName, JSONObject _dictParas,

    DoIScriptEngine _scriptEngine, DoInvokeResult _invokeResult)

    throws Exception {

    //...do something

    return super.invokeSyncMethod(_methodName, _dictParas, _scriptEngine, _invokeResult);

    }

     

    /**

    异步方法(通常都处理些耗时操作,避免UI线程阻塞),JS脚本调用该组件对象方法时会被调用,

    可以根据_methodName调用相应的接口实现方法;

    * @_methodName 方法名称

    * @_dictParas 参数(K,V),获取参数值使用API提供DoJsonHelper类;

    * @_scriptEngine 当前page JS上下文环境

    * @_callbackFuncName 回调函数名

    * #如何执行异步方法回调?可以通过如下方法:

    * _scriptEngine.callback(_callbackFuncName, _invokeResult);

    参数解释:@_callbackFuncName回调函数名,@_invokeResult传递回调函数参数对象;

    获取DoInvokeResult对象方式new DoInvokeResult(this.getUniqueKey());

    */

    @Override

    public boolean invokeAsyncMethod(String _methodName, JSONObject _dictParas,

    DoIScriptEngine _scriptEngine, String _callbackFuncName)throws Exception {

    //...do something

    return super.invokeAsyncMethod(_methodName, _dictParas, _scriptEngine, _callbackFuncName);

    }

     

     

    /**

    获取名片信息;

    * @_dictParas 参数(K,V),可以通过此对象提供相关方法来获取参数值(Key:为参数名称);

    * @_scriptEngine 当前Page JS上下文环境对象

    * @_callbackFuncName 回调函数名

    */

    @Override

    public void getInfo(JSONObject _dictParas, DoIScriptEngine _scriptEngine,String _callbackFuncName) {

     

    }

     

    }

    整个这个代码是我们定义好组件之后,官方生成好的,经过阅读,我们看到这个代码的中文解析已经很清晰了,那我在这里在解析一下,

    里面有两个方法,一个是同步方法,一个是异步方法,这个是根据我们定义的组件的方法性质来说的,但是一般建议使用异步方法,这样不会出现

    屏幕卡顿的现象,我用的是异步方法。所以下面的编程,我就在异步方法里面编写就可以了。

    还有一个就是getInfo这个方法,看到这个方法很熟悉吧,因为是我们在组件里面定义过的,就是这个方法,看来我们要定义自己的逻辑就要在这个方法

    里面写了,这样我们就清晰的知道了我们要写组件代码的去处了。

    下一步就是我们开始写了。

    /**

    异步方法(通常都处理些耗时操作,避免UI线程阻塞),JS脚本调用该组件对象方法时会被调用,

    可以根据_methodName调用相应的接口实现方法;

    * @_methodName 方法名称

    * @_dictParas 参数(K,V),获取参数值使用API提供DoJsonHelper类;

    * @_scriptEngine 当前page JS上下文环境

    * @_callbackFuncName 回调函数名

    * #如何执行异步方法回调?可以通过如下方法:

    * _scriptEngine.callback(_callbackFuncName, _invokeResult);

    参数解释:@_callbackFuncName回调函数名,@_invokeResult传递回调函数参数对象;

    获取DoInvokeResult对象方式new DoInvokeResult(this.getUniqueKey());

    */

    @Override

    public boolean invokeAsyncMethod(String _methodName, JSONObject _dictParas,

    DoIScriptEngine _scriptEngine, String _callbackFuncName)throws Exception {

    if("getInfo".equals(_methodName))

    {

    getInfo(_dictParas, _scriptEngine, _callbackFuncName);

     

    }

    return super.invokeAsyncMethod(_methodName, _dictParas, _scriptEngine, _callbackFuncName);

     

    }

    看上面的代码,我把我写的这段话标注为红色了,大家可以看的清楚一下,我写这段话的目的就是要判断一下我传入的方法进行相应的调用,

    也就是说我们通常写组件的时候,这个地方可能会有好几个方法,所以这个地方会有好几个判断的。这样讲大家就清楚了。

    下面,我们就把之前的demo的代码直接拷贝到当前的项目中,然后倒入jar包(这个不讲了,如果不会可以百度倒入jar包)。直接代码

    public class M1294_hwymp_Model extends DoSingletonModule implements M1294_hwymp_IMethod{

        

        

        private Button button1;

        private Button button2;

        private ImageView iv_image;

        private TextView testView;

        private ProgressDialog pd;

        private DiscernHandler discernHandler;

        

        String picPath = null;

        String result = null;

        private HWCloudManager hwCloudManagerBcard;

     

    public M1294_hwymp_Model() throws Exception {

    super();

    }

     

    /**

    同步方法,JS脚本调用该组件对象方法时会被调用,可以根据_methodName调用相应的接口实现方法;

    * @_methodName 方法名称

    * @_dictParas 参数(K,V),获取参数值使用API提供DoJsonHelper类;

    * @_scriptEngine 当前Page JS上下文环境对象

    * @_invokeResult 用于返回方法结果对象

    */

    @Override

    public boolean invokeSyncMethod(String _methodName, JSONObject _dictParas,

    DoIScriptEngine _scriptEngine, DoInvokeResult _invokeResult)

    throws Exception {

    //...do something

    return super.invokeSyncMethod(_methodName, _dictParas, _scriptEngine, _invokeResult);

    }

     

    /**

    异步方法(通常都处理些耗时操作,避免UI线程阻塞),JS脚本调用该组件对象方法时会被调用,

    可以根据_methodName调用相应的接口实现方法;

    * @_methodName 方法名称

    * @_dictParas 参数(K,V),获取参数值使用API提供DoJsonHelper类;

    * @_scriptEngine 当前page JS上下文环境

    * @_callbackFuncName 回调函数名

    * #如何执行异步方法回调?可以通过如下方法:

    * _scriptEngine.callback(_callbackFuncName, _invokeResult);

    参数解释:@_callbackFuncName回调函数名,@_invokeResult传递回调函数参数对象;

    获取DoInvokeResult对象方式new DoInvokeResult(this.getUniqueKey());

    */

    @Override

    public boolean invokeAsyncMethod(String _methodName, JSONObject _dictParas,

    DoIScriptEngine _scriptEngine, String _callbackFuncName)throws Exception {

    //...do something

    return super.invokeAsyncMethod(_methodName, _dictParas, _scriptEngine, _callbackFuncName);

    }

     

     

    /**

    获取名片信息;

    * @_dictParas 参数(K,V),可以通过此对象提供相关方法来获取参数值(Key:为参数名称);

    * @_scriptEngine 当前Page JS上下文环境对象

    * @_callbackFuncName 回调函数名

    */

    @Override

    public void getInfo(JSONObject _dictParas, DoIScriptEngine _scriptEngine,String _callbackFuncName) {

            hwCloudManagerBcard = new HWCloudManager(this"your_android_key");

            

            

            

            discernHandler = new DiscernHandler();

            

            button1 = (Button) findViewById(R.id.button1);

            button2 = (Button) findViewById(R.id.button2);

            iv_image = (ImageView) findViewById(R.id.iv_image);

            testView = (TextView) findViewById(R.id.result);

            

            button1.setOnClickListener(listener);

            button2.setOnClickListener(listener);

    }

        

        OnClickListener listener = new OnClickListener() {

        @Override

        public void onClick(View view) {

        switch (view.getId()) {

    case R.id.button1:

        // 激活系统图库,选择一张图片

        Intent intent = new Intent();

        intent.setAction(Intent.ACTION_PICK);

        intent.setType("image/*");

        startActivityForResult(intent, 0);

        break;

        

    case R.id.button2:

        //识别

        testView.setText("");

        ConnectionDetector connectionDetector = new ConnectionDetector(getApplication());

        if (connectionDetector.isConnectingTOInternet()) {

            if (null != picPath) {

            pd = ProgressDialog.show(MainActivity.this"""正在识别请稍后......");

                DiscernThread discernThread = new DiscernThread();

                new Thread(discernThread).start();

            } else {

                Toast.makeText(getApplication(), "请选择图片后再试", Toast.LENGTH_LONG).show();

        }

        } else {

            Toast.makeText(getApplication(), "网络连接失败,请检查网络后重试!", Toast.LENGTH_LONG).show();

        }

        

        

        break;

    }

    }

    };

     

    public class DiscernThread implements Runnable{

        

        @Override

        public void run() {

            try {

                /**

                 * 调用汉王云名片识别方法

                 */

                result = hwCloudManagerBcard.cardLanguage("chns", picPath);

                // result = hwCloudManagerBcard.cardLanguage4Https("chns", picPath);

            } catch (Exception e) {

                // TODO: handle exception

            }

            Bundle mBundle = new Bundle();

            mBundle.putString("responce", result);

            Message msg = new Message();

            msg.setData(mBundle);

            discernHandler.sendMessage(msg);

        }

    }

     

    public class DiscernHandler extends Handler {

        @Override

        public void handleMessage(Message msg) {

            super.handleMessage(msg);

            pd.dismiss();

            Bundle bundle = msg.getData();

            String responce = bundle.getString("responce");

            testView.setText(responce);

        }

    }

     

    @Override

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (data != null) {

    Uri uri = data.getData();

    //閫氳繃uri鑾峰彇鍥剧墖璺

    String[] proj = { MediaStore.Images.Media.DATA };

    Cursor cursor = getContentResolver().query(uri, proj, nullnullnull);

    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);

    cursor.moveToFirst();

    picPath = cursor.getString(column_index);

    System.out.println(picPath);

     

    final BitmapFactory.Options options = new BitmapFactory.Options();

    options.inJustDecodeBounds = true;

    BitmapFactory.decodeFile(picPath, options);

    options.inSampleSize = BitmapUtil.calculateInSampleSize(options, 1280720);

    options.inJustDecodeBounds = false;

    Bitmap bitmap = BitmapFactory.decodeFile(picPath, options);

    iv_image.setImageBitmap(bitmap);

    }

    super.onActivityResult(requestCode, resultCode, data);

    }

     

    }

    上面的代码,标记为紫色的是我第一次要去掉的代码,原因:因为我是直接传入的照片的地址,所以跟照片有关系的我都不需要了。

    public class M1294_hwymp_Model extends DoSingletonModule implements M1294_hwymp_IMethod{

        

        

        private DiscernHandler discernHandler;

        

        String picPath = null;

        String result = null;

        private HWCloudManager hwCloudManagerBcard;

     

    public M1294_hwymp_Model() throws Exception {

    super();

    }

     

    /**

    同步方法,JS脚本调用该组件对象方法时会被调用,可以根据_methodName调用相应的接口实现方法;

    * @_methodName 方法名称

    * @_dictParas 参数(K,V),获取参数值使用API提供DoJsonHelper类;

    * @_scriptEngine 当前Page JS上下文环境对象

    * @_invokeResult 用于返回方法结果对象

    */

    @Override

    public boolean invokeSyncMethod(String _methodName, JSONObject _dictParas,

    DoIScriptEngine _scriptEngine, DoInvokeResult _invokeResult)

    throws Exception {

    //...do something

    return super.invokeSyncMethod(_methodName, _dictParas, _scriptEngine, _invokeResult);

    }

     

    /**

    异步方法(通常都处理些耗时操作,避免UI线程阻塞),JS脚本调用该组件对象方法时会被调用,

    可以根据_methodName调用相应的接口实现方法;

    * @_methodName 方法名称

    * @_dictParas 参数(K,V),获取参数值使用API提供DoJsonHelper类;

    * @_scriptEngine 当前page JS上下文环境

    * @_callbackFuncName 回调函数名

    * #如何执行异步方法回调?可以通过如下方法:

    * _scriptEngine.callback(_callbackFuncName, _invokeResult);

    参数解释:@_callbackFuncName回调函数名,@_invokeResult传递回调函数参数对象;

    获取DoInvokeResult对象方式new DoInvokeResult(this.getUniqueKey());

    */

    @Override

    public boolean invokeAsyncMethod(String _methodName, JSONObject _dictParas,

    DoIScriptEngine _scriptEngine, String _callbackFuncName)throws Exception {

            if("getInfo".equals(_methodName))

            {

                getInfo(_dictParas, _scriptEngine, _callbackFuncName);

            }

    return super.invokeAsyncMethod(_methodName, _dictParas, _scriptEngine, _callbackFuncName);

    }

     

     

    /**

    获取名片信息;

    * @_dictParas 参数(K,V),可以通过此对象提供相关方法来获取参数值(Key:为参数名称);

    * @_scriptEngine 当前Page JS上下文环境对象

    * @_callbackFuncName 回调函数名

    */

    @Override

    public void getInfo(JSONObject _dictParas, DoIScriptEngine _scriptEngine,String _callbackFuncName) {

            hwCloudManagerBcard = new HWCloudManager(this"your_android_key");

            discernHandler = new DiscernHandler();

            ConnectionDetector connectionDetector = new ConnectionDetector(getApplication());

            if (connectionDetector.isConnectingTOInternet()) {

                if (null != picPath) {

                    DiscernThread discernThread = new DiscernThread();

                    new Thread(discernThread).start();

                } else {

                    Toast.makeText(getApplication(), "请选择图片后再试", Toast.LENGTH_LONG).show();

                }

            } else {

                Toast.makeText(getApplication(), "网络连接失败,请检查网络后重试!", Toast.LENGTH_LONG).show();

            }

    }

    }

    };

     

    public class DiscernThread implements Runnable{

        

        @Override

        public void run() {

            try {

                /**

                 * 调用汉王云名片识别方法

                 */

                result = hwCloudManagerBcard.cardLanguage("chns", picPath);

                // result = hwCloudManagerBcard.cardLanguage4Https("chns", picPath);

            } catch (Exception e) {

                // TODO: handle exception

            }

            Bundle mBundle = new Bundle();

            mBundle.putString("responce", result);

            Message msg = new Message();

            msg.setData(mBundle);

            discernHandler.sendMessage(msg);

        }

    }

     

    public class DiscernHandler extends Handler {

        @Override

        public void handleMessage(Message msg) {

            super.handleMessage(msg);

            pd.dismiss();

            Bundle bundle = msg.getData();

            String responce = bundle.getString("responce");

            testView.setText(responce);

        }

    }

     

     

    }

    上面这段代码基本是我去掉后的代码,看起来好像是没什么问题,那我们在看看,在精简一下。

    public class M1294_hwymp_Model extends DoSingletonModule implements M1294_hwymp_IMethod{

     

    String picPath = null;

    String result = null;

    private HWCloudManager hwCloudManagerBcard;

     

    public M1294_hwymp_Model() throws Exception {

    super();

    }

     

    /**

    * 同步方法,JS脚本调用该组件对象方法时会被调用,可以根据_methodName调用相应的接口实现方法;

    @_methodName 方法名称

    @_dictParas 参数(K,V),获取参数值使用API提供DoJsonHelper类;

    @_scriptEngine 当前Page JS上下文环境对象

    @_invokeResult 用于返回方法结果对象

    */

    @Override

    public boolean invokeSyncMethod(String _methodName, JSONObject _dictParas,

    DoIScriptEngine _scriptEngine, DoInvokeResult _invokeResult)

    throws Exception {

    //...do something

    return super.invokeSyncMethod(_methodName, _dictParas, _scriptEngine, _invokeResult);

    }

     

    /**

    * 异步方法(通常都处理些耗时操作,避免UI线程阻塞),JS脚本调用该组件对象方法时会被调用,

    * 可以根据_methodName调用相应的接口实现方法;

    @_methodName 方法名称

    @_dictParas 参数(K,V),获取参数值使用API提供DoJsonHelper类;

    @_scriptEngine 当前page JS上下文环境

    @_callbackFuncName 回调函数名

    * #如何执行异步方法回调?可以通过如下方法:

    * _scriptEngine.callback(_callbackFuncName, _invokeResult);

    * 参数解释:@_callbackFuncName回调函数名,@_invokeResult传递回调函数参数对象;

    * 获取DoInvokeResult对象方式new DoInvokeResult(this.getUniqueKey());

    */

    @Override

    public boolean invokeAsyncMethod(String _methodName, JSONObject _dictParas,

    DoIScriptEngine _scriptEngine, String _callbackFuncName)throws Exception {

    if("getInfo".equals(_methodName))

    {

    getInfo(_dictParas, _scriptEngine, _callbackFuncName);

    }

    return super.invokeAsyncMethod(_methodName, _dictParas, _scriptEngine, _callbackFuncName);

    }

     

     

    /**

    * 获取名片信息;

    @_dictParas 参数(K,V),可以通过此对象提供相关方法来获取参数值(Key:为参数名称);

    @_scriptEngine 当前Page JS上下文环境对象

    @_callbackFuncName 回调函数名

    */

    @Override

    public void getInfo(JSONObject _dictParas, DoIScriptEngine _scriptEngine,String _callbackFuncName) {

    ApplicationInfo info = null;

    try {

    info = DoServiceContainer.getPageViewFactory().getAppContext().getPackageManager().getApplicationInfo(DoServiceContainer.getPageViewFactory().getAppContext().getPackageName(), PackageManager.GET_META_DATA);

    //添加判断

    String androidKey = info.metaData.getString("hwymp_android");

    hwCloudManagerBcard = new HWCloudManager(DoServiceContainer.getPageViewFactory().getAppContext(), androidKey);

    picPath = DoJsonHelper.getString(_dictParas, "imgUrl", "");

    if(DoIOHelper.existFile(DoIOHelper.getLocalFileFullPath(_scriptEngine.getCurrentApp(), picPath)))

    {

    picPath = DoIOHelper.getLocalFileFullPath(_scriptEngine.getCurrentApp(), picPath);

    }

    catch (Exception e) {

    e.printStackTrace();

    }

    ConnectionDetector connectionDetector = new ConnectionDetector(DoServiceContainer.getPageViewFactory().getAppContext());

    if (connectionDetector.isConnectingTOInternet()) {

    if (null != picPath) {

    result = hwCloudManagerBcard.cardLanguage("chns", picPath);

    DoInvokeResult invokeResult = new DoInvokeResult(getUniqueKey());

    invokeResult.setResultText(result);

    _scriptEngine.callback(_callbackFuncName, invokeResult);

    else {

    new Exception("请传入图片后再试");

    }

    else {

    new Exception("网络连接失败,请检查网络后重试!");

    }

    }

     

    }

    上面这段代码是我精简之后的,看起来是不是简介了很多,我现在讲解一下如何精简的,

    public class DiscernThread implements Runnable{

        

        @Override

        public void run() {

            try {

                /**

                 * 调用汉王云名片识别方法

                 */

                result = hwCloudManagerBcard.cardLanguage("chns", picPath);

                // result = hwCloudManagerBcard.cardLanguage4Https("chns", picPath);

            } catch (Exception e) {

                // TODO: handle exception

            }

            Bundle mBundle = new Bundle();

            mBundle.putString("responce", result);

            Message msg = new Message();

            msg.setData(mBundle);

            discernHandler.sendMessage(msg);

        }

    }

     

    public class DiscernHandler extends Handler {

        @Override

        public void handleMessage(Message msg) {

            super.handleMessage(msg);

            pd.dismiss();

            Bundle bundle = msg.getData();

            String responce = bundle.getString("responce");

            testView.setText(responce);

        }

    }

    这两段代码完全是没有用的,因为我们是异步方法,已经在一个线程里面了,不需要再去new一个线程,还要像主线程发消息,好复杂,而且容易出错

    没有用,去掉就可以了。然后就有上面的简介代码了。

    info = DoServiceContainer.getPageViewFactory().getAppContext().getPackageManager().getApplicationInfo(DoServiceContainer.getPageViewFactory().getAppContext().getPackageName(), PackageManager.GET_META_DATA);

    //添加判断

    String androidKey = info.metaData.getString("hwymp_android");

    这段代码就是我在manifest里面定义了一个,这样方便我在发布到商店的时候,可以让其他开发者去使用自己的key

     

    <meta-data android:name="hwymp_android" android:value="your  android key"></meta-data>

    这样,我们的组件算是写好了,下面的工作就是我们要去dotest里面来测试一下我们的组件是否正确运行了,go

    我们首先找到dotest/module/activity/webviewsampletestactivity.java文件,直接看代码吧。

    public class WebViewSampleTestActivty extends DoTestActivity{

     

    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    }

     

    @Override

    protected void initModuleModel() throws Exception {

    this.model = new M1294_hwymp_Model();

    }

     

    @Override

    protected void initUIView() throws Exception {

    // Do_WebView_View view = new Do_WebView_View(this);

    //        ((DoUIModule)this.model).setCurrentUIModuleView(view);

    //        ((DoUIModule)this.model).setCurrentPage(currentPage);

    //        view.loadView((DoUIModule)this.model);

    //        LinearLayout uiview = (LinearLayout)findViewById(R.id.uiview);

    //        uiview.addView(view);

    }

     

    @Override

    public void doTestProperties(View view) {

    DoService.setPropertyValue(this.model, "url", "https://www.baidu.com");

    }

     

    @Override

    protected void doTestSyncMethod() {

    Map<String, String> _paras_back = new HashMap<String, String>();

            DoService.syncMethod(this.model, "back", _paras_back);

    }

     

    @Override

    protected void doTestAsyncMethod() {

    Map<String, String>  _paras_loadString = new HashMap<String, String>();

            _paras_loadString.put("imgUrl", "/storage/emulated/0/tencent/MicroMsg/WeiXin/mmexport1473648247058.jpg.do");

            DoService.asyncMethod(this.model, "getInfo", _paras_loadString, new DoService.EventCallBack() {

    @Override

    public void eventCallBack(String _data) {//回调函数

    DoServiceContainer.getLogEngine().writeDebug("异步方法回调:" + _data);

    }

    });

    }

     

    @Override

    protected void onEvent() {

    DoService.subscribeEvent(this.model, "loaded", new DoService.EventCallBack() {

    @Override

    public void eventCallBack(String _data) {

    DoServiceContainer.getLogEngine().writeDebug("事件回调:" + _data);

    }

    });

    }

     

    @Override

    public void doTestFireEvent(View view) {

    DoInvokeResult invokeResult = new DoInvokeResult(this.model.getUniqueKey());

    this.model.getEventCenter().fireEvent("_messageName", invokeResult);

    }

     

     

    }

    看下上面标红的部分,因为我这个组件是sm的组件,所以跟UI相关的我需要,所以注释掉,然后找到方法的地方,将我东西初始化并调用方法。

    这样直接在android上面运行这个项目就可以了。

    至此,我的android项目编写完成。

     

    IOS:

    看下项目的目录

    点击doExtLib右键,添加新文件,导入之后的图片

    然后我们点击“组件_sm.m”文件看下代码。

    @implementation M1294_hwymp_SM

    #pragma mark - 方法

    #pragma mark - 同步异步方法的实现

    //同步

    //异步

    - (void)getInfo:(NSArray *)parms

    {

        //异步耗时操作,但是不需要启动线程,框架会自动加载一个后台线程处理这个函数

        NSDictionary *_dictParas = [parms objectAtIndex:0];

        //参数字典_dictParas

        id<doIScriptEngine> _scritEngine = [parms objectAtIndex:1];

        //自己的代码实现

        

        NSString *_callbackName = [parms objectAtIndex:2];

        //回调函数名_callbackName

        doInvokeResult *_invokeResult = [[doInvokeResult allocinit];

        //_invokeResult设置返回值

        

        [_scritEngine Callback:_callbackName :_invokeResult];

    }

     

     

    @end

    代码非常简单,我们直观的看到了我们创建好的组件,我们来看下里面的中文解释也是非常的清晰,下面我们直接贴代码。

    导入.a文件的步骤省略(百度)

    @implementation M1294_hwymp_SM

    #pragma mark - 方法

    #pragma mark - 同步异步方法的实现

    //同步

    //异步

    - (void)getInfo:(NSArray *)parms

    {

        //异步耗时操作,但是不需要启动线程,框架会自动加载一个后台线程处理这个函数

        NSDictionary *_dictParas = [parms objectAtIndex:0];

        //参数字典_dictParas

        id<doIScriptEngine> _scritEngine = [parms objectAtIndex:1];

        //自己的代码实现

        

        NSString *_callbackName = [parms objectAtIndex:2];

        //回调函数名_callbackName

        doInvokeResult *_invokeResult = [[doInvokeResult allocinit];

        //_invokeResult设置返回值

        

        

        HWCloudsdk *sdk = [[HWCloudsdk alloc]init];

        UIImage *cardImg = [UIImage imageNamed:@"cardimage.jpg"];

        

        //apiKey 需要您到developer.hanvon.com 自行申请

        NSString *apiKey = @"your - ios - key";

        

        [sdk cardLanguage:@"auto" cardImage:cardImg apiKey:apiKey successBlock:^(id responseObject) {

            NSLog(@"%@",responseObject);

        } failureBlock:^(NSError *error) {

            NSLog(@"%@",error);

        }];

     

        

        

        [_scritEngine Callback:_callbackName :_invokeResult];

    }

     

     

    @end

    红色为示例demo下面的代码,直接贴过来,我们在看下。

    看过之后,好像离我们要的组件编码已经很接近了。修改代码如下。

    @implementation M1294_hwymp_SM

    #pragma mark - 方法

    #pragma mark - 同步异步方法的实现

    //同步

    //异步

    - (void)getInfo:(NSArray *)parms

    {

        //异步耗时操作,但是不需要启动线程,框架会自动加载一个后台线程处理这个函数

        NSDictionary *_dictParas = [parms objectAtIndex:0];

        //参数字典_dictParas

        id<doIScriptEngine> _scritEngine = [parms objectAtIndex:1];

        NSString *_callbackName = [parms objectAtIndex:2];

        //获取图片地址

        NSString *url = [doJsonHelper GetOneText:_dictParas :@"imgUrl" :@"" ];

        UIImage *cardImg = [UIImage imageWithContentsOfFile: [doIOHelper GetLocalFileFullPath:[_scritEngine CurrentApp] :url]];

        //初始化HWCloud

        HWCloudsdk *sdk = [[HWCloudsdk alloc]init];

        //apiKey 需要您到developer.hanvon.com 自行申请

        NSString *apiKey = [[doServiceContainer Instance].ModuleExtManage GetThirdAppKey:@"hwymp.plist" :@"hwymp_ios" ];

        [sdk cardLanguage:@"chns" cardImage:cardImg apiKey:apiKey successBlock:^(id responseObject) {

            doInvokeResult *_invokeResult = [[doInvokeResult allocinit];

            [_invokeResult SetResultText:responseObject];

            [_scritEngine Callback:_callbackName :_invokeResult];

        } failureBlock:^(NSError *error) {

            NSLog(@"%@",error);

        }];

     

    }

    上面蓝色部分为我修改过的代码。我在项目中自己定义了一个plist文件,用于去key值,方便以后提交到上面,开发者可以填写自己的key

    这样我编码就完成了,接下来测试。我们打开do_test文件夹下面的viewcontroller。直接看源码。

    #import "ViewController.h"

    #import "doPage.h"

    #import "doService.h"

    #import "doModuleFactory.h"

     

    #import "M1294_hwymp_SM.h"

    @interface ViewController ()

    {

    @private

        NSString *Type;

        doModule* model;

    }

    @end

    @implementation CallBackEvnet

     

    -(void)eventCallBack:(NSString *)_data

    {

        NSLog(@"异步方法回调数据:%@",_data);

    }

     

    @end

    @implementation ViewController

     

    - (void)viewDidLoad {

        [super viewDidLoad];

        [self InitInstance];

        [self ConfigUI];

        // Do any additional setup after loading the view, typically from a nib.

    }

    - (void) InitInstance

    {

        NSString *testPath = [[NSBundle mainBundlepathForResource:@"do_Test" ofType:@"json"];

        NSData *data = [NSData dataWithContentsOfFile:testPath];

        NSMutableDictionary *_testDics = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];

        Type = [_testDics valueForKey:@"Type"];

        //在下面构造model

        model = [[M1294_hwymp_SM alloc]init];

        

        [doServiceContainer Instance].SingletonModuleFactory =  [[doModuleFactory alloc]init:model];

        

        //如果是UI类型,还需要构造view

        //UIView* view = [[xxxxView alloc]init];

        

    }

    - (void)ConfigUI {

        CGFloat w = self.view.frame.size.width;

        CGFloat h = self.view.frame.size.height;

        //在对应的测试按钮添加自己的测试代码如果6个测试按钮不够,可以自己添加

        

        if([Type isEqualToString:@"UI"]){

            //SMMM不一样,UI类型还得添加自己的View,所以测试按钮都在底部

            CGFloat height = h/6;

            CGFloat width = (w - 35)/6;

            for(int i = 0;i<6;i++){

                UIButton *test = [UIButton buttonWithType:UIButtonTypeCustom];

                test.frame = CGRectMake(5*(i+1)+width*i, h-h/6, width, height);

                NSString* title = [NSString stringWithFormat:@"Test%d",i ];

                [test setTitle:title forState:UIControlStateNormal];

                SEL customSelector = NSSelectorFromString([NSString stringWithFormat:@"test%d:",i]);

                [test addTarget:self action:customSelector forControlEvents:UIControlEventTouchUpInside];

                [self.view addSubview:test];

            }

            //addsubview 自定义的UI

            

        }else{

            CGFloat height = (h-140)/6;

            CGFloat width = w - 60;

            for(int i = 0;i<6;i++){

                UIButton *test = [UIButton buttonWithType:UIButtonTypeCustom];

                test.frame = CGRectMake(3020*(i+1)+height*i, width, height);

                NSString* title = [NSString stringWithFormat:@"Test%d",i ];

                [test setTitle:title forState:UIControlStateNormal];

                SEL customSelector = NSSelectorFromString([NSString stringWithFormat:@"test%d:",i]);

                [test addTarget:self action:customSelector forControlEvents:UIControlEventTouchUpInside];

                [self.view addSubview:test];

            }

        }

    }

     

    - (void)test0:(UIButton *)sender

    {

        NSLog(@"请添加自己的测试代码");

    }

    - (void)test1:(UIButton *)sender

    {

        NSLog(@"请添加自己的测试代码");

        //执行同步方法

        //NSMutableDictionary* node = [[NSMutableDictionary alloc]init];

        //[node setObject:参数值 forKey:参数名];

        //[[doService Instance] SyncMethod:model :同步方法名 :node];

        

    }

    - (void)test2:(UIButton *)sender

    {

        NSLog(@"请添加自己的测试代码");

        //执行异步方法

        NSMutableDictionary* node = [[NSMutableDictionary alloc]init];

        [node setObject:@"/var/mobile/Containers/Data/Application/8F26712D-29F1-46F8-93FD-144D606E0342/Library/deviceone/data/1ea276f4-2fb8-4c03-8c0c-2c43f14c0b5d/temp/do_Album/BF74D875-7B19-44F5-9D88-40F3254BA5D4.jpg" forKey:@"imgUrl"];

        CallBackEvnet* event = [[CallBackEvnet alloc]init];//回调类

        [[doService InstanceAsyncMethod:model :@"getInfo" :node:event];

     

    }

    - (void)test3:(UIButton *)sender

    {

        NSLog(@"请添加自己的测试代码");

    }

    - (void)test4:(UIButton *)sender

    {

        NSLog(@"请添加自己的测试代码");

    }

    - (void)test5:(UIButton *)sender

    {

        NSLog(@"请添加自己的测试代码");

    }

    - (void)didReceiveMemoryWarning {

        [super didReceiveMemoryWarning];

        // Dispose of any resources that can be recreated.

     

    }

    上面蓝色部分为我添加的代码,直接在手机上面真是运行就可以了。

    上面就是编码完成了。

     

    7.上传zip包

    经过步骤6的工作,我们下一步就是上传zip包到deviceone开发者后台的组件开发里面。

    下面还是通过两个平台来讲解。

    android:

    我们看到在组件项目中有一个do_build.xml文件,打开,然后修改sdk版本路径。

    然后点击右键的ant  build。就可以打包出来上传的zip包。

     ios:

    直接上图

     

    通过这个编译之后,会有一个.a文件生成,然后将这个。a文件拷贝到一个文件夹下面

    然后在拷贝下图文件

    整理好的文件如下列表

    hwymp.a

    hwymp.plist

    M1294_hwymp_App.h

    M1294_hwymp_SM.h

    四个文件。将这四个文件压缩成一个zip就可以了。

    我们上传到android和ios各自平台上即可。

     

    8.编写示例进行调试

    打开deviceone的eclipse的开发工具。

    创建一个项目。(这个略过)

    然后去后台配置这个项目(略过)

    然后配置组件,选择自己开发的内部组件,选择。(省略)

    然后回到eclipse开发工具,同步组件(省略)

    接下来开发

     

    接下来看js的代码。

    var nf = sm("do_Notification");

    var album = sm("do_Album");

     

    var hw = sm("M1294_hwymp");

     

    var page = sm("do_Page");

    var app = sm("do_App");

     

    var file = sm("do_Storage");

     

    page.on("back", function(data) {

    app.closePage();

    })

     

     

    var select = ui("select");

    select.on("touch", function() {

    album.select(1, -1, -1, 100, falsefunction(data, e) {

    select.source = data[0];

    })

    });

     

    var btn = ui("btn");

     

    btn.on("touch", function() {

    hw.getInfo(select.source + "", function(data, e) {

    nf.alert(JSON.stringify(data));

    })

     

    });

    整个的思路就是,

    我用一个imageview来看我选择的图片

    我用一个album来选择图片并返回路径

    我用一个button来控制识别

     

    这样我的demo就完成了

     

    9.完成。

     

    下载安装调试版本的安装包。(省略)

    点击更新。

    调试出结果。OK

     

    感谢大家。谢谢。

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    Wine 的安装与解决微信文字不可见,无法聚焦问题。#Wine教程
    Utuntu / CentOS设置环境变量 #java #maven
    真机安装Linux系统 (CentOS与Ubuntu)
    scrollUtils.js #触底触发上拉加载更多 #越线 #上下滚动事件
    微信小程序 bus.js
    svchost.exe占网速的解决办法
    Linux常用的解压缩命令
    本博客标题指示灯代码
    Jenkins持续集成
    jenkins.plugins.publish_over.BapPublisherException: Failed to connect and initialize SSH connection. Message: [Failed to connect session for config [master_server]. Message [Auth fail]]
  • 原文地址:https://www.cnblogs.com/onlydo/p/5870926.html
Copyright © 2011-2022 走看看