文章目录

  • Zebra 打印机 Android 端驱动接口开发及调用
    • GitHub 源码
    • 开发步骤
      • 环境配置
      • Zebra SDK 资源下载
      • Android 开发环境搭建
      • 新建Android项目
      • 新建 Android Library
      • 导入 Zebra 驱动包
      • Android Library 权限配置
      • ZPL II 语法在线测试
      • 主体功能开发
      • 打包 arr 文件
      • 调用 arr 接口
      • 附加:APP 打包成 APK 文件

Zebra 打印机 Android 端驱动接口开发及调用

Android 设备驱动 Zebra ZQ520 移动式打印机打印条码信息案例

GitHub 源码

  • 点击跳转

开发步骤

环境配置

  • 硬件环境

    • Zebra ZQ520 移动打印机 1 台
    • Android 设备 1 台
    • 打印纸(50mm * 40mm)
  • 软件环境
    • Android Studio 3.2

      • gradle:3.2.0

Zebra SDK 资源下载

  • 方法1:官网下载(需要各种注册信息)

    由于我是 windows 系统,所以点击 windows Installer,下载完成后,在 windows 系统中直接双击安装,安装完成后在目录:\link_os_sdk\android\v2.14.5198\lib 目录下可以找到所需要的 jar 包。

  • 方法2:CSDN 资源下载(会需要少量积分)

  • 方法3:百度网盘下载(链接:https://pan.baidu.com/s/1tVg6lW52SSeh3j6kW7ih8Q 提取码: qfc8 )

Android 开发环境搭建

正常来讲,如果是开发完整的 app 引用,则直接引入上一步中的 jar 包就可以调用 Zebra 的驱动接口了。

但是由于业务需求,我这边只负责开发一个处理拆分数据、生成ZPL命令、驱动列印功能的接口。

其他同事负责开发 Android 客户端并调用我提供的接口

所以,本案例采用的开发模式是:

  • 开发 Android Library ,打包成 arr 文件;
  • 新建空 App 应用,调用打包的 arr 接口测试。
  • 测试成功后,将测试案例与 arr 接口发送给调用者使用。

新建Android项目

  • 输入项目名称、包名,选择项目目录。

  • 选择支持的驱动环境。选择 Phone,最低 Android 4.0

  • 创建一个空模板,方便后续测试。

  • Activity 的 name 和 layout name,默认即可,点击 finish

新建完成后, Gradle 会自动同步,此时需要保持网络畅通(需要一段时间,耐心等待即可。如果没有网络,需要保证 gradle 的离线版本支持)

如果遇到如下错误:

Unable to resolve dependency for ‘:app@debug/compileClasspath’: Could not find any version that matches com.android.support:appcompat-v7:29.+.
Open File
Show Details

这是因为没有找到符合正则验证: com.android.support:appcompat-v7:29.+. 版本的文件

解决方案:

简单暴力:放宽该包的正则验证规则。

步骤:

  • 点击报错信息中的 Open File 超链接打开对应的 build gradle 文件;
  • 找到 com.android.support:appcompat-v7:29.+ 这一行;
  • 删除 29. 几个字符,保存
  • 点击上方的 “try agine”,或者 “File --> Sync Project With Gradle Files” 重新同步 gradle 文件

至此,一个空的 Android 项目就新建完成了。

新建 Android Library

  • 在项目文件上右键,或者 File --> new module
  • 选择 Android Library
  • 输入 library name,选择 minmum SDK 版本(建议和 Android 项目相同),点击 finish。

如果遇到如下错误:

Unable to resolve dependency for ‘:app@debug/compileClasspath’: Could not find any version that matches com.android.support:appcompat-v7:29.+.
Open File
Show Details

解决方案和上面相同(注意Library有自己对应的 build.gradle 文件,建议 点击报错信息中 open file 超链接跳转)

导入 Zebra 驱动包

  • 点击左上角资源总览视图中的 Android 部分,切换为 project 显示方式
  • 引入 Zebra 驱动文件到 Android Library 模块的 libs 目录下(第一步中下载的 jar 包)
  • 选中所有 jar 包,右键,Add as Library,选择 add to module 为 刚才新建的 Android Library

Add 成功后,在 Android Library 对应的 build.gradle 文件下,会自动生成如下一段代码:

dependencies {...implementation files('libs/commons-io-2.2.jar')implementation files('libs/commons-net-3.1.jar')implementation files('libs/commons-validator-1.4.0.jar')implementation files('libs/httpcore-4.3.1.jar')implementation files('libs/httpmime-4.3.2.jar')implementation files('libs/jackson-annotations-2.2.3.jar')implementation files('libs/jackson-core-2.2.3.jar')implementation files('libs/jackson-databind-2.2.3.jar')implementation files('libs/opencsv-2.2.jar')implementation files('libs/snmp6_1.jar')implementation files('libs/ZSDK_ANDROID_API.jar')
}

如果上一步中右键没有找到 “Add as Library” 选项,也可以直接手动在对应的 build.gradle 文件中添加如上代码(注意路径)

Android Library 权限配置

由于本案例采用 BlueTooth 连接,所以,需要配置 BlueTooth 赋予蓝牙的访问权限。

  • 在 Android Library 模块(zebraprinter)下依次展开 src --> main --> AndroidMainfest.xml 文件。加入如下两行代码:

    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    

    如果需要其他需求,也可以在这里继续配置权限(如:后续可能需要获取主机mac地址,所以我再加入WIFI_STATE权限)

ZPL II 语法在线测试

推荐一个在线测试 ZPL II 的网站。点击跳转

在这里,你可以在线编写 ZPL 代码,并随时点击 redraw 按钮预览结果,非常方便!

主体功能开发

本案例的主体需求为:收到一份信息,将该信息进行拆分,打印出两份信息。

Android Library 的代码基本结构如下:


其中:

  • Entity 包中存放了两个实体:

    • ResultObj:返回信息实体类。包含一个 boolean 类型的执行状态,和一个 String 类型的执行信息
    • ZeroSymbolBill:存储案例中收到与拆分的信息。为了方便操作。
  • Utils 包中存放了一个工具类:
    • Utils:工具类。包含一个生成唯一码 GUID 的静态方法。
  • ZebraPrinter 包中存放了打印机相关代码
    • ZQ520 Printer:存放了调用 ZQ520 打印机的主体代码

具体代码如下:

package com.amborsecdmeng.demo.entity;/*** Result Object*/
public class ResultObj {/*** 状态*/private boolean status;/*** 信息*/private String message;public ResultObj() {this.status = false;}public ResultObj(boolean status) {this.status = status;}public ResultObj(boolean status, String message) {this.status = status;this.message = message;}public boolean isStatus() {return status;}public void setStatus(boolean status) {this.status = status;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
}
package com.amborsecdmeng.demo.entity;/*** Model of ZeroSymbolBill** Example:** W,NEW00182631190729C0001,P2a-J60102,2T459M000-000-G5,20190729,WmL-J76036,2200,PCS,VCN00182631190729C0001* W,NEW00182631190729C0002,P2a-J60102,2T459M000-000-G5,20190729,WmL-J76036,5000,PCS,VCN00182631190729C0001*/
public class ZeroSymbolBill {/*** 类型:W*/private String type;/*** 料号:2T459M000-000-G5*/private String pn;/*** 数量:7200*/private Integer qty;/*** 拆分:5000*/private Integer splitQty;/*** 单位:PCS*/private String unit;/*** 旧 GUID:VCN00182631190729C0001*/private String oldGuid;/*** 新 GUID:NEW00182631190729C0001*/private String newGuid;/*** 日期:20190729*/private String date;/*** 预留字段 1:P2a-J60102*/private String var1;/*** 预留字段 2:WmL-J76036*/private String var2;/*** Constructor without params*/public ZeroSymbolBill() {}/*** Constructor with all params** @param type* @param newGuid* @param var1* @param pn* @param date* @param var2* @param qty* @param unit* @param oldGuid* @param splitQty*/public ZeroSymbolBill(String type, String newGuid, String var1, String pn, String date, String var2, Integer qty, String unit, String oldGuid, Integer splitQty) {this.type = type;this.newGuid = newGuid;this.var1 = var1;this.pn = pn;this.date = date;this.var2 = var2;this.qty = qty;this.unit = unit;this.oldGuid = oldGuid;this.splitQty = splitQty;}/*** Getter & Setter*/public String getType() {return type;}public void setType(String type) {this.type = type;}public String getPn() {return pn;}public void setPn(String pn) {this.pn = pn;}public Integer getQty() {return qty;}public void setQty(Integer qty) {this.qty = qty;}public Integer getSplitQty() {return splitQty;}public void setSplitQty(Integer splitQty) {this.splitQty = splitQty;}public String getUnit() {return unit;}public void setUnit(String unit) {this.unit = unit;}public String getOldGuid() {return oldGuid;}public void setOldGuid(String oldGuid) {this.oldGuid = oldGuid;}public String getNewGuid() {return newGuid;}public void setNewGuid(String newGuid) {this.newGuid = newGuid;}public String getDate() {return date;}public void setDate(String date) {this.date = date;}public String getVar1() {return var1;}public void setVar1(String var1) {this.var1 = var1;}public String getVar2() {return var2;}public void setVar2(String var2) {this.var2 = var2;}
}
package com.amborsecdmeng.demo.utils;import java.util.UUID;public class Utils {public static String GUID() {UUID uuid = UUID.randomUUID();String str = uuid.toString();String uuidStr = str.replace("-", "");return uuidStr;}
}
package com.amborsecdmeng.demo.zerbraprinter;import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.net.wifi.WifiManager;import com.amborsecdmeng.demo.entity.ResultObj;
import com.amborsecdmeng.demo.entity.ZeroSymbolBill;
import com.amborsecdmeng.demo.utils.Utils;
import com.zebra.sdk.comm.BluetoothConnection;
import com.zebra.sdk.comm.Connection;
import com.zebra.sdk.comm.ConnectionException;
import com.zebra.sdk.comm.TcpConnection;
import com.zebra.sdk.printer.PrinterLanguage;
import com.zebra.sdk.printer.PrinterStatus;
import com.zebra.sdk.printer.ZebraPrinter;
import com.zebra.sdk.printer.ZebraPrinterFactory;
import com.zebra.sdk.printer.ZebraPrinterLinkOs;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Set;/*** ZQ520 Printer*/
public class ZQ520Printer {private Context context;public ZQ520Printer(Context context) {this.context = context;}private Connection connection = null;private boolean isConnByBluetooth = true;private String bluetoothMacAddress = "";// Test Machine mac address:    AC:3F:A4:E4:D6:3Fprivate String tcpAddress = "127.0.0.1";private Integer tcpPortNumber = 0;private String printerStatusMsg = "";/*** ZeroSymbolBill Printer** @param codeMsg  BQ code message.*                 Example:*                 W,NEW00182631190729C0001,P2a-J60102,2T459M000-000-G5,20190729,WmL-J76036,2000,PCS,VCN00182631190729C0001* @param splitQty split quantity* @return*/public ResultObj zeroSymbolBill(String codeMsg, Integer splitQty) {String[] codeMsgArr = codeMsg.split(",");ArrayList<ZeroSymbolBill> zsbs = new ArrayList<>();/* BQ code message before split. include split quantity */ZeroSymbolBill zsb = new ZeroSymbolBill();try {zsb.setType(codeMsgArr[0].trim());     // type.zsb.setNewGuid(codeMsgArr[1].trim());  // current guid.    -- after split. It will become the old guidzsb.setVar1(codeMsgArr[2].trim());     //zsb.setPn(codeMsgArr[3].trim());       // p/nzsb.setDate(codeMsgArr[4].trim());     // datezsb.setVar2(codeMsgArr[5].trim());     //zsb.setQty(Integer.valueOf(codeMsgArr[6].trim())); // quantityzsb.setUnit(codeMsgArr[7].trim());     // unitzsb.setSplitQty(splitQty);} catch (NumberFormatException e) {return new ResultObj(false, "Exc-03: "+e.getMessage());}if (zsb.getSplitQty() >= zsb.getQty())return new ResultObj(false, "the split quantity must be less than quantity");/* BQ code message after split. return an arrayList */zsbs.add(new ZeroSymbolBill(zsb.getType(),Utils.GUID(), // set new guid for BQ code after splitzsb.getVar1(),zsb.getPn(),zsb.getDate(),zsb.getVar2(),zsb.getSplitQty(),// first split.    quantity = split quantityzsb.getUnit(),zsb.getNewGuid(),   // become the old guid after split0));zsbs.add(new ZeroSymbolBill(zsb.getType(),Utils.GUID(), // set new guid for BQ code after splitzsb.getVar1(),zsb.getPn(),zsb.getDate(),zsb.getVar2(),zsb.getQty() - zsb.getSplitQty(),// second split.    quantity = quantity - split quantityzsb.getUnit(),zsb.getNewGuid(),   // become the old guid after split0));/* BQ code split completion */if (isConnByBluetooth) {/* get first bonded mac address */bluetoothMacAddress = findBluetoothMacAddress().get(0);connection = new BluetoothConnection(bluetoothMacAddress);} else {try {connection = new TcpConnection(tcpAddress, tcpPortNumber);} catch (NumberFormatException e) {return new ResultObj(false, "Exc-01: Tcp connection open failed");}}try {connection.open();ZebraPrinter printer = ZebraPrinterFactory.getInstance(connection);ZebraPrinterLinkOs linkOsPrinter = ZebraPrinterFactory.createLinkOsPrinter(printer);PrinterStatus printerStatus = (linkOsPrinter != null) ? linkOsPrinter.getCurrentStatus() : printer.getCurrentStatus();if (printerStatus.isReadyToPrint) {return sendToPrint(printer, zsbs);} else if (printerStatus.isHeadOpen)printerStatusMsg = "Err-01: Head Open! \n Please close Printer Head to print. ";else if (printerStatus.isHeadCold)printerStatusMsg = "Err-02: Head Cold! \n Please try again. ";else if (printerStatus.isHeadTooHot)printerStatusMsg = "Err-03: Head too hot! \n Please do it later. ";else if (printerStatus.isPaperOut)printerStatusMsg = "Err-04: Media Out! \n Please load Media to Print. ";else if (printerStatus.isPartialFormatInProgress)printerStatusMsg = "Err-05: Head Open! \n Please try again later. ";else if (printerStatus.isPaused)printerStatusMsg = "Err-06: Printer Paused. ";else if (printerStatus.isReceiveBufferFull)printerStatusMsg = "Err-07: Buffer full! \n Please do it later. ";else if (printerStatus.isRibbonOut)printerStatusMsg = "Err-08: Ribbon Out! \n Please retry after adjustment. ";connection.close();return new ResultObj("".equals(printerStatusMsg), printerStatusMsg);} catch (Exception e) {return new ResultObj(false, "Exc-02: " + e.getMessage());} finally {}}private ResultObj sendToPrint(ZebraPrinter printer, ArrayList<ZeroSymbolBill> zsbs) {String filename = "TEMP.LBL";try {File file = context.getFileStreamPath(filename);if (!file.exists())file.createNewFile();createZPLFile(printer, filename, zsbs);printer.sendFileContents(file.getAbsolutePath());return new ResultObj(true, "filepath: " + file.getAbsolutePath());} catch (IOException e) {return new ResultObj(false, e.getMessage());} catch (ConnectionException e) {return new ResultObj(false, e.getMessage());}}private void createZPLFile(ZebraPrinter printer, String filename, ArrayList<ZeroSymbolBill> zsbs) throws IOException {FileOutputStream os = context.openFileOutput(filename, Context.MODE_PRIVATE);byte[] zplByte = null;PrinterLanguage printerLanguage = printer.getPrinterControlLanguage();if (printerLanguage == printerLanguage.ZPL) {StringBuilder sb = new StringBuilder();for (ZeroSymbolBill zsb : zsbs) {sb.append(buildZPLTemplate(zsb));}zplByte = sb.toString().getBytes();}os.write(zplByte);os.flush();os.close();}private String buildZPLTemplate(ZeroSymbolBill zsb) {final String formName = "Zero Symbol Bill";zsb.setNewGuid(Utils.GUID());StringBuilder sb = new StringBuilder();sb.append("^XA\n").append("^LL320\n").append("^PW400\n").append("^LH0,0\n").append("^CI26\n").append("^SEE:GB18030.DAT\n").append("^FO48,20^AEN,10,10^FD" + formName + "^FS\n")//Zero Symbol Bill.append("^FO24,62^AEN,10,10^FDP/N:^FS\n")//P/N.append("^FO54,102^AEN,10,10^FD" + zsb.getPn() + "^FS\n")//2T459M000-000-G5.append("^FO24,142^AEN,10,10^FDQTY:^FS\n")//QTY.append("^FO54,182^AEN,10,10^FD" + zsb.getQty() + " PCS^FS\n")//200000.append("^FO24,222^AEN,10,10^FDDATE:^FS\n")//DATE.append("^FO54,264^AEN,10,10^FD" + zsb.getDate() + "^FS\n")//20191107.append("^FO280,172^BQN,2,2^FD\n").append("   " + zsb.getType()+ "," + zsb.getNewGuid()+ "," + zsb.getVar1()+ "," + zsb.getPn()+ "," + zsb.getDate()+ "," + zsb.getVar2() + "," + zsb.getQty() + ",PCS," + zsb.getOldGuid() + "^FS\n").append("^XZ");return sb.toString();}/*** find bluetooth mac address list** @return*/private ArrayList<String> findBluetoothMacAddress() {ArrayList<String> macAddressList = new ArrayList<>();BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();for (BluetoothDevice device : devices)macAddressList.add(device.getAddress());return macAddressList;}/*** get Local Mac Address** @return*/private String getLocalMacAddress(){WifiManager wifi = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);return wifi.getConnectionInfo().getMacAddress();}
}

打包 arr 文件

arr 文件和 jar 文件类似都可以理解为一个类库文件。不同的是,arr 文件包含了class以及res资源文件,而 jar 文件只包含了 class 文件。

至于这两种文件详细的异同,请自行查阅资料,本文不做详细介绍。

  • 在 Android Studio 代码界面最右侧 “gradle” 选项,选中开始创建的 Android Library 目录,依次展开:Tasks --> build --> assemble。 双击执行。

  • 打包 arr 文件。(输出在 /build/outputs/arr 目录下)

    其中,zebraprinter-release.aar 文件就是打包好的发布版本(才发现,模块名字中我将 zebra 误写成 zerbra 了)

调用 arr 接口

以上,arr 接口开发以及打包已经完成,按理来说,这里只需要将 arr 文件打包发送 Android 客户端的开发人员即可。

但是,我们这里先自行测试一下。

  • 将 arr 文件 copy 到 项目 app 模块(最开始创建的 Android 应用空模板)的 libs 目录下并重命名(记得切换到 project 显示,否则不显示 libs 包)。

  • 修改 build.gradle 配置文件(如不修改,在使用时 Android Studio 也会提示修改,建议手动修改)
    在 app 模块的 build.gradle 文件中的 dependencies 代码块中,加入如下代码:

    implementation files('libs/zebraprinter.aar')
    

  • 在 app 模块的 activity_main.xml 界面设计文件中,增加一个按钮用于测试。

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><Buttonandroid:id="@+id/btnPrintTest"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="67dp"android:text="PrintTest"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /></android.support.constraint.ConstraintLayout>
    

  • 在 app 模块的 MainActivity 文件中为 printtest 按钮增加点击监听事件,调用 arr 接口中的 zeroSymbolBill 方法发送打印命令

    package com.foxconn.mac1.zebraprintdemo;import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.Toast;import com.foxconn.mac1.zebraprinter.Entity.ResultObj;
    import com.foxconn.mac1.zebraprinter.ZebraPrinter.ZQ520Printer;public class MainActivity extends AppCompatActivity {protected Button btnPrint;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);btnPrint = this.findViewById(R.id.btnPrintTest);btnPrint.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View view){printTest();}});}public void printTest(){try {/* Example for Test */String BQcode = "W,VCN00182631190729C0001,P2a-J60102,2T459M000-000-G5,20190729,WmL-J76036,7200,PCS";Integer split = 2000;ZQ520Printer zq520Printer = new ZQ520Printer(this);ResultObj resultObj = zq520Printer.zeroSymbolBill(BQcode, split);if (resultObj.isStatus()){Toast.makeText(MainActivity.this, "print test success", Toast.LENGTH_SHORT).show();}else{Toast.makeText(MainActivity.this, resultObj.getMessage(), Toast.LENGTH_SHORT).show();}/* Example end */} catch (Exception e) {e.printStackTrace();Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();}}
    }

至此,代码开发及测试已经完成。

附加:APP 打包成 APK 文件

  • 选中 app 模块,依次选择 Build --> Generate Signed Bundle / APK

  • 选择打包类型。

    • 选择 Android APP Bundle 会生成 aab 格式文件;

    • 选择 APK 会生成 apk 格式文件;

      aab 格式与 apk 格式的区别:参考文章

  • 配置 app 开发证书信息

    Android 开发证书生成指南:参考文章

  • 选择最终生成 apk 文件的目录

  • 打包成功


    打包完成,Copy 到 Android 客户端即可安装测试。

Zebra 打印机 Android 端驱动接口开发及调用案例相关推荐

  1. Android实现注册登录头像上传等功能常规开发(Android端,服务器端开发实例)

    Android实现注册登录头像上传等功能常规开发(Android端,服务器端开发实例) 标签: 注册登录Android开发servlet 2017-04-18 20:34  454人阅读  评论(1) ...

  2. Android项目驱动式开发教程 第2版,《Android项目驱动式开发教程》第一章开发入门.ppt...

    <Android项目驱动式开发教程>第一章开发入门 1.4 项目框架分析 4 android:versionName="1.0" > 5 8 第9行代码andro ...

  3. android滴滴打车代码,Android 端滴滴打车接口的开发

    前两天做了一个对Android端'滴滴打车'的接口开发吧! 今天来做个简单的流程, 滴滴会提供这样一个接口, http://webapp.diditaxi.com.cn/? maptype=wgs&a ...

  4. Android 端滴滴打车接口的开发

    前两天做了一个对Android端'滴滴打车'的接口开发吧! 今天来做个简单的流程, 滴滴会提供这样一个接口, http://webapp.diditaxi.com.cn/? maptype=wgs&a ...

  5. 【Android 逆向】Android 进程注入工具开发 ( 远程调用 | x86 架构的返回值获取 | arm 架构远程调用 )

    文章目录 前言 一.x86 架构的返回值获取 二.ARM 架构远程调用 前言 在之前的博客 [Android 逆向]Android 进程注入工具开发 ( 注入代码分析 | 获取 远程 目标进程 中的 ...

  6. 【Android 逆向】Android 进程注入工具开发 ( 远程调用总结 | 远程调用注意事项 )

    文章目录 一.远程调用总结 二.远程调用注意事项 一.远程调用总结 在之前的博客 [Android 逆向]Android 进程注入工具开发 ( 调试进程中寄存器的作用 | 通过 EIP 寄存器控制程序 ...

  7. android 服务器201,Android端i-jetty服务器开发(八)

    http://blog.csdn.net/kongxx/article/details/7237034 Jetty实战之 嵌入式Jetty运行web app 1. 运行标准的war文件 1.1 首先找 ...

  8. java 红包接口开发_java调用微信现金红包接口的心得与体会总结

    这几天看了下之前写的有关微信支付的博客,看的人还是挺多的,看了下留言不知道是因为博客写的不够细还是什么情况,大多都找我要源码,我觉得吧程序员还是需要有这么一个思考的过程,因此没直接给源码,俗话说&qu ...

  9. Android端海康监控视频调用-实例

    一. 开发环境 1. 操作系统:windows7(X64) 2. 开发工具:eclipse adt Build: v22.2.1-833290 JDK7 android SDK 3. 客户端设备版本: ...

最新文章

  1. oracle以sysdba登陆,oracle 以SYSDBA身份登陆
  2. 限制数据记录查询数量
  3. windows docker 卸载_安装Docker(Docker Toolbox)与Splash库
  4. Windows批处理命令学习三
  5. 学习CGI之前,需要配置阿帕奇---windows
  6. outlook 附件保存位置-附件无法打开
  7. [状压dp][剪枝搜索] 洛谷 P2831 愤怒的小鸟
  8. 谷歌、bing 翻译插件调研总结
  9. dpdk-pktgen快速发包工具踩坑日记
  10. 北航计算机学院考研专硕,北京航空航天大学计算机学院2020考研拟录取及未录取名单...
  11. 柯特斯公式的matlab代码,牛顿-柯特斯公式C语言的实现.pdf
  12. linux内存显示少,linux 显示的内存怎么少于我实际的物理内存
  13. 【原创】linux使用终端命令执行pyt…
  14. openstack虚拟机热迁移优化如何治本?
  15. 2022最新版40个前端练手项目【附视频+源码】
  16. python 抓取猫眼电影评分
  17. 如何在vue中设置全局方法
  18. 论语 尧曰篇(笔记)
  19. [JS]Array对象
  20. 【转载】飞秋最新版2013下载

热门文章

  1. 【随笔】Windows 查看端口占用并关闭
  2. 7-3 高空坠球(20 分)
  3. Appium自动化测试基础 — APPium基本原理
  4. 归并排序(C语言)详解
  5. CorelDRAW大全集及按键技巧
  6. 温度传感器种类及工作原理
  7. 传统语音增强——基于小波分解的语音降噪算法
  8. JavaScript 国际化,货币展示与选定时区日期展示
  9. Qin.Data发布及 使用说明
  10. PDF阅读器怎么编辑文件?快来学习一下这个方法