IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 身份证读取设备开发解决方案:2、Android下通过usb转串口读取身份证信息 -> 正文阅读

[移动开发]身份证读取设备开发解决方案:2、Android下通过usb转串口读取身份证信息

身份证读取设备开发解决方案:2、Android下通过usb转串口读取身份证信息


1. 前言

之前我们已经在Windows下通过Qt5开发了一个简单的demo测试了通过封装的身份证模块读取身份证信息是可用的,接下来我们将在Android手机上开发一个简单的demo进行测试,仍然使用串口方式。(这个是上一篇:https://blog.csdn.net/weixin_39510813/article/details/118579865?spm=1001.2014.3001.5501

2. 准备

  • usb转ttl串口的模块,这个我们在Windows下测试的时候也需要的,默认厂家ttl串口的只引出了排线,没有这个转接模块,需要自己接一下线

  • 如果是直接在手机上测试的话还需要一个usb的转接头,具体看你的手机是type c的还是Micro USB接口,大多数Android现在都使用type c了,我这里测试的手机也是type c的接口

在这里插入图片描述

当然,如果是定制的Android板子的话则也可以根据自己的外设接口选择不同的身份证模块,一般Android可以直接买usb接口的。

组合后的样式:

在这里插入图片描述

ok,万事具备,开始coding

3. android下读取身份证信息的demo

3.1 部分源码

这里没有做过多的封装,只是一个demo,而且为了看代码比较方便,所以目前只放了两个文件,由于协议原因,部分内容暂时不展示:

MainActivity.java部分内容:

package com.xiaoyaoyou.xyz;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.graphics.Bitmap;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import com.hoho.android.usbserial.util.SerialInputOutputManager;
import com.zkteco.android.IDReader.WLTService;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "ReadIDCardMainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button buttonConnect = (Button) findViewById(R.id.buttonConnect);
        Button buttonDisconnect = (Button) findViewById(R.id.buttonDisConnect);
        Button buttonBuzzer = (Button) findViewById(R.id.buttonBuzzer);
        Button buttonFindIDCard = (Button) findViewById(R.id.buttonFindIdCard);
        Button buttonSelectIDCard = (Button) findViewById(R.id.buttonSelectIDCard);
        Button buttonReadIDCard = (Button) findViewById(R.id.buttonReadIDCard);
        Button buttonClear = (Button) findViewById(R.id.buttonClear);
        final UsbSerialPort[] port = new UsbSerialPort[1];
        TextView ReadSerialRes = (TextView) findViewById(R.id.textViewSerialRead);
        TextView IDCardInfoRes = (TextView) findViewById(R.id.IDCardInfotextView);
        AtomicBoolean g_readIDCardInfoFlag = new AtomicBoolean(false);
        byte[] IDCardInfo = new byte[1290];
        AtomicInteger IDCardInfoLen = new AtomicInteger();

        //连接串口
        buttonConnect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Find all available drivers from attached devices.
                UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
                List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager);
                if (availableDrivers.isEmpty()) {
                    Toast.makeText(getApplicationContext(), "未查询到串口设备", Toast.LENGTH_SHORT).show();
                    return;
                }

                // Open a connection to the first available driver.
                UsbSerialDriver driver = availableDrivers.get(0);
                UsbDeviceConnection connection = manager.openDevice(driver.getDevice());
                if (connection == null) {
                    Toast.makeText(getApplicationContext(), "连接串口失败,请确认是否开启usb权限", Toast.LENGTH_SHORT).show();
                    return;
                }

                port[0] = driver.getPorts().get(0);  //Most devices have just one port (port 0)
                try {
                    port[0].open(connection);
                    port[0].setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
                    Toast.makeText(getApplicationContext(), "打开串口成功", Toast.LENGTH_SHORT).show();

                    //串口读取监听
                    SerialInputOutputManager.Listener listener = new SerialInputOutputManager.Listener() {
                        @RequiresApi(api = Build.VERSION_CODES.KITKAT)
                        @Override
                        public void onNewData(byte[] data) {
                            runOnUiThread(() -> {
                                ReadSerialRes.append(bytesToHex(data) + "\n");

                                for (int i = 0; i < data.length; i++) {
                                    switch (data[7]) {
                                        case (byte) 0xA0:
                                            ReadSerialRes.setText("蜂鸣器");
                                            ReadSerialRes.append(bytesToHex(data), 12, 14);
                                            break;
                                        case (byte) 0xB0:
                                            ReadSerialRes.setText("寻卡");
                                            ReadSerialRes.append(bytesToHex(data), 12, 14);
                                            break;
                                        case (byte) 0xB1:
                                            ReadSerialRes.setText("选卡");
                                            ReadSerialRes.append(bytesToHex(data), 12, 14);
                                            break;
                                        case (byte) 0xB4:
                                            ReadSerialRes.setText("读卡");
                                            ReadSerialRes.append(bytesToHex(data), 12, 14);
                                            ReadSerialRes.append("\n");

                                            //触发读卡
                                            g_readIDCardInfoFlag.set(true);
                                            break;
                                        default:
                                            break;
                                    }
                                }

                                if (g_readIDCardInfoFlag.get()) {
                                    Log.d(TAG, "readData:" + bytesToHex(data));
                                    if (IDCardInfoLen.get() < 1290) {
                                        System.arraycopy(data, 0, IDCardInfo, IDCardInfoLen.get(), data.length);
                                        IDCardInfoLen.addAndGet(data.length);
                                        Log.d(TAG, "IDCardInfoLen:" + IDCardInfoLen);
                                    }

                                    if (IDCardInfoLen.get() == 1290) {
                                        Log.d(TAG, "IDCardInfo:" + bytesToHex(IDCardInfo));
                                        //头8字节不用理会,30字节姓名
                                        byte[] name = new byte[30];
                                        System.arraycopy(IDCardInfo, 8, name, 0, 30);
                                        Log.d(TAG, "nameByte:" + bytesToHex(name));
                                        String nameStr = UnicodeByteToStr(name);
                                        IDCardInfoRes.append(nameStr + "\n");
                                        Log.i(TAG, "name:" + nameStr);

                                        //2字节性别
                                        byte[] sex = new byte[2];
                                        System.arraycopy(IDCardInfo, 8 + 30, sex, 0, 2);
                                        Log.d(TAG, "sexByte:" + bytesToHex(sex));
                                        String sexStr = UnicodeByteToStr(sex);
                                        switch (sexStr) {
                                            case "1":
                                                sexStr = "男";
                                                break;
                                            case "2":
                                                sexStr = "女";
                                                break;
                                            case "9":
                                                sexStr = "其他";
                                                break;
                                            default:
                                                Log.e(TAG, "Unknown sex:" + sexStr);
                                                break;
                                        }
                                        IDCardInfoRes.append(sexStr + "\n");
                                        Log.i(TAG, "sex:" + sexStr);

                                        //4字节民族
                                        byte[] nation = new byte[4];
                                        System.arraycopy(IDCardInfo, 8 + 30 + 2, nation, 0, 4);
                                        Log.d(TAG, "nationByte:" + bytesToHex(nation));
                                        String nationStr = UnicodeByteToStr(nation);
                                        switch (Integer.parseInt(nationStr)) {
                                            case 1:
                                                nationStr = "汉";
                                                break;
                                            case 2:
                                                nationStr = "蒙古";
                                                break;
                                            case 3:
                                                nationStr = "回";
                                                break;
                                            case 4:
                                                nationStr = "藏";
                                                break;
                                            case 5:
                                                nationStr = "维吾尔";
                                                break;
                                            case 6:
                                                nationStr = "苗";
                                                break;
                                            case 7:
                                                nationStr = "彝";  //yizu彝族
                                                break;
                                            case 8:
                                                nationStr = "壮";
                                                break;
                                            case 9:
                                                nationStr = "布依";
                                                break;
                                            case 10:
                                                nationStr = "朝鲜";
                                                break;
                                            case 11:
                                                nationStr = "满";
                                                break;
                                            case 12:
                                                nationStr = "侗";  //侗族dongzu
                                                break;
                                            case 13:
                                                nationStr = "瑶";
                                                break;
                                            case 14:
                                                nationStr = "白";
                                                break;
                                            case 15:
                                                nationStr = "土家";
                                                break;
                                            case 16:
                                                nationStr = "哈尼";
                                                break;
                                            case 17:
                                                nationStr = "哈萨克";
                                                break;
                                            case 18:
                                                nationStr = "傣";  //傣族daizu
                                                break;
                                            case 19:
                                                nationStr = "黎";
                                                break;
                                            case 20:
                                                nationStr = "傈僳";  //傈僳族lisuzu
                                                break;
                                            case 21:
                                                nationStr = "佤";  //佤族wazu
                                                break;
                                            case 22:
                                                nationStr = "畲";  //畲族shezu
                                                break;
                                            case 23:
                                                nationStr = "高山";
                                                break;
                                            case 24:
                                                nationStr = "拉祜";  //拉祜lahu
                                                break;
                                            case 25:
                                                nationStr = "水";
                                                break;
                                            case 26:
                                                nationStr = "东乡";
                                                break;
                                            case 27:
                                                nationStr = "纳西";
                                                break;
                                            case 28:
                                                nationStr = "景颇";
                                                break;
                                            case 29:
                                                nationStr = "柯尔克孜";
                                                break;
                                            case 30:
                                                nationStr = "土";
                                                break;
                                            case 31:
                                                nationStr = "达斡尔";  //dawoer
                                                break;
                                            case 32:
                                                nationStr = "仫佬族";  //mulaozu
                                                break;
                                            case 33:
                                                nationStr = "羌";  //qiang
                                                break;
                                            case 34:
                                                nationStr = "布朗";
                                                break;
                                            case 35:
                                                nationStr = "撒拉";
                                                break;
                                            case 36:
                                                nationStr = "毛南";
                                                break;
                                            case 37:
                                                nationStr = "仡佬";  //仡佬族gelaozu
                                                break;
                                            case 38:
                                                nationStr = "锡伯";
                                                break;
                                            case 39:
                                                nationStr = "阿昌";
                                                break;
                                            case 40:
                                                nationStr = "普米";
                                                break;
                                            case 41:
                                                nationStr = "塔吉克";
                                                break;
                                            case 42:
                                                nationStr = "怒";
                                                break;
                                            case 43:
                                                nationStr = "乌孜别克";
                                                break;
                                            case 44:
                                                nationStr = "俄罗斯";
                                                break;
                                            case 45:
                                                nationStr = "鄂温克";
                                                break;
                                            case 46:
                                                nationStr = "德昂";
                                                break;
                                            case 47:
                                                nationStr = "独龙";
                                                break;
                                            case 48:
                                                nationStr = "裕固";
                                                break;
                                            case 49:
                                                nationStr = "京";
                                                break;
                                            case 50:
                                                nationStr = "塔塔尔";
                                                break;
                                            case 51:
                                                nationStr = "独龙";
                                                break;
                                            case 52:
                                                nationStr = "鄂伦春";
                                                break;
                                            case 53:
                                                nationStr = "赫哲";
                                                break;
                                            case 54:
                                                nationStr = "门巴";
                                                break;
                                            case 55:
                                                nationStr = "珞巴";
                                                break;
                                            case 56:
                                                nationStr = "基诺";
                                                break;
                                            default:
                                                break;
                                        }
                                        IDCardInfoRes.append(nationStr + "\n");
                                        Log.i(TAG, "nation:" + nationStr);

                                        //16字节出生
                                        byte[] birth = new byte[16];
                                        System.arraycopy(IDCardInfo, 8 + 30 + 2 + 4, birth, 0, 16);
                                        Log.d(TAG, "birthByte:" + bytesToHex(birth));
                                        String birthStr = UnicodeByteToStr(birth);
                                        IDCardInfoRes.append(birthStr + "\n");
                                        Log.i(TAG, "birth:" + birthStr);

                                        //70字节住址
                                        byte[] address = new byte[70];
                                        System.arraycopy(IDCardInfo, 8 + 30 + 2 + 4 + 16, address, 0, 70);
                                        Log.d(TAG, "addressByte:" + bytesToHex(address));
                                        String addressStr = UnicodeByteToStr(address);
                                        IDCardInfoRes.append(addressStr + "\n");
                                        Log.i(TAG, "address:" + addressStr);

                                        //36字节公民身份证号码
                                        byte[] IDNum = new byte[36];
                                        System.arraycopy(IDCardInfo, 8 + 30 + 2 + 4 + 16 + 70, IDNum, 0, 36);
                                        Log.d(TAG, "IDNumByte:" + bytesToHex(IDNum));
                                        String IDNumStr = UnicodeByteToStr(IDNum);
                                        IDCardInfoRes.append(IDNumStr + "\n");
                                        Log.i(TAG, "IDNum:" + IDNumStr);

                                        //30字节签发机关
                                        byte[] issuingAuthority = new byte[30];
                                        System.arraycopy(IDCardInfo, 8 + 30 + 2 + 4 + 16 + 70 + 36, issuingAuthority, 0, 30);
                                        Log.d(TAG, "issuingAuthority:" + bytesToHex(issuingAuthority));
                                        String issuingAuthorityStr = UnicodeByteToStr(issuingAuthority);
                                        IDCardInfoRes.append(issuingAuthorityStr + "\n");
                                        Log.i(TAG, "issuingAuthority:" + issuingAuthorityStr);

                                        //16字节有效起始日期
                                        byte[] effectiveStartDate = new byte[16];
                                        System.arraycopy(IDCardInfo, 8 + 30 + 2 + 4 + 16 + 70 + 36 + 30, effectiveStartDate, 0, 16);
                                        Log.d(TAG, "effectiveStartDate:" + bytesToHex(effectiveStartDate));
                                        String effectiveStartDateStr = UnicodeByteToStr(effectiveStartDate);
                                        IDCardInfoRes.append(effectiveStartDateStr + "\n");
                                        Log.i(TAG, "effectiveStartDateStr:" + effectiveStartDateStr);

                                        //16字节有效截至日期
                                        byte[] effectiveEndDate = new byte[16];
                                        System.arraycopy(IDCardInfo, 8 + 30 + 2 + 4 + 16 + 70 + 36 + 30 + 16, effectiveEndDate, 0, 16);
                                        Log.d(TAG, "effectiveEndDate:" + bytesToHex(effectiveEndDate));
                                        String effectiveEndDateStr = UnicodeByteToStr(effectiveEndDate);
                                        IDCardInfoRes.append(effectiveEndDateStr + "\n");
                                        Log.i(TAG, "effectiveEndDateStr:" + effectiveEndDateStr);

                                        //36字节备用

                                        //1024字节照片信息
                                        byte[] photo = new byte[1024];
                                        System.arraycopy(IDCardInfo, 8 + 30 + 2 + 4 + 16 + 70 + 36 + 30 + 16 + 16 + 36, photo, 0, 1024);
                                        Log.d(TAG, "photo:" + bytesToHex(photo));
                                        Bitmap photoRes = Tool.getBitmap(photo);
                                        ImageView image = (ImageView)findViewById(R.id.imageView);
                                        image.setImageBitmap(photoRes);
                                    }

                                    if (IDCardInfoLen.get() >= 1290) {
                                        //处理完毕初始化
                                        g_readIDCardInfoFlag.set(false);
                                        IDCardInfoLen.set(0);
                                    }
                                }
                            });
                        }

                        @Override
                        public void onRunError(Exception e) {

                        }
                    };
                    SerialInputOutputManager usbIoManager = new SerialInputOutputManager(port[0], listener);
                    usbIoManager.start();
                } catch (IOException e) {
                    Toast.makeText(getApplicationContext(), "打开串口失败", Toast.LENGTH_SHORT).show();
                    e.printStackTrace();
                }
            }
        });

        //蜂鸣器
        buttonBuzzer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            }
        });

        //寻卡
        buttonFindIDCard.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            }
        });

        //选卡
        buttonSelectIDCard.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            }
        });

        //读卡
        buttonReadIDCard.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            }
        });

        buttonClear.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ReadSerialRes.setText("");
                IDCardInfoRes.setText("");
            }
        });
    }

    final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();

    public static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public static String UnicodeByteToStr(byte[] bBuf) {
        return new String(bBuf, StandardCharsets.UTF_16LE); // 这种不会处理字符串结束符 \0
    }
}

Tool.java:

package com.xiaoyaoyou.xyz;

import android.graphics.Bitmap;
import android.util.Log;

import com.zkteco.android.IDReader.WLTService;

public class Tool
{
    private static final String TAG = "ReadIDCardMainActivity";
    public static Bitmap getBitmap(byte []data) {
        byte[] arrayOfByte1 = new byte[40960];
        try {
            if(data==null) return null;
            int k = WLTService.wlt2Bmp(data, arrayOfByte1);

            Log.i(TAG, "getBitmap: 解码结果:"+k);
            if (k != 1) {
                return null;
            }
            byte[] arrayOfByte2 = new byte[38556];
            System.arraycopy(arrayOfByte1, 0, arrayOfByte2, 0, 38556);

            return Tool.createRgbBitmap(arrayOfByte2, 102, 126);


        } catch (Exception localException) {
            localException.printStackTrace();
        }
        return null;
    }
    private static int convertByteToInt(byte paramByte)
    {
        int i = paramByte >> 4 & 0xF;
        int j = 0xF & paramByte;
        return i * 16 + j;
    }

    private static int[] convertByteToColor(byte[] paramArrayOfByte, int paramInt1, int paramInt2)
    {
        int i = paramArrayOfByte.length;
        if (i == 0) {
            return null;
        }
        int[] arrayOfInt = new int[i / 3];
        for (int n = 0; n < paramInt2; n++)
        {
            int i1 = n * paramInt1;
            for (int i2 = 0; i2 < paramInt1; i2++)
            {
                int i3 = (i1 + i2) * 3;
                int j = convertByteToInt(paramArrayOfByte[i3]);
                int k = convertByteToInt(paramArrayOfByte[(i3 + 1)]);
                int m = convertByteToInt(paramArrayOfByte[(i3 + 2)]);
                arrayOfInt[((paramInt2 - n - 1) * paramInt1 + i2)] = (j << 16 | k << 8 | m | 0xFF000000);
            }
        }
        return arrayOfInt;
    }

    private static Bitmap createRgbBitmap(byte[] paramArrayOfByte, int paramInt1, int paramInt2)
    {
        int[] arrayOfInt = convertByteToColor(paramArrayOfByte, paramInt1, paramInt2);
        if (arrayOfInt == null) {
            return null;
        }
        Bitmap localBitmap;
        localBitmap = Bitmap.createBitmap(arrayOfInt, 0, paramInt1, paramInt1, paramInt2, Bitmap.Config.ARGB_8888);
        return localBitmap;
    }
}

3.2 碎片代码

串口读取这个库通过监听的方式来读取,后续读取结果也都在这个读取到的线程中处理:

SerialInputOutputManager.Listener listener = new SerialInputOutputManager.Listener() {
                        @RequiresApi(api = Build.VERSION_CODES.KITKAT)
                        @Override
                        public void onNewData(byte[] data) {
                            runOnUiThread(() -> {
								...
							}
						}
}

关于读取到信息后的处理结果和之前的类似,由于长度为1290,所以需要根据表示缓存多帧数据后进一步处理:

//触发读卡
g_readIDCardInfoFlag.set(true);

if (g_readIDCardInfoFlag.get()) {
    if (IDCardInfoLen.get() < 1290) {
		...
	}

	if (IDCardInfoLen.get() == 1290) {
	}

	if (IDCardInfoLen.get() >= 1290) {
    	//处理完毕初始化
        g_readIDCardInfoFlag.set(false);
    	IDCardInfoLen.set(0);
    }
}

将byte[]转换为16进制字符串:

final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();

    public static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }

处理byte[]转unicode:

@RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public static String UnicodeByteToStr(byte[] bBuf) {
        return new String(bBuf, StandardCharsets.UTF_16LE); // 这种不会处理字符串结束符 \0
    }

拿到1024个字节的图片信息后,我们通过Tool.java中提供的接口调用相关库进行解码处理,这个库厂家会提供,我们只要拿到对应的库后以jni的方式添加到我们项目中即可调用。

3.3 结果展示

在这里插入图片描述

3.4 注意点

3.4.1 添加串口库

我是使用的:https://github.com/mik3y/usb-serial-for-android这个串口库,按照GitHub上添加扩展:

dependencies {
    implementation 'com.github.mik3y:usb-serial-for-android:3.4.1'
}

出现错误:could not find method implementtation

最终发现这个有点被误导:

在这里插入图片描述

这里显示是添加到根目录下的build.gradle,实际上只是第一部分url添加到项目根目录下的build.gradle,而下面依赖项的内容是添加到android/app下的build.gradle的(根据这里找到了答案:https://stackoverflow.com/questions/45615474/gradle-error-could-not-find-method-implementation-for-arguments-com-android,我是使用的最新4.x的AndroidStudio)。

此外,需要注意添加device_filter.xml

创建资源文件xml后复制内容进来即可。

3.4.2 SDK最小版本错误

串口库要求的sdk最低版本是17,而默认一般是16:

Manifest merger failed : uses-sdk:minSdkVersion 16 cannot be smaller than version 17 declared in library [com.github.mik3y:usb-serial-for-android:3.4.1] C:\Users\admin\.gradle\caches\transforms-2\files-2.1\f58431aa42060dd0c91c5352a5ce0898\usb-serial-for-android-3.4.1\AndroidManifest.xml as the library might be using APIs not available in 16
	Suggestion: use a compatible library with a minSdk of at most 16,
		or increase this project's minSdk version to at least 17,
		or use tools:overrideLibrary="com.hoho.android.usbserial" to force usage (may lead to runtime failures)

修改一下android/app下面的build.gradle,修改minSdkVersion为17即可,我们基本不会用到16版本的什么内容,所以16和17基本没有什么影响。

3.4.3 获取解码后的图片

由于Android终端机基本上我们都是使用一个usb口,所以串口基本就是搜索到的一个,波特率我们也直接写死了。拿到1024个字节的图片信息后可以通过这个Android库直接进行处理;es-100厂家给的Android demo封装的太狠了,串口处理这块的内容全部封装了。

如果有需要单独处理串口的可以看一下这个库:https://github.com/Sabirjan/WLT2Bmp_Android (主要是看其怎么使用wlt2bmp这个库的,我们通过串口已经拿到了1024字节的图片byte数组,只需要再通过这个库解码成bmp图片后展示即可,Tool.java就是我从这块拿出来的,然后结合厂家给的解码库做了一点点修改)。

当然,如果是Android上直接通过usb使用的话不需要按照我上面这样来处理,官方的demo给了jar包和so,按照jni的方式添加后,根据demo直接读取即可,封装的接口已经足够简便了,我这里仍然操作串口处理主要是为了熟悉串口协议确认这种方式也可行。

4. 最后

接下来我们将在单片机上进行身份证信息的读取,说实话我是不推荐这么做的,身份证照片的加密压缩信息需要公安部研究所提供的解码库才能解码,而单片机上是没有对应库的,所以最终要获取照片信息还是得发送到上位机处理,所以如果可以的话最好直接使用Android或Windows(Linux下也可以,但是需要单独找厂家获取SDK),不然加个单片机最后获取照片还是需要上位机,那何必浪费这个单片机,还无故多个单片机和上位机的通信过程。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-07-14 11:02:31  更:2021-07-14 11:03:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/28 0:11:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码