汉王云名片识别(SM)组件开发详解
Posted only_do
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了汉王云名片识别(SM)组件开发详解相关的知识,希望对你有一定的参考价值。
大家好,最近在DeviceOne平台上做了一个汉王云名片识别的功能组件。下面把我开发过程给大家做一个分享,希望可以帮助到大家。
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, null, null, null);
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.下载组件的项目
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, null, null, null);
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);
}
}
上面的代码,标记为紫色的是我第一次要去掉的代码,原因:因为我是直接传入的照片的地址,所以跟照片有关系的我都不需要了。
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 alloc] init];
//_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 alloc] init];
//_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 alloc] init];
[_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 mainBundle] pathForResource:@"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"]){
//和SM,MM不一样,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(30, 20*(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 Instance] AsyncMethod: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, false, function(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
感谢大家。谢谢。
以上是关于汉王云名片识别(SM)组件开发详解的主要内容,如果未能解决你的问题,请参考以下文章