华为鸿蒙HarmonyOS已经发展到4.0,使用ArkTS作为开发语言。这篇文章结合Dynamsoft Service开发一个简单的鸿蒙应用,用来获取办公室里连接PC的扫描仪(惠普,富士通,爱普生,等),把文档扫描到手机里。
准备工作
-
Dynamsoft Service
-
在连接着扫描仪的电脑上安装Dynamsoft Service。安装包可以满足各种国产操作系统,比如统信UOS,麒麟Kylin OS等。支持的架构有:x86,x64,arm64,mips64el。支持的扫描仪协议包括TWAIN,WIA,SANE,ICA和eSCL(AirPrint)。下载地址:
- Windows: Dynamsoft-Service-Setup.msi
- macOS: Dynamsoft-Service-Setup.pkg
- Linux:
- Dynamsoft-Service-Setup.deb
- Dynamsoft-Service-Setup-arm64.deb
- Dynamsoft-Service-Setup-mips64el.deb
- Dynamsoft-Service-Setup.rpm
然后访问
http://127.0.0.1:18622/DWTAPI/Scanners
。正常安装可以获取到扫描仪列表。 -
在浏览器中打开
http://127.0.0.1:18625/
,把host从127.0.0.1
改成PC的局域网IP地址。比如192.168.8.72
,修改成功可以通过局域网IP地址访问192.168.8.72:18622/DWTAPI/Scanners
获取到扫描仪列表。 -
申请一个免费试用序列号,扫描文件的时候需要用。
-
-
DevEco Studio
下载地址:https://developer.harmonyos.com/cn/develop/deveco-studio/#download。安装前先安装Node.js,路径中不要带空格,否则安装DevEco Studio, 下载HarmonyOS SDK可能会失败。
鸿蒙程序开发
在DevEco Studio中新建工程。
在entry/src/main/module.json5
中添加网络权限:
{"module": {..."abilities": [...],"requestPermissions": [{"name": "ohos.permission.INTERNET"}]}
}
打开entry/src/main/etc/pages/Index.ets
,导入网络和图像模块:
import http from '@ohos.net.http';
import image from '@ohos.multimedia.image';
声明UI组件,包含两个按钮,一个下拉按钮和一个图片控件:
@Entry
@Component
struct Index {@State deviceNames: SelectOption[] = [{value: ''}]@State displayImage: PixelMap = undefinedlicenseKey: string = "LICENSE-KEY"; // https://www.dynamsoft.com/customer/license/trialLicense?product=dwthost: string = 'http://192.168.8.72:18622'devices = []index: number = 0build() {Column() {Row() {Button('Get Devices').onClick(() => {});}).width('30%')Column() {Select(this.deviceNames).selected(this.index).value(this.deviceNames[this.index].value.toString()).font({size: 14, family: 'serif', style: FontStyle.Normal }).onSelect((index:number)=>{this.index = index;})}.width('40%').alignItems(HorizontalAlign.Center)Button('Scan').onClick(() => {});}).width('30%')}.backgroundColor(0xFFFFFF).padding({ left: 12 }).width('100%').margin({bottom: 5})Divider()Image(this.displayImage).height('100%').width('100%')}.justifyContent(FlexAlign.Start).width('100%').height('100%').padding({left: 5, top: 5, right: 5, bottom: 5})}
}
这里的licenseKey
和host
需要替换成自己的。
当点击Get Devices
按钮的时候,我们通过HTTP GET来获取扫描仪列表:
Button('Get Devices').onClick(() => {let url = this.host + '/DWTAPI/Scanners'let httpRequest = http.createHttp();httpRequest.on('headersReceive', (header) => {console.info('header: ' + JSON.stringify(header));})httpRequest.request(url,{method: http.RequestMethod.GET,header: {'Content-Type': 'application/json'}}, (err, data) => {if (!err) {try {const jsonArray = JSON.parse(data.result.toString())this.devices = []let tmp: SelectOption[] = []for (const obj of jsonArray) {tmp.push({value: obj.name})this.devices.push(obj)}if (tmp.length > 0) {this.index = 0this.deviceNames = tmp}} catch (error) {console.error("Error parsing JSON:", error);}console.info('code:' + JSON.stringify(data.responseCode));} else {console.info('error:' + JSON.stringify(err));httpRequest.off('headersReceive');httpRequest.destroy();}});}).width('30%')
当点击Scan
按钮的时候,我们通过HTTP POST来触发扫描仪扫描文档. 字段extraData用于传输内容,等同于HTTP请求中的body
。传输的参数可以自定义,具体可以参考在线文档。
Button('Scan').onClick(() => {if (this.devices.length == 0) {return;}let parameters = {license: this.licenseKey,device: this.devices[this.index].device,config: {IfShowUI: false,PixelType: 2,//XferCount: 1,//PageSize: 1,Resolution: 200,IfFeederEnabled: false,IfDuplexEnabled: false,}};let url = this.host + '/DWTAPI/ScanJobs';let httpRequest = http.createHttp();httpRequest.on('headersReceive', (header) => {console.info('header: ' + JSON.stringify(header));})httpRequest.request(url,{method: http.RequestMethod.POST,header: {'Content-Type': 'application/json'},extraData: JSON.stringify(parameters),}, (err, data) => {if (!err) {if (data.responseCode == 201) {let jobId = data.result;let url = this.host + '/DWTAPI/ScanJobs/' + jobId + '/NextDocument';let httpRequest = http.createHttp();httpRequest.request(url,{method: http.RequestMethod.GET,expectDataType: http.HttpDataType.ARRAY_BUFFER}, (err, data) => {if (!err) {if (data.responseCode == 200) {// show image}} else {console.info('error:' + JSON.stringify(err));httpRequest.destroy();}});}} else {console.info('error:' + JSON.stringify(err));httpRequest.off('headersReceive');httpRequest.destroy();}});}).width('30%')
获取到的图像是一个ArrayBuffer
,我们通过image.createImageSource来创建一个PixelMap
对象,然后把它赋值给displayImage
,就可以在UI上显示出来了。
let imageData = data.result as ArrayBuffer;
const imageSource = image.createImageSource(imageData);
imageSource.createPixelMap().then(pixelmap => {this.displayImage = pixelmap;
});
在华为手机或者鸿蒙模拟器中运行文档扫描程序:
源代码
https://gitee.com/yushulx/harmonyos-document-scanner