汉王云名片识别(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,?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.下載組件的項目
通過步驟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,?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
?
感謝大家。謝謝。
?
?
?
?
?
?
?
?
?
?
?
轉載于:https://www.cnblogs.com/onlydo/p/5870926.html
總結
以上是生活随笔為你收集整理的汉王云名片识别(SM)组件开发详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows 2008 r2 系统默认
- 下一篇: WebAPI 2参数绑定方法