From 17b8ba745b3e84f96dab2d30fe57ed316c38c4c9 Mon Sep 17 00:00:00 2001 From: localhorst Date: Mon, 25 Apr 2022 14:42:06 +0200 Subject: [PATCH] first working usb serial --- app/build.gradle | 3 +- app/src/main/AndroidManifest.xml | 8 +- .../com/externgnss/MainActivity.java | 25 ++- .../com/externgnss/SerialUSB.java | 163 ++++++++++++++++++ app/src/main/res/xml/usb_serial_devices.xml | 4 + build.gradle | 4 +- 6 files changed, 202 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/hendrikschutter/com/externgnss/SerialUSB.java create mode 100644 app/src/main/res/xml/usb_serial_devices.xml diff --git a/app/build.gradle b/app/build.gradle index 0ae3888..f9c37ac 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,7 +4,7 @@ android { compileSdkVersion 30 defaultConfig { applicationId "hendrikschutter.com.externgnss" - minSdkVersion 14 + minSdkVersion 17 targetSdkVersion 30 versionCode 1 versionName "1.0" @@ -27,4 +27,5 @@ dependencies { testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + implementation 'com.github.mik3y:usb-serial-for-android:3.4.3' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 33ee0cc..3987fa6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,6 +4,7 @@ + - + + + + diff --git a/app/src/main/java/hendrikschutter/com/externgnss/MainActivity.java b/app/src/main/java/hendrikschutter/com/externgnss/MainActivity.java index 5540ee6..0861c71 100644 --- a/app/src/main/java/hendrikschutter/com/externgnss/MainActivity.java +++ b/app/src/main/java/hendrikschutter/com/externgnss/MainActivity.java @@ -2,7 +2,13 @@ package hendrikschutter.com.externgnss; import android.Manifest; import android.annotation.SuppressLint; +import android.app.PendingIntent; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbDeviceConnection; +import android.hardware.usb.UsbManager; import android.location.LocationListener; import android.location.LocationManager; import androidx.appcompat.app.AppCompatActivity; @@ -17,12 +23,20 @@ import pub.devrel.easypermissions.EasyPermissions; import static java.lang.Thread.sleep; +import com.hoho.android.usbserial.driver.UsbSerialDriver; +import com.hoho.android.usbserial.driver.UsbSerialPort; +import com.hoho.android.usbserial.driver.UsbSerialProber; + +import java.io.IOException; +import java.util.List; + public class MainActivity extends AppCompatActivity { private TextView output; private LocationManager locationManager; private boolean doRun = true; private final Context cntxToastInternGNSSUpdate = this; - final String[] perms = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.INTERNET}; + final String[] perms = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.INTERNET,}; + private static final String INTENT_ACTION_GRANT_USB = BuildConfig.APPLICATION_ID + ".GRANT_USB"; private boolean bChange = true; @Override @@ -30,6 +44,15 @@ public class MainActivity extends AppCompatActivity { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startLocationInit(); + + SerialUSB serialUSB = new SerialUSB(this); + + + + + + + } // From https://github.com/googlesamples/easypermissions diff --git a/app/src/main/java/hendrikschutter/com/externgnss/SerialUSB.java b/app/src/main/java/hendrikschutter/com/externgnss/SerialUSB.java new file mode 100644 index 0000000..eb69739 --- /dev/null +++ b/app/src/main/java/hendrikschutter/com/externgnss/SerialUSB.java @@ -0,0 +1,163 @@ +package hendrikschutter.com.externgnss; + +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.UsbDeviceConnection; +import android.hardware.usb.UsbManager; +import android.util.Log; + +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 java.io.IOException; + +public class SerialUSB implements SerialInputOutputManager.Listener{ + + private MainActivity mainActivity = null; + + private enum UsbPermission { Unknown, Requested, Granted, Denied } + + private static final String INTENT_ACTION_GRANT_USB = BuildConfig.APPLICATION_ID + ".GRANT_USB"; + private static final int WRITE_WAIT_MILLIS = 2000; + private static final int READ_WAIT_MILLIS = 2000; + + private int deviceId, portNum, baudRate; + private boolean withIoManager; + + private BroadcastReceiver broadcastReceiver = null; + //private final Handler mainLooper; + //private TextView receiveText; + //private ControlLines controlLines; + + private SerialInputOutputManager usbIoManager; + private UsbSerialPort usbSerialPort; + private UsbPermission usbPermission = UsbPermission.Unknown; + private boolean connected = false; + + public SerialUSB(MainActivity mainActivity){ + this.mainActivity = mainActivity; + + // Find all available drivers from attached devices. + UsbManager usbManager = (UsbManager) this.mainActivity.getSystemService(Context.USB_SERVICE); + UsbSerialProber usbDefaultProber = UsbSerialProber.getDefaultProber(); + + if (usbManager.getDeviceList().values().size() > 0){ + UsbDevice device = (UsbDevice) usbManager.getDeviceList().values().toArray()[0]; + UsbSerialDriver driver = usbDefaultProber.probeDevice(device); + if(driver == null) { + Log.i("SerialUSB", "driver is null"); + } + if(driver != null) { + Log.i("SerialUSB", "ExternGNSS: device/driver found!"); + this.deviceId = device.getDeviceId(); + this.portNum = 0; + this.baudRate = 9600; + this.withIoManager = true; + } + } + + + broadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if(INTENT_ACTION_GRANT_USB.equals(intent.getAction())) { + usbPermission = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false) ? UsbPermission.Granted : UsbPermission.Denied; + connect(); + } else { + Log.i("SerialUSB", "USB permissions are not set"); + } + } + }; + connect(); + this.mainActivity.registerReceiver(broadcastReceiver, new IntentFilter(INTENT_ACTION_GRANT_USB)); + } + + private void connect() { + Log.i("connect", "starting to connect ..."); + UsbDevice device = null; + UsbManager usbManager = (UsbManager) this.mainActivity.getSystemService(Context.USB_SERVICE); + for(UsbDevice v : usbManager.getDeviceList().values()) + if(v.getDeviceId() == deviceId) + device = v; + if(device == null) { + Log.i("connect", "connection failed: device not found"); + return; + } + UsbSerialDriver driver = UsbSerialProber.getDefaultProber().probeDevice(device); + /* + if(driver == null) { + driver = CustomProber.getCustomProber().probeDevice(device); + } + */ + if(driver == null) { + Log.i("connect", "connection failed: no driver for device"); + return; + } + if(driver.getPorts().size() < portNum) { + Log.i("connect", "connection failed: not enough ports at device"); + return; + } + usbSerialPort = driver.getPorts().get(portNum); + UsbDeviceConnection usbConnection = usbManager.openDevice(driver.getDevice()); + if(usbConnection == null && usbPermission == UsbPermission.Unknown && !usbManager.hasPermission(driver.getDevice())) { + usbPermission = UsbPermission.Requested; + PendingIntent usbPermissionIntent = PendingIntent.getBroadcast(this.mainActivity, 0, new Intent(INTENT_ACTION_GRANT_USB), 0); + usbManager.requestPermission(driver.getDevice(), usbPermissionIntent); + return; + } + if(usbConnection == null) { + if (!usbManager.hasPermission(driver.getDevice())) + Log.i("connect", "connection failed: permission denied"); + else + Log.i("connect", "connection failed: open failed"); + return; + } + + try { + usbSerialPort.open(usbConnection); + usbSerialPort.setParameters(baudRate, 8, 1, UsbSerialPort.PARITY_NONE); + if(withIoManager) { + usbIoManager = new SerialInputOutputManager(usbSerialPort, this); + usbIoManager.start(); + } + + Log.i("connect", "connected"); + connected = true; + //controlLines.start(); + } catch (Exception e) { + Log.i("connect", "connection failed: " + e.getMessage()); + disconnect(); + } + } + + private void disconnect() { + connected = false; + //controlLines.stop(); + if(usbIoManager != null) { + usbIoManager.setListener(null); + usbIoManager.stop(); + } + usbIoManager = null; + try { + usbSerialPort.close(); + } catch (IOException ignored) {} + usbSerialPort = null; + } + + @Override + public void onNewData(byte[] data) { + Log.i("connect", "received data: " + data.length); + } + + @Override + public void onRunError(Exception e) { + Log.e("SerialUSB", "runtime error: " + e.getMessage()); + this.disconnect(); + } +} diff --git a/app/src/main/res/xml/usb_serial_devices.xml b/app/src/main/res/xml/usb_serial_devices.xml new file mode 100644 index 0000000..b7bba29 --- /dev/null +++ b/app/src/main/res/xml/usb_serial_devices.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 30178be..a44dd51 100644 --- a/build.gradle +++ b/build.gradle @@ -6,8 +6,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.1.2' - + classpath 'com.android.tools.build:gradle:7.1.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } @@ -17,6 +16,7 @@ allprojects { repositories { google() mavenCentral() + maven { url 'https://jitpack.io' } } }