mirror of
https://github.com/RfidResearchGroup/RFIDtools.git
synced 2026-05-12 11:19:59 -07:00
module from github to local files.
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
package com.dxl.iobridges;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
|
||||
assertEquals("com.dxl.iobridges.test", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.dxl.iobridges" />
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.iobridges.bulkio;
|
||||
|
||||
import android.hardware.usb.UsbDeviceConnection;
|
||||
import android.hardware.usb.UsbEndpoint;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class BulkInputStream extends InputStream {
|
||||
private int timeout;
|
||||
private UsbDeviceConnection connection;
|
||||
private UsbEndpoint endpoint;
|
||||
|
||||
public BulkInputStream(UsbDeviceConnection connection, UsbEndpoint endpoint) {
|
||||
this.connection = connection;
|
||||
this.endpoint = endpoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
byte[] bs = new byte[1];
|
||||
int len = connection.bulkTransfer(endpoint, bs, 1, timeout);
|
||||
if (len > 0) {
|
||||
return bs[0];
|
||||
}
|
||||
if (len < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(@NonNull byte[] b) throws IOException {
|
||||
return connection.bulkTransfer(endpoint, b, b.length, timeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(@NonNull byte[] b, int off, int len) throws IOException {
|
||||
return connection.bulkTransfer(endpoint, b, off, len, timeout);
|
||||
}
|
||||
|
||||
public int getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public void setTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.iobridges.bulkio;
|
||||
|
||||
import android.hardware.usb.UsbDeviceConnection;
|
||||
import android.hardware.usb.UsbEndpoint;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class BulkOutputStream extends OutputStream {
|
||||
private int timeout = 2333;
|
||||
private UsbDeviceConnection connection;
|
||||
private UsbEndpoint endpoint;
|
||||
|
||||
public BulkOutputStream(UsbDeviceConnection connection, UsbEndpoint endpoint) {
|
||||
this.connection = connection;
|
||||
this.endpoint = endpoint;
|
||||
}
|
||||
|
||||
public int getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public void setTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
connection.bulkTransfer(endpoint, new byte[]{(byte) b}, 0, 1, timeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NonNull byte[] b, int off, int len) throws IOException {
|
||||
connection.bulkTransfer(endpoint, b, off, len, timeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NonNull byte[] b) throws IOException {
|
||||
connection.bulkTransfer(endpoint, b, 0, b.length, timeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.iobridges.com;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* author DXL
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public interface Communication extends Serializable {
|
||||
/**
|
||||
* Get OutputStream implement!
|
||||
*/
|
||||
OutputStream getOutput();
|
||||
|
||||
/**
|
||||
* Get InputStream implement!
|
||||
*/
|
||||
InputStream getInput();
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.iobridges.com;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Abstract device check base class, can judge whether the device and communication are normal!
|
||||
*
|
||||
* @author DXL
|
||||
* @version 1.1
|
||||
*/
|
||||
public abstract class DeviceChecker implements Serializable, Closeable {
|
||||
protected Communication communication;
|
||||
|
||||
public DeviceChecker(Communication communication) {
|
||||
this.communication = communication;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a device is can work!
|
||||
*
|
||||
* @return if can work return true, if no, return false
|
||||
*/
|
||||
public final boolean check() throws IOException {
|
||||
if (communication == null) {
|
||||
throw new IOException("The communication must be nonnull.");
|
||||
}
|
||||
InputStream is = communication.getInput();
|
||||
OutputStream os = communication.getOutput();
|
||||
if (is == null || os == null) {
|
||||
throw new IOException("The inputStream and outputStream must be nonnull.");
|
||||
}
|
||||
// Auto init communication to mapper.
|
||||
LocalComBridgeAdapter.getInstance().setInputStream(is).setOutputStream(os)
|
||||
.startServer(LocalComBridgeAdapter.NAMESPACE_DEFAULT);
|
||||
if (!checkDevice()) {
|
||||
// if check failed, we must to close client!
|
||||
close();
|
||||
// and close client communication!
|
||||
LocalComBridgeAdapter.getInstance().stopClient();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract boolean checkDevice() throws IOException;
|
||||
|
||||
/**
|
||||
* Close the device(Should no close communication. only close device!)
|
||||
*/
|
||||
public abstract void close() throws IOException;
|
||||
}
|
||||
@@ -0,0 +1,436 @@
|
||||
package com.iobridges.com;
|
||||
|
||||
import android.hardware.usb.UsbConstants;
|
||||
import android.hardware.usb.UsbEndpoint;
|
||||
import android.net.LocalServerSocket;
|
||||
import android.net.LocalSocket;
|
||||
import android.net.LocalSocketAddress;
|
||||
import android.util.Log;
|
||||
|
||||
import com.iobridges.utils.HexUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author DXL
|
||||
* Created by DXL on 2017/8/21.
|
||||
* Communication control mapping implementation,
|
||||
* the realization of inter process communication!
|
||||
*/
|
||||
public final class LocalComBridgeAdapter implements Serializable {
|
||||
/*
|
||||
* Warning!!!
|
||||
* If your implementation does not need to be mapped to the c/c++ (only Java exists), please do not use this tool class!
|
||||
*
|
||||
* 警告!!!
|
||||
* 如果您的实现不需要映射到底层(只存在Java),请不要使用此工具类!
|
||||
* */
|
||||
|
||||
// The namespace of the LocalServerSocket
|
||||
public static final String NAMESPACE_DEFAULT = "DXL.COM.ASL";
|
||||
// The tag of the log.
|
||||
private final String LOG_TAG = "LocalComBridgeAdapter";
|
||||
// 本地套接字服务!
|
||||
private LocalServerSocket serverSocket;
|
||||
// 单例!
|
||||
private static LocalComBridgeAdapter instance;
|
||||
// 设备输入流!
|
||||
private volatile InputStream mInputStreamFromDevice;
|
||||
// 设备输出流!
|
||||
private volatile OutputStream mOutputStreamFromDevice;
|
||||
// 客户端输入流
|
||||
private volatile InputStream mInputStreamFromSocket;
|
||||
// 客户端输出流
|
||||
private volatile OutputStream mOutputStreamFromSocket;
|
||||
// 是否已经连接!
|
||||
private volatile boolean isHasClient = false;
|
||||
// 是否关闭监听!
|
||||
private volatile boolean listenAccept = false;
|
||||
// 连接到转发服务的客户端!
|
||||
private LocalSocket socket;
|
||||
// 设备数据转发线程是否可以工作
|
||||
private volatile boolean forwardWork = false;
|
||||
// connection lock!
|
||||
private static final Object LOCK = new Object();
|
||||
// con thread status!
|
||||
private volatile boolean isConThreadRunning = false;
|
||||
// device thread status!
|
||||
private volatile boolean isDeviceDataThreadRunning = false;
|
||||
// server action timeout, default is 1000ms!
|
||||
private int timeout = 1000;
|
||||
// current namespace
|
||||
private String namespace;
|
||||
// is server stop
|
||||
private volatile boolean isServerStopAction = false;
|
||||
// The buffer max for the device IO, default is 16384
|
||||
private int deviceBufferMax = 16384;
|
||||
|
||||
private LocalComBridgeAdapter() { /* No instantiation is required */ }
|
||||
|
||||
/**
|
||||
* Data forward thread!
|
||||
* data will from a InputStream to a OutputStream!
|
||||
*/
|
||||
private class ConServerThread extends Thread {
|
||||
@Override
|
||||
public void run() {
|
||||
while (listenAccept) {
|
||||
try {
|
||||
if (serverSocket != null) {
|
||||
Log.d(LOG_TAG, "服务套接字堵塞等待连接中!");
|
||||
isConThreadRunning = true;
|
||||
LocalSocket socketInternal = serverSocket.accept();
|
||||
if (isServerStopAction) throw new IOException("Server closed.");
|
||||
Log.d(LOG_TAG, "服务套接字连接成功,将会开启一个客户端线程!");
|
||||
mInputStreamFromSocket = socketInternal.getInputStream();
|
||||
mOutputStreamFromSocket = socketInternal.getOutputStream();
|
||||
socket = socketInternal;
|
||||
isHasClient = true;
|
||||
new SocketDataThread().start();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
isHasClient = false;
|
||||
listenAccept = false;
|
||||
Log.w(LOG_TAG, "Connection thread abort!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
isConThreadRunning = false;
|
||||
Log.d(LOG_TAG, "ConServerThread结束");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data from socket to device transfer
|
||||
* need client connect and stable communication!
|
||||
*/
|
||||
private class SocketDataThread extends Thread {
|
||||
private byte[] buffer = new byte[1024 * 500];
|
||||
|
||||
SocketDataThread() {
|
||||
setPriority(MAX_PRIORITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Log.d(LOG_TAG, "SocketDataThread执行");
|
||||
while (true) {
|
||||
try {
|
||||
int available = mInputStreamFromSocket.available();
|
||||
if (available > 0) {
|
||||
int len = mInputStreamFromSocket.read(buffer);
|
||||
// Log.d(LOG_TAG, "mInputStreamFromSocket.read()->len: " + len);
|
||||
if (len > 0) {
|
||||
mOutputStreamFromDevice.write(Arrays.copyOf(buffer, len));
|
||||
mOutputStreamFromDevice.flush();
|
||||
// Log.d(LOG_TAG, "SocketDataThread数据传输: " + HexUtil.toHexString(buffer, 0, len));
|
||||
}
|
||||
if (len == -1) {
|
||||
throw new IOException("Socket already disconnected.");
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
}
|
||||
}
|
||||
Log.d(LOG_TAG, "SocketDataThread结束");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data from device to socket client transfer
|
||||
* default case, it is always worked at runtime!
|
||||
*/
|
||||
private class DeviceDataThread extends Thread {
|
||||
// 在某些机型上,这个值是无效的,会导致bulkTransfer()卡死
|
||||
// private byte[] buffer = new byte[1024 * 500];
|
||||
// 因此我们需要使用Usb规定的最大值
|
||||
private final byte[] buffer = new byte[deviceBufferMax];
|
||||
|
||||
DeviceDataThread() {
|
||||
setPriority(MAX_PRIORITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Log.d(LOG_TAG, "DeviceDataThread执行");
|
||||
isDeviceDataThreadRunning = true;
|
||||
while (forwardWork) {
|
||||
if (isHasClient) { // 有客户端的时候才接收数据!
|
||||
try {
|
||||
int len = mInputStreamFromDevice.read(buffer);
|
||||
if (len > 0) {
|
||||
// Log.d(LOG_TAG, "mInputStreamFromDevice.read()->len: " + len);
|
||||
mOutputStreamFromSocket.write(Arrays.copyOf(buffer, len));
|
||||
mOutputStreamFromSocket.flush();
|
||||
// Log.d(LOG_TAG, "DeviceDataThread数据传输: " + HexUtil.toHexString(buffer));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Empty
|
||||
// e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.d(LOG_TAG, "DeviceDataThread结束");
|
||||
}
|
||||
}
|
||||
|
||||
public static LocalComBridgeAdapter getInstance() {
|
||||
synchronized (LOCK) {
|
||||
/*
|
||||
* It is a single instance tools
|
||||
* you can't instantiation than for once.
|
||||
* */
|
||||
if (instance == null) instance = new LocalComBridgeAdapter();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* get inputStream from external device
|
||||
*
|
||||
* @return the inputStream of device
|
||||
*/
|
||||
public InputStream getInputStream() {
|
||||
return mInputStreamFromDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
* set inputStream from external device
|
||||
* The adapter will automatically read bytes from this input stream
|
||||
* and forward them to the client with socket
|
||||
*
|
||||
* @param mInputStream the inputStream from external device implement!
|
||||
* @return this
|
||||
*/
|
||||
public LocalComBridgeAdapter setInputStream(InputStream mInputStream) {
|
||||
this.mInputStreamFromDevice = mInputStream;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* get outputStream from external device
|
||||
*
|
||||
* @return the outputStream of device
|
||||
*/
|
||||
public OutputStream getOutputStream() {
|
||||
return mOutputStreamFromDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
* set outputStream from external device
|
||||
* The adapter will automatically read bytes from the socket client
|
||||
* and write them to this output stream
|
||||
*
|
||||
* @param mOutputStream the outputStream from external device implement!
|
||||
* @return this
|
||||
*/
|
||||
public LocalComBridgeAdapter setOutputStream(OutputStream mOutputStream) {
|
||||
this.mOutputStreamFromDevice = mOutputStream;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn on server on a namespace
|
||||
* default namespace is {@link #NAMESPACE_DEFAULT }
|
||||
* namespace only once instance at runtime
|
||||
* namespace is unique
|
||||
*
|
||||
* @param namespace the namespace is also used when clients connect
|
||||
* @return this
|
||||
*/
|
||||
public LocalComBridgeAdapter startServer(String namespace) {
|
||||
synchronized (LOCK) {
|
||||
if (!listenAccept) {
|
||||
listenAccept = true;
|
||||
isConThreadRunning = false;
|
||||
isServerStopAction = false;
|
||||
try {
|
||||
if (serverSocket == null) {
|
||||
serverSocket = new LocalServerSocket(namespace);
|
||||
this.namespace = namespace;
|
||||
}
|
||||
// 创建一个客户端连接线程
|
||||
new ConServerThread().start();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Log.e(LOG_TAG, "If you see an error message like \"Address already in use\", check that you call the stopServer function");
|
||||
}
|
||||
// wait con thread running...
|
||||
long startTime = System.currentTimeMillis();
|
||||
while (!isConThreadRunning) {
|
||||
// Log.w(LOG_TAG, "Waiting for LocalComBridgeAdapter server start......");
|
||||
if (System.currentTimeMillis() - startTime > timeout) {
|
||||
Log.w(LOG_TAG, "LocalComBridgeAdapter server start timeout.");
|
||||
return this;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.w(LOG_TAG, "LocalComBridgeAdapter already start!");
|
||||
}
|
||||
if (!forwardWork) {
|
||||
forwardWork = true;
|
||||
isDeviceDataThreadRunning = false;
|
||||
// 创建一个数据转发线程
|
||||
new DeviceDataThread().start();
|
||||
// wait device data thread running...
|
||||
long startTime = System.currentTimeMillis();
|
||||
while (!isDeviceDataThreadRunning) {
|
||||
// Log.w(LOG_TAG, "Waiting for LocalComBridgeAdapter server start......");
|
||||
if (System.currentTimeMillis() - startTime > timeout) {
|
||||
Log.w(LOG_TAG, "LocalComBridgeAdapter server start timeout.");
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if task is start successfully, we need sleep 100ms, ensure all resource is readied.
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Log.d(LOG_TAG, "LocalComBridgeAdapter start!");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop server listen!
|
||||
* After the service is stopped,
|
||||
* the client will not be able to connect.
|
||||
* In general, please do not shut down the service.
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
public LocalComBridgeAdapter stopServer() {
|
||||
synchronized (LOCK) {
|
||||
listenAccept = false;
|
||||
isServerStopAction = true;
|
||||
isDeviceDataThreadRunning = false;
|
||||
if (serverSocket != null) {
|
||||
try {
|
||||
simClient2CloseServer();
|
||||
serverSocket.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
serverSocket = null;
|
||||
}
|
||||
long startTime = System.currentTimeMillis();
|
||||
while (isConThreadRunning) {
|
||||
// Log.w(LOG_TAG, "Waiting for LocalComBridgeAdapter server stop......");
|
||||
if (System.currentTimeMillis() - startTime > timeout) {
|
||||
Log.w(LOG_TAG, "LocalComBridgeAdapter server stop timeout.");
|
||||
return this;
|
||||
}
|
||||
}
|
||||
Log.d(LOG_TAG, "LocalComBridgeAdapter server stop!");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// Simulate the behavior of requesting a connection to close it
|
||||
private void simClient2CloseServer() {
|
||||
LocalSocket localSocket = new LocalSocket();
|
||||
try {
|
||||
localSocket.connect(new LocalSocketAddress(namespace));
|
||||
localSocket.shutdownInput();
|
||||
localSocket.shutdownOutput();
|
||||
localSocket.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop client connection.
|
||||
* Calling this function will close the client link from C/C++ or java or any...
|
||||
* please call when you need to connect to a new client.
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
public LocalComBridgeAdapter stopClient() {
|
||||
synchronized (LOCK) {
|
||||
isHasClient = false;
|
||||
try {
|
||||
if (socket != null) {
|
||||
// close socket
|
||||
socket.shutdownInput();
|
||||
socket.shutdownOutput();
|
||||
socket.close();
|
||||
mInputStreamFromSocket.close();
|
||||
mOutputStreamFromSocket.close();
|
||||
socket = null;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Log.d(LOG_TAG, "LocalComBridgeAdapter client stop!");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The timeout fro start and stop server!
|
||||
*
|
||||
* @return timeout ms.
|
||||
*/
|
||||
public int getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* The timeout for start and stop server!
|
||||
*
|
||||
* @param timeout timeout ms.
|
||||
* @return this
|
||||
*/
|
||||
public LocalComBridgeAdapter setTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get buffer of device
|
||||
*
|
||||
* @return buffer size max
|
||||
*/
|
||||
public int getDeviceBufferMax() {
|
||||
return deviceBufferMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set buffer size max of the device.
|
||||
* if you are UsbDevice, the buffer size recommend use default!
|
||||
* or less than 16384, see {@link android.hardware.usb.UsbDeviceConnection#bulkTransfer(UsbEndpoint, byte[], int, int)}
|
||||
*
|
||||
* @param deviceBufferMax the new size of buffer
|
||||
* @return this
|
||||
*/
|
||||
public LocalComBridgeAdapter setDeviceBufferMax(int deviceBufferMax) {
|
||||
this.deviceBufferMax = deviceBufferMax;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy all task and recovery all resources
|
||||
* Warning!! this action only can run on app exit!
|
||||
* It will destroy server and client, and adapter single instance!
|
||||
* so, it can run on application exit only.
|
||||
*/
|
||||
public void destroy() {
|
||||
stopClient();
|
||||
stopServer();
|
||||
forwardWork = false;
|
||||
instance = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
package com.iobridges.utils;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class HexUtil {
|
||||
private final static char[] HEX_DIGITS = {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
||||
};
|
||||
|
||||
public static String dumpHexString(byte[] array) {
|
||||
return dumpHexString(array, 0, array.length);
|
||||
}
|
||||
|
||||
public static String dumpHexString(byte[] array, int offset, int length) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
byte[] line = new byte[16];
|
||||
int lineIndex = 0;
|
||||
|
||||
result.append("\n0x");
|
||||
result.append(toHexString(offset));
|
||||
|
||||
for (int i = offset; i < offset + length; i++) {
|
||||
if (lineIndex == 16) {
|
||||
result.append(" ");
|
||||
|
||||
for (int j = 0; j < 16; j++) {
|
||||
if (line[j] > ' ' && line[j] < '~') {
|
||||
result.append(new String(line, j, 1));
|
||||
} else {
|
||||
result.append(".");
|
||||
}
|
||||
}
|
||||
|
||||
result.append("\n0x");
|
||||
result.append(toHexString(i));
|
||||
lineIndex = 0;
|
||||
}
|
||||
|
||||
byte b = array[i];
|
||||
result.append(" ");
|
||||
result.append(HEX_DIGITS[(b >>> 4) & 0x0F]);
|
||||
result.append(HEX_DIGITS[b & 0x0F]);
|
||||
|
||||
line[lineIndex++] = b;
|
||||
}
|
||||
|
||||
if (lineIndex != 16) {
|
||||
int count = (16 - lineIndex) * 3;
|
||||
count++;
|
||||
for (int i = 0; i < count; i++) {
|
||||
result.append(" ");
|
||||
}
|
||||
|
||||
for (int i = 0; i < lineIndex; i++) {
|
||||
if (line[i] > ' ' && line[i] < '~') {
|
||||
result.append(new String(line, i, 1));
|
||||
} else {
|
||||
result.append(".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static String toHexString(byte b) {
|
||||
return toHexString(toByteArray(b));
|
||||
}
|
||||
|
||||
public static String toHexString(byte[] array) {
|
||||
if (array == null) return null;
|
||||
return toHexString(array, 0, array.length);
|
||||
}
|
||||
|
||||
public static String toHexString(Byte[] array) {
|
||||
if (array == null) return null;
|
||||
byte[] bytes = new byte[array.length];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
bytes[i] = array[i];
|
||||
}
|
||||
return toHexString(bytes, 0, array.length);
|
||||
}
|
||||
|
||||
public static String toHexString(byte[] array, int offset, int length) {
|
||||
char[] buf = new char[length * 2];
|
||||
|
||||
int bufIndex = 0;
|
||||
for (int i = offset; i < offset + length; i++) {
|
||||
byte b = array[i];
|
||||
buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F];
|
||||
buf[bufIndex++] = HEX_DIGITS[b & 0x0F];
|
||||
}
|
||||
|
||||
return new String(buf);
|
||||
}
|
||||
|
||||
public static String toHexString(int i) {
|
||||
return toHexString(toByteArray(i));
|
||||
}
|
||||
|
||||
public static String toHexString(short i) {
|
||||
return toHexString(toByteArray(i));
|
||||
}
|
||||
|
||||
public static String decorateHex(String hexStr) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
char[] charArr = hexStr.toCharArray();
|
||||
for (int i = 0; i < charArr.length; i += 2) {
|
||||
sb.append("0x").append(charArr[i])
|
||||
.append(charArr[i + 1]).append(" ");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static byte[] toByteArray(byte b) {
|
||||
byte[] array = new byte[1];
|
||||
array[0] = b;
|
||||
return array;
|
||||
}
|
||||
|
||||
public static byte[] toByteArray(int i) {
|
||||
byte[] array = new byte[4];
|
||||
|
||||
array[3] = (byte) (i & 0xFF);
|
||||
array[2] = (byte) ((i >> 8) & 0xFF);
|
||||
array[1] = (byte) ((i >> 16) & 0xFF);
|
||||
array[0] = (byte) ((i >> 24) & 0xFF);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public static byte[] toByteArray(short i) {
|
||||
byte[] array = new byte[2];
|
||||
|
||||
array[1] = (byte) (i & 0xFF);
|
||||
array[0] = (byte) ((i >> 8) & 0xFF);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
private static int toByte(char c) {
|
||||
if (c >= '0' && c <= '9')
|
||||
return (c - '0');
|
||||
if (c >= 'A' && c <= 'F')
|
||||
return (c - 'A' + 10);
|
||||
if (c >= 'a' && c <= 'f')
|
||||
return (c - 'a' + 10);
|
||||
Log.d("HexUtil", "The byte char is invalid: " + c);
|
||||
//throw new RuntimeException("Invalid hex char '" + c + "'");
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int toInt(byte b) {
|
||||
return b & 0xFF;
|
||||
}
|
||||
|
||||
public static int toIntFrom2Byte(byte[] b) {
|
||||
return Integer.parseInt(toHexString(b), 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拆分byte数组
|
||||
*
|
||||
* @param bytes 要拆分的数组
|
||||
* @param size 要按几个组成一份
|
||||
* @return
|
||||
*/
|
||||
public static byte[][] splitBytes(byte[] bytes, int size) {
|
||||
double splitLength = Double.parseDouble(size + "");
|
||||
int arrayLength = (int) Math.ceil(bytes.length / splitLength);
|
||||
byte[][] result = new byte[arrayLength][];
|
||||
int from, to;
|
||||
for (int i = 0; i < arrayLength; i++) {
|
||||
from = (int) (i * splitLength);
|
||||
to = (int) (from + splitLength);
|
||||
if (to > bytes.length)
|
||||
to = bytes.length;
|
||||
result[i] = Arrays.copyOfRange(bytes, from, to);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static byte[] bytesMerge(byte[]... arrs) {
|
||||
byte[] ret = new byte[byteArraysLength(arrs)];
|
||||
int pos = 0;
|
||||
for (byte[] tmp : arrs) {
|
||||
if (tmp != null && tmp.length > 0) {
|
||||
System.arraycopy(tmp, 0, ret, pos, tmp.length);
|
||||
pos += tmp.length;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static int byteArraysLength(byte[]... arrs) {
|
||||
int ret = 0;
|
||||
for (byte[] tmp : arrs) {
|
||||
if (tmp != null)
|
||||
ret += tmp.length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static int byteArrayToInt(byte[] b) {
|
||||
return (b[3] & 0xFF) |
|
||||
(b[2] & 0xFF) << 8 |
|
||||
(b[1] & 0xFF) << 16 |
|
||||
(b[0] & 0xFF) << 24;
|
||||
}
|
||||
|
||||
public static int byte2Int(byte[] data, int offset) {
|
||||
byte[] bs = new byte[4];
|
||||
for (int i = offset, j = 0; j < bs.length; i++, j++) {
|
||||
bs[j] = data[i];
|
||||
}
|
||||
return HexUtil.byteArrayToInt(bs);
|
||||
}
|
||||
|
||||
public static int hexString2Int(String hexString) {
|
||||
byte[] hexByte = hexStringToByteArray(hexString);
|
||||
return byteArrayToInt(hexByte);
|
||||
}
|
||||
|
||||
public static byte[] intToByteArray(int a) {
|
||||
return new byte[]{
|
||||
(byte) ((a >> 24) & 0xFF),
|
||||
(byte) ((a >> 16) & 0xFF),
|
||||
(byte) ((a >> 8) & 0xFF),
|
||||
(byte) (a & 0xFF)
|
||||
};
|
||||
}
|
||||
|
||||
public static byte[] hexStringToByteArray(String hexString) {
|
||||
if (hexString == null) return null;
|
||||
if (hexString.length() == 0) return null;
|
||||
int length = hexString.length();
|
||||
byte[] buffer = new byte[length / 2];
|
||||
for (int i = 0; i < length; i += 2) {
|
||||
buffer[i / 2] = (byte) ((toByte(hexString.charAt(i)) << 4) | toByte(hexString
|
||||
.charAt(i + 1)));
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static byte[] getAsciiBytes(String str) {
|
||||
return str.getBytes(Charset.forName("ascii"));
|
||||
}
|
||||
|
||||
//判断是否是十六进制格式的字符串
|
||||
public static boolean isHexString(String str) {
|
||||
if (str == null) return false;
|
||||
if (str.matches("[0-9a-fA-F]+")) return true;
|
||||
if (str.matches("0x[0-9a-fA-F]+")) return true;
|
||||
return str.matches("0x[0-9a-fA-F] +");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.dxl.iobridges;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user