Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package org.mrmalinka.usbapp;
- import android.annotation.SuppressLint;
- import android.app.PendingIntent;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.hardware.usb.UsbDevice;
- import android.hardware.usb.UsbManager;
- import android.os.Bundle;
- import android.util.Log;
- import android.webkit.JavascriptInterface;
- import android.webkit.WebSettings;
- import android.webkit.WebView;
- import android.widget.Toast;
- import android.hardware.usb.UsbDeviceConnection;
- import com.hoho.android.usbserial.driver.UsbSerialDriver;
- import com.hoho.android.usbserial.driver.UsbSerialPort;
- import androidx.appcompat.app.AppCompatActivity;
- import org.json.JSONObject;
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.util.Arrays;
- import java.util.Base64;
- public class MainActivity extends AppCompatActivity {
- private enum UsbPermission { Unknown, Requested, Granted, Denied }
- private static final String TAG = "UsbApp";
- private static final String ACTION_USB_PERMISSION = "org.mrmalinka.usbapp.USB_PERMISSION";
- private static final boolean ENABLE_DEBUG_LOGGING = true;
- private static final int MAX_PACKET_SIZE = 1024; // bytes
- private final BroadcastReceiver broadcastReceiver;
- private WebView webView;
- private UsbSerialPort usbSerialPort;
- private UsbPermission usbPermission = UsbPermission.Unknown;
- public MainActivity() {
- broadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- internalLog("Broadcast: " + action, false);
- if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
- setUsbStatus("Attached");
- try {
- connect();
- } catch (Exception e) {
- internalLog("Connect exception: " + e, true);
- setUsbStatus(e.toString());
- }
- }
- if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
- internalLog("Detached", true);
- setUsbStatus("Detached");
- disconnect();
- }
- if (ACTION_USB_PERMISSION.equals(action)) {
- if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
- usbPermission = UsbPermission.Granted;
- internalLog("Granted", true);
- } else {
- usbPermission = UsbPermission.Denied;
- internalLog("Denied", true);
- }
- try {
- setUsbStatus("Trying");
- connect();
- } catch (Exception e) {
- internalLog("Connect exception: " + e, true);
- setUsbStatus(e.toString());
- }
- }
- }
- };
- }
- private void connect() {
- UsbDevice device = null;
- UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
- for (UsbDevice v : usbManager.getDeviceList().values()) {
- if (v.getVendorId() == 0x2E8A) {
- device = v;
- }
- }
- if (device == null) {
- internalLog("Device not found", true);
- return;
- }
- // get driver
- UsbSerialDriver driver = CustomProber.getCustomProber().probeDevice(device);
- if (driver == null) {
- internalLog("No driver", true);
- return;
- }
- internalLog(driver.getPorts().size() + " ports", false);
- usbSerialPort = driver.getPorts().get(0);
- UsbDeviceConnection usbConnection = usbManager.openDevice(driver.getDevice());
- if (usbConnection == null && usbPermission == UsbPermission.Unknown && !usbManager.hasPermission(driver.getDevice())) {
- // ask for permission
- usbPermission = UsbPermission.Requested;
- Intent intent = new Intent(ACTION_USB_PERMISSION);
- intent.setPackage(getPackageName());
- PendingIntent usbPermissionIntent = PendingIntent.getBroadcast(
- this,
- 0,
- intent,
- PendingIntent.FLAG_MUTABLE
- );
- internalLog("Permission requested", false);
- usbManager.requestPermission(driver.getDevice(), usbPermissionIntent);
- return;
- }
- if (usbConnection == null) {
- if (!usbManager.hasPermission(driver.getDevice()))
- internalLog("No permission & connection", true);
- else
- internalLog("No connection", true);
- return;
- }
- StringBuilder logHist = new StringBuilder();
- for (UsbSerialPort port : driver.getPorts()) {
- try {
- port.open(usbConnection);
- port.setParameters(115200, 8, 1, UsbSerialPort.PARITY_NONE);
- usbSerialPort = port;
- internalLog("Connected to port", false);
- setUsbStatus("Active");
- return;
- } catch (Exception e) {
- logHist.append("|Fail: ").append(e);
- try { if (port.isOpen()) port.close(); } catch (Exception ignored) {}
- }
- }
- try { usbConnection.close(); } catch (Exception ignored) {}
- usbSerialPort = null;
- internalLog(logHist.toString(), true);
- }
- private void disconnect() {
- try {
- usbSerialPort.close();
- } catch (IOException e) {
- internalLog("Exception closing port: " + e, true);
- }
- usbSerialPort = null;
- }
- private void write(byte[] data) {
- if (usbSerialPort == null) {
- internalLog("Not connected", true);
- return;
- }
- try {
- // constant timeout of 1 second
- usbSerialPort.write(data, 1000);
- } catch (Exception e) {
- internalLog("Write exception: " + e, true);
- }
- }
- private byte[] read(int timeoutPer) throws IOException {
- if (usbSerialPort == null || !usbSerialPort.isOpen()) {
- throw new IOException("Not connected");
- }
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- boolean lenByteRead = false;
- int expectedTotalLen = -1;
- do {
- byte[] packet = new byte[MAX_PACKET_SIZE];
- int readLen = usbSerialPort.read(packet, timeoutPer);
- internalLog("Read: " + readLen + "| " + usbSerialPort.getDevice().getProductName(), true);
- if (readLen < 0) {
- throw new IOException("Error reading from USB port");
- }
- if (readLen == 0) {
- throw new IOException("Read timed out");
- }
- baos.write(packet, 0, readLen);
- if (!lenByteRead) {
- expectedTotalLen = (packet[0] & 0xFF);
- lenByteRead = true;
- }
- } while (baos.size() < expectedTotalLen);
- byte[] full = baos.toByteArray();
- internalLog("Data: " + Arrays.toString(full), true);
- if (full.length > expectedTotalLen)
- return Arrays.copyOf(full, expectedTotalLen);
- else return full;
- }
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setupUsb();
- setupWebView();
- webView.loadUrl("file:///android_asset/index.html");
- internalLog("onCreate completed", false);
- }
- @Override
- protected void onDestroy() {
- super.onDestroy();
- unregisterReceiver(broadcastReceiver);
- }
- private void setupUsb() {
- internalLog("Setting up usb", false);
- IntentFilter filter = new IntentFilter();
- filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
- filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
- filter.addAction(ACTION_USB_PERMISSION);
- registerReceiver(broadcastReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
- }
- @SuppressLint("SetJavaScriptEnabled")
- private void setupWebView() {
- internalLog("Setting up WebView", false);
- webView = new WebView(this);
- setContentView(webView);
- WebSettings webSettings = webView.getSettings();
- webSettings.setJavaScriptEnabled(true);
- webSettings.setDomStorageEnabled(true);
- webSettings.setAllowFileAccess(true);
- webSettings.setAllowContentAccess(true);
- webView.addJavascriptInterface(new AndroidInterface(), "Android");
- internalLog("WebView setup completed", false);
- }
- private void internalLog(String message, boolean important) {
- if (important)
- runOnUiThread(() -> Toast.makeText(this, message, Toast.LENGTH_SHORT).show());
- if (ENABLE_DEBUG_LOGGING)
- Log.d(TAG, message);
- }
- private void setUsbStatus(String status) {
- if (webView != null)
- runOnUiThread(() -> webView.evaluateJavascript(
- "javascript:window.updateUsbStatusText(" + JSONObject.quote(status) + ")",
- null
- ));
- }
- public class AndroidInterface {
- @JavascriptInterface
- public void loadAssetToWebView(String path) {
- internalLog("Loading asset: " + path, false);
- runOnUiThread(() -> webView.loadUrl("file:///android_asset/" + path));
- }
- @JavascriptInterface
- public void internalLogJS(String message) {
- internalLog(message, true);
- }
- @JavascriptInterface
- public String usbRead(int timeoutPer) {
- try {
- byte[] data = read(timeoutPer);
- return Base64.getEncoder().encodeToString(data);
- } catch (Exception e) {
- internalLog("usbRead exception: " + e, true);
- // im not sure if we can actually return errors to js so
- // a character that never appears in base64 strings is fine
- return "!";
- }
- }
- @JavascriptInterface
- public void usbWrite(String base64) {
- write(Base64.getDecoder().decode(base64));
- }
- @JavascriptInterface
- public boolean isConnected() {
- if (usbSerialPort != null)
- return usbSerialPort.isOpen();
- else return false;
- }
- }
- }
Add Comment
Please, Sign In to add comment