文章目录

  • 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. c#项目转JAVA,第5个月,基本完成
  2. java将两个区间范围合并_Java如何将若干时间区间进行合并的方法步骤
  3. SQL Server数据库原理
  4. java ee会话_Java EE会话技术Cookie和Session
  5. mysql将表的某一列全部置空NULL。
  6. [NOI2015]寿司晚宴——状压dp
  7. pd17虚拟机启动器生成方法
  8. 麦子学院python百度云_麦子学院python
  9. 【Win10】【亲手解决】华硕笔记本重装系统遇到的各种问题【包括重启会自动修复】
  10. 【阿里云镜像】更新阿里巴巴开源镜像站镜像——Ubuntu镜像
  11. linux离线安装nettools,CentOS最小安装之安装net-tools并配置网络
  12. Aegisub彩虹字特效代码
  13. 路由器不同网段虚拟服务器设置,局域网中不同网段互访?静态路由表必须要学会设置...
  14. 无需代码,1秒搞定QQ和微信多开!
  15. MoverScore: Text Generation Evaluating with Contextualized Embeddings and Earth Mover Distance
  16. wms、wmts和wfs的区别
  17. 高防服务器好,还是游戏盾好?
  18. 第一个只出现一次的字符
  19. python协程和网易云歌单
  20. 室内定位UWB技术在工业场景的潜力几何?

热门文章

  1. 解决51单片机学习过程中mac环境下虚拟机不能安装ch341驱动的问题
  2. webservice接口使用json参数
  3. 【23年1月17日】基于Flask技术的全国气象数据采集及可视化分析系统,支持城市定制服务
  4. 个人网站模板颜色搭配技巧
  5. 软考网络工程师上午常考点
  6. php有strock吗,PHP函数中满足条件时的类中的Echo元素
  7. CocosCreator多语言包的处理
  8. 射频功率放大器设计基础
  9. Spring Boot+高德地图热力图动态数据展示+MySQL
  10. c语言 | 求100-200之间的素数(两种方法)