From 2354f93354753596fc2f216fa34499b22d41c23e Mon Sep 17 00:00:00 2001 From: kai-morich Date: Mon, 23 Mar 2020 20:11:39 +0100 Subject: [PATCH] modernize example app --- .idea/misc.xml | 2 +- README.md | 4 +- gradle.properties | 2 + usbSerialExamples/build.gradle | 7 + .../src/main/AndroidManifest.xml | 34 +- .../usbserial/examples/CustomProber.java | 21 ++ .../examples/DeviceListActivity.java | 233 ------------- .../usbserial/examples/DevicesFragment.java | 151 +++++++++ .../usbserial/examples/MainActivity.java | 45 +++ .../examples/SerialConsoleActivity.java | 230 ------------- .../usbserial/examples/TerminalFragment.java | 315 ++++++++++++++++++ .../hoho/android/usbserial/util/HexDump.java | 41 +-- .../main/res/drawable-hdpi/ic_launcher.png | Bin 4147 -> 0 bytes .../main/res/drawable-ldpi/ic_launcher.png | Bin 1723 -> 0 bytes .../main/res/drawable-mdpi/ic_launcher.png | Bin 2574 -> 0 bytes .../res/drawable/ic_delete_white_24dp.xml | 9 + .../main/res/drawable/ic_send_white_24dp.xml | 9 + .../src/main/res/layout/activity_main.xml | 28 ++ .../main/res/layout/device_list_header.xml | 17 + .../src/main/res/layout/device_list_item.xml | 26 ++ .../src/main/res/layout/fragment_terminal.xml | 122 +++++++ .../src/main/res/layout/main.xml | 50 --- .../src/main/res/layout/serial_console.xml | 54 --- .../src/main/res/menu/menu_devices.xml | 9 + .../src/main/res/menu/menu_terminal.xml | 9 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1475 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 895 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 1650 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 2462 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 3424 bytes .../src/main/res/values/arrays.xml | 10 + .../src/main/res/values/colors.xml | 10 + .../src/main/res/values/strings.xml | 10 +- .../src/main/res/values/styles.xml | 7 + 34 files changed, 834 insertions(+), 621 deletions(-) create mode 100644 gradle.properties create mode 100644 usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/CustomProber.java delete mode 100644 usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/DeviceListActivity.java create mode 100644 usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/DevicesFragment.java create mode 100644 usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/MainActivity.java delete mode 100644 usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/SerialConsoleActivity.java create mode 100644 usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/TerminalFragment.java delete mode 100644 usbSerialExamples/src/main/res/drawable-hdpi/ic_launcher.png delete mode 100644 usbSerialExamples/src/main/res/drawable-ldpi/ic_launcher.png delete mode 100644 usbSerialExamples/src/main/res/drawable-mdpi/ic_launcher.png create mode 100644 usbSerialExamples/src/main/res/drawable/ic_delete_white_24dp.xml create mode 100644 usbSerialExamples/src/main/res/drawable/ic_send_white_24dp.xml create mode 100644 usbSerialExamples/src/main/res/layout/activity_main.xml create mode 100644 usbSerialExamples/src/main/res/layout/device_list_header.xml create mode 100644 usbSerialExamples/src/main/res/layout/device_list_item.xml create mode 100644 usbSerialExamples/src/main/res/layout/fragment_terminal.xml delete mode 100644 usbSerialExamples/src/main/res/layout/main.xml delete mode 100644 usbSerialExamples/src/main/res/layout/serial_console.xml create mode 100644 usbSerialExamples/src/main/res/menu/menu_devices.xml create mode 100644 usbSerialExamples/src/main/res/menu/menu_terminal.xml create mode 100644 usbSerialExamples/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 usbSerialExamples/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 usbSerialExamples/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 usbSerialExamples/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 usbSerialExamples/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 usbSerialExamples/src/main/res/values/arrays.xml create mode 100644 usbSerialExamples/src/main/res/values/colors.xml create mode 100644 usbSerialExamples/src/main/res/values/styles.xml diff --git a/.idea/misc.xml b/.idea/misc.xml index 047238c..1011831 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -39,7 +39,7 @@ - + diff --git a/README.md b/README.md index cacaad0..6333c0a 100644 --- a/README.md +++ b/README.md @@ -96,12 +96,12 @@ and finally: port.close(); ``` - For a simple example, see [UsbSerialExamples](https://github.com/mik3y/usb-serial-for-android/blob/master/usbSerialExamples) folder in this project. -For a more complete example, see separate github project +For a more complete example with background service to stay connected while +the app is not visible or rotating, see separate github project [SimpleUsbTerminal](https://github.com/kai-morich/SimpleUsbTerminal). ## Probing for Unrecognized Devices diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..399f577 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,2 @@ +#android.enableJetifier=true +android.useAndroidX=true diff --git a/usbSerialExamples/build.gradle b/usbSerialExamples/build.gradle index 5f27979..7fdae7e 100644 --- a/usbSerialExamples/build.gradle +++ b/usbSerialExamples/build.gradle @@ -4,6 +4,11 @@ android { compileSdkVersion 28 buildToolsVersion '28.0.3' + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + defaultConfig { minSdkVersion 17 targetSdkVersion 28 @@ -21,4 +26,6 @@ android { dependencies { implementation project(':usbSerialForAndroid') + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'com.google.android.material:material:1.1.0' } diff --git a/usbSerialExamples/src/main/AndroidManifest.xml b/usbSerialExamples/src/main/AndroidManifest.xml index efa205f..d264658 100644 --- a/usbSerialExamples/src/main/AndroidManifest.xml +++ b/usbSerialExamples/src/main/AndroidManifest.xml @@ -1,37 +1,33 @@ - - + xmlns:tools="http://schemas.android.com/tools" + package="com.hoho.android.usbserial.examples"> + + android:icon="@mipmap/ic_launcher" + android:label="@string/app_name" + android:theme="@style/AppTheme" + tools:ignore="AllowBackup,GoogleAppIndexingWarning"> + + android:launchMode="singleTask" + android:windowSoftInputMode="stateHidden|adjustResize"> - - - - - - - \ No newline at end of file + diff --git a/usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/CustomProber.java b/usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/CustomProber.java new file mode 100644 index 0000000..0447317 --- /dev/null +++ b/usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/CustomProber.java @@ -0,0 +1,21 @@ +package com.hoho.android.usbserial.examples; + +import com.hoho.android.usbserial.driver.CdcAcmSerialDriver; +import com.hoho.android.usbserial.driver.ProbeTable; +import com.hoho.android.usbserial.driver.UsbSerialProber; + +/** + * add devices here, that are not known to DefaultProber + * + * if the App should auto start for these devices, also + * add IDs to app/src/main/res/xml/device_filter.xml + */ +class CustomProber { + + static UsbSerialProber getCustomProber() { + ProbeTable customTable = new ProbeTable(); + customTable.addProduct(0x16d0, 0x087e, CdcAcmSerialDriver.class); // e.g. Digispark CDC + return new UsbSerialProber(customTable); + } + +} diff --git a/usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/DeviceListActivity.java b/usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/DeviceListActivity.java deleted file mode 100644 index a69a3c0..0000000 --- a/usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/DeviceListActivity.java +++ /dev/null @@ -1,233 +0,0 @@ -/* Copyright 2011-2013 Google Inc. - * Copyright 2013 mike wakerly - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - * - * Project home page: https://github.com/mik3y/usb-serial-for-android - */ - -package com.hoho.android.usbserial.examples; - -import android.app.Activity; -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.AsyncTask; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.SystemClock; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.ListView; -import android.widget.ProgressBar; -import android.widget.TextView; -import android.widget.Toast; -import android.widget.TwoLineListItem; - -import com.hoho.android.usbserial.driver.UsbSerialDriver; -import com.hoho.android.usbserial.driver.UsbSerialPort; -import com.hoho.android.usbserial.driver.UsbSerialProber; - -import java.util.ArrayList; -import java.util.List; - -/** - * Shows a {@link ListView} of available USB devices. - * - * @author mike wakerly (opensource@hoho.com) - */ -public class DeviceListActivity extends Activity { - - private final String TAG = DeviceListActivity.class.getSimpleName(); - - private UsbManager mUsbManager; - private UsbSerialPort mSerialPort; - private ListView mListView; - private TextView mProgressBarTitle; - private ProgressBar mProgressBar; - - private static final int MESSAGE_REFRESH = 101; - private static final long REFRESH_TIMEOUT_MILLIS = 5000; - public static final String INTENT_ACTION_GRANT_USB = BuildConfig.APPLICATION_ID + ".GRANT_USB"; - - private final Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MESSAGE_REFRESH: - refreshDeviceList(); - mHandler.sendEmptyMessageDelayed(MESSAGE_REFRESH, REFRESH_TIMEOUT_MILLIS); - break; - default: - super.handleMessage(msg); - break; - } - } - - }; - private BroadcastReceiver mUsbReceiver; - - private List mEntries = new ArrayList(); - private ArrayAdapter mAdapter; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.main); - final Context context = this; - - mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE); - mListView = findViewById(R.id.deviceList); - mProgressBar = findViewById(R.id.progressBar); - mProgressBarTitle = findViewById(R.id.progressBarTitle); - - mUsbReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if(intent.getAction().equals(INTENT_ACTION_GRANT_USB)) { - if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { - showConsoleActivity(mSerialPort); - } else { - Toast.makeText(context, "USB permission denied", Toast.LENGTH_SHORT).show(); - } - } - } - }; - - mAdapter = new ArrayAdapter(this, - android.R.layout.simple_expandable_list_item_2, mEntries) { - @Override - public View getView(int position, View convertView, ViewGroup parent) { - final TwoLineListItem row; - if (convertView == null){ - final LayoutInflater inflater = - (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); - row = (TwoLineListItem) inflater.inflate(android.R.layout.simple_list_item_2, null); - } else { - row = (TwoLineListItem) convertView; - } - - final UsbSerialPort port = mEntries.get(position); - final UsbSerialDriver driver = port.getDriver(); - final UsbDevice device = driver.getDevice(); - - final String title = String.format("Vendor %4X Product %4X", device.getVendorId(), device.getProductId()); - row.getText1().setText(title); - - final String subtitle = driver.getClass().getSimpleName(); - row.getText2().setText(subtitle); - - return row; - } - - }; - mListView.setAdapter(mAdapter); - - mListView.setOnItemClickListener(new ListView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - Log.d(TAG, "Pressed item " + position); - if (position >= mEntries.size()) { - Log.w(TAG, "Illegal position."); - return; - } - - mSerialPort = mEntries.get(position); - UsbDevice device = mSerialPort.getDriver().getDevice(); - if (!mUsbManager.hasPermission(device)) { - PendingIntent usbPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(INTENT_ACTION_GRANT_USB), 0); - mUsbManager.requestPermission(device, usbPermissionIntent); - } else { - showConsoleActivity(mSerialPort); - } - } - }); - } - - @Override - protected void onResume() { - super.onResume(); - mHandler.sendEmptyMessage(MESSAGE_REFRESH); - registerReceiver(mUsbReceiver, new IntentFilter(INTENT_ACTION_GRANT_USB)); - } - - @Override - protected void onPause() { - super.onPause(); - mHandler.removeMessages(MESSAGE_REFRESH); - unregisterReceiver(mUsbReceiver); - } - - private void refreshDeviceList() { - showProgressBar(); - - new AsyncTask>() { - @Override - protected List doInBackground(Void... params) { - Log.d(TAG, "Refreshing device list ..."); - SystemClock.sleep(1000); - - final List drivers = - UsbSerialProber.getDefaultProber().findAllDrivers(mUsbManager); - - final List result = new ArrayList(); - for (final UsbSerialDriver driver : drivers) { - final List ports = driver.getPorts(); - Log.d(TAG, String.format("+ %s: %s port%s", - driver, Integer.valueOf(ports.size()), ports.size() == 1 ? "" : "s")); - result.addAll(ports); - } - - return result; - } - - @Override - protected void onPostExecute(List result) { - mEntries.clear(); - mEntries.addAll(result); - mAdapter.notifyDataSetChanged(); - mProgressBarTitle.setText( - String.format("%s device(s) found",Integer.valueOf(mEntries.size()))); - hideProgressBar(); - Log.d(TAG, "Done refreshing, " + mEntries.size() + " entries found."); - } - - }.execute((Void) null); - } - - private void showProgressBar() { - mProgressBar.setVisibility(View.VISIBLE); - mProgressBarTitle.setText(R.string.refreshing); - } - - private void hideProgressBar() { - mProgressBar.setVisibility(View.INVISIBLE); - } - - private void showConsoleActivity(UsbSerialPort port) { - SerialConsoleActivity.show(this, port); - } - -} diff --git a/usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/DevicesFragment.java b/usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/DevicesFragment.java new file mode 100644 index 0000000..adfc38b --- /dev/null +++ b/usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/DevicesFragment.java @@ -0,0 +1,151 @@ +package com.hoho.android.usbserial.examples; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbManager; +import android.os.Bundle; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.ListFragment; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; + +import com.hoho.android.usbserial.driver.UsbSerialDriver; +import com.hoho.android.usbserial.driver.UsbSerialProber; + +import java.util.ArrayList; +import java.util.Locale; + +public class DevicesFragment extends ListFragment { + + class ListItem { + UsbDevice device; + int port; + UsbSerialDriver driver; + + ListItem(UsbDevice device, int port, UsbSerialDriver driver) { + this.device = device; + this.port = port; + this.driver = driver; + } + } + + private ArrayList listItems = new ArrayList<>(); + private ArrayAdapter listAdapter; + private int baudRate = 19200; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + listAdapter = new ArrayAdapter(getActivity(), 0, listItems) { + @Override + public View getView(int position, View view, ViewGroup parent) { + ListItem item = listItems.get(position); + if (view == null) + view = getActivity().getLayoutInflater().inflate(R.layout.device_list_item, parent, false); + TextView text1 = view.findViewById(R.id.text1); + TextView text2 = view.findViewById(R.id.text2); + if(item.driver == null) + text1.setText(""); + else if(item.driver.getPorts().size() == 1) + text1.setText(item.driver.getClass().getSimpleName().replace("SerialDriver","")); + else + text1.setText(item.driver.getClass().getSimpleName().replace("SerialDriver","")+", Port "+item.port); + text2.setText(String.format(Locale.US, "Vendor %04X, Product %04X", item.device.getVendorId(), item.device.getProductId())); + return view; + } + }; + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + setListAdapter(null); + View header = getActivity().getLayoutInflater().inflate(R.layout.device_list_header, null, false); + getListView().addHeaderView(header, null, false); + setEmptyText(""); + ((TextView) getListView().getEmptyView()).setTextSize(18); + setListAdapter(listAdapter); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.menu_devices, menu); + } + + @Override + public void onResume() { + super.onResume(); + refresh(); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int id = item.getItemId(); + if(id == R.id.refresh) { + refresh(); + return true; + } else if (id ==R.id.baud_rate) { + final String[] baudRates = getResources().getStringArray(R.array.baud_rates); + int pos = java.util.Arrays.asList(baudRates).indexOf(String.valueOf(baudRate)); + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle("Baud rate"); + builder.setSingleChoiceItems(baudRates, pos, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int item) { + baudRate = Integer.valueOf(baudRates[item]); + dialog.dismiss(); + } + }); + builder.create().show(); + return true; + } else { + return super.onOptionsItemSelected(item); + } + } + + void refresh() { + UsbManager usbManager = (UsbManager) getActivity().getSystemService(Context.USB_SERVICE); + UsbSerialProber usbDefaultProber = UsbSerialProber.getDefaultProber(); + UsbSerialProber usbCustomProber = CustomProber.getCustomProber(); + listItems.clear(); + for(UsbDevice device : usbManager.getDeviceList().values()) { + UsbSerialDriver driver = usbDefaultProber.probeDevice(device); + if(driver == null) { + driver = usbCustomProber.probeDevice(device); + } + if(driver != null) { + for(int port = 0; port < driver.getPorts().size(); port++) + listItems.add(new ListItem(device, port, driver)); + } else { + listItems.add(new ListItem(device, 0, null)); + } + } + listAdapter.notifyDataSetChanged(); + } + + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + ListItem item = listItems.get(position-1); + if(item.driver == null) { + Toast.makeText(getActivity(), "no driver", Toast.LENGTH_SHORT).show(); + } else { + Bundle args = new Bundle(); + args.putInt("device", item.device.getDeviceId()); + args.putInt("port", item.port); + args.putInt("baud", baudRate); + Fragment fragment = new TerminalFragment(); + fragment.setArguments(args); + getFragmentManager().beginTransaction().replace(R.id.fragment, fragment, "terminal").addToBackStack(null).commit(); + } + } + +} diff --git a/usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/MainActivity.java b/usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/MainActivity.java new file mode 100644 index 0000000..27d88e5 --- /dev/null +++ b/usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/MainActivity.java @@ -0,0 +1,45 @@ +package com.hoho.android.usbserial.examples; + +import android.content.Intent; +import android.os.Bundle; +import androidx.fragment.app.FragmentManager; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; + +public class MainActivity extends AppCompatActivity implements FragmentManager.OnBackStackChangedListener { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + getSupportFragmentManager().addOnBackStackChangedListener(this); + if (savedInstanceState == null) + getSupportFragmentManager().beginTransaction().add(R.id.fragment, new DevicesFragment(), "devices").commit(); + else + onBackStackChanged(); + } + + @Override + public void onBackStackChanged() { + getSupportActionBar().setDisplayHomeAsUpEnabled(getSupportFragmentManager().getBackStackEntryCount()>0); + } + + @Override + public boolean onSupportNavigateUp() { + onBackPressed(); + return true; + } + + @Override + protected void onNewIntent(Intent intent) { + if(intent.getAction().equals("android.hardware.usb.action.USB_DEVICE_ATTACHED")) { + TerminalFragment terminal = (TerminalFragment)getSupportFragmentManager().findFragmentByTag("terminal"); + if (terminal != null) + terminal.status("USB device detected"); + } + super.onNewIntent(intent); + } + +} diff --git a/usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/SerialConsoleActivity.java b/usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/SerialConsoleActivity.java deleted file mode 100644 index 1a7d71d..0000000 --- a/usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/SerialConsoleActivity.java +++ /dev/null @@ -1,230 +0,0 @@ -/* Copyright 2011-2013 Google Inc. - * Copyright 2013 mike wakerly - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - * - * Project home page: https://github.com/mik3y/usb-serial-for-android - */ - -package com.hoho.android.usbserial.examples; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.hardware.usb.UsbDeviceConnection; -import android.hardware.usb.UsbManager; -import android.os.Bundle; -import android.util.Log; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.ScrollView; -import android.widget.TextView; - -import com.hoho.android.usbserial.driver.UsbSerialPort; -import com.hoho.android.usbserial.util.HexDump; -import com.hoho.android.usbserial.util.SerialInputOutputManager; - -import java.io.IOException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * Monitors a single {@link UsbSerialPort} instance, showing all data - * received. - * - * @author mike wakerly (opensource@hoho.com) - */ -public class SerialConsoleActivity extends Activity { - - private final String TAG = SerialConsoleActivity.class.getSimpleName(); - - /** - * Driver instance, passed in statically via - * {@link #show(Context, UsbSerialPort)}. - * - *

- * This is a devious hack; it'd be cleaner to re-create the driver using - * arguments passed in with the {@link #startActivity(Intent)} intent. We - * can get away with it because both activities will run in the same - * process, and this is a simple demo. - */ - private static UsbSerialPort sPort = null; - - private TextView mTitleTextView; - private TextView mDumpTextView; - private ScrollView mScrollView; - private CheckBox chkDTR; - private CheckBox chkRTS; - - private final ExecutorService mExecutor = Executors.newSingleThreadExecutor(); - - private SerialInputOutputManager mSerialIoManager; - - private final SerialInputOutputManager.Listener mListener = - new SerialInputOutputManager.Listener() { - - @Override - public void onRunError(Exception e) { - Log.d(TAG, "Runner stopped."); - } - - @Override - public void onNewData(final byte[] data) { - SerialConsoleActivity.this.runOnUiThread(new Runnable() { - @Override - public void run() { - SerialConsoleActivity.this.updateReceivedData(data); - } - }); - } - }; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.serial_console); - mTitleTextView = (TextView) findViewById(R.id.demoTitle); - mDumpTextView = (TextView) findViewById(R.id.consoleText); - mScrollView = (ScrollView) findViewById(R.id.demoScroller); - chkDTR = (CheckBox) findViewById(R.id.checkBoxDTR); - chkRTS = (CheckBox) findViewById(R.id.checkBoxRTS); - - chkDTR.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - try { - sPort.setDTR(isChecked); - }catch (IOException x){} - } - }); - - chkRTS.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - try { - sPort.setRTS(isChecked); - }catch (IOException x){} - } - }); - - } - - - @Override - protected void onPause() { - super.onPause(); - stopIoManager(); - if (sPort != null) { - try { - sPort.close(); - } catch (IOException e) { - // Ignore. - } - sPort = null; - } - finish(); - } - - void showStatus(TextView theTextView, String theLabel, boolean theValue){ - String msg = theLabel + ": " + (theValue ? "enabled" : "disabled") + "\n"; - theTextView.append(msg); - } - - @Override - protected void onResume() { - super.onResume(); - Log.d(TAG, "Resumed, port=" + sPort); - if (sPort == null) { - mTitleTextView.setText("No serial device."); - } else { - final UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE); - - UsbDeviceConnection connection = usbManager.openDevice(sPort.getDriver().getDevice()); - if (connection == null) { - mTitleTextView.setText("Opening device failed"); - return; - } - - try { - sPort.open(connection); - sPort.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE); - - showStatus(mDumpTextView, "CD - Carrier Detect", sPort.getCD()); - showStatus(mDumpTextView, "CTS - Clear To Send", sPort.getCTS()); - showStatus(mDumpTextView, "DSR - Data Set Ready", sPort.getDSR()); - showStatus(mDumpTextView, "DTR - Data Terminal Ready", sPort.getDTR()); - showStatus(mDumpTextView, "DSR - Data Set Ready", sPort.getDSR()); - showStatus(mDumpTextView, "RI - Ring Indicator", sPort.getRI()); - showStatus(mDumpTextView, "RTS - Request To Send", sPort.getRTS()); - - } catch (IOException e) { - Log.e(TAG, "Error setting up device: " + e.getMessage(), e); - mTitleTextView.setText("Error opening device: " + e.getMessage()); - try { - sPort.close(); - } catch (IOException e2) { - // Ignore. - } - sPort = null; - return; - } - mTitleTextView.setText("Serial device: " + sPort.getClass().getSimpleName()); - } - onDeviceStateChange(); - } - - private void stopIoManager() { - if (mSerialIoManager != null) { - Log.i(TAG, "Stopping io manager .."); - mSerialIoManager.stop(); - mSerialIoManager = null; - } - } - - private void startIoManager() { - if (sPort != null) { - Log.i(TAG, "Starting io manager .."); - mSerialIoManager = new SerialInputOutputManager(sPort, mListener); - mExecutor.submit(mSerialIoManager); - } - } - - private void onDeviceStateChange() { - stopIoManager(); - startIoManager(); - } - - private void updateReceivedData(byte[] data) { - final String message = "Read " + data.length + " bytes: \n" - + HexDump.dumpHexString(data) + "\n\n"; - mDumpTextView.append(message); - mScrollView.smoothScrollTo(0, mDumpTextView.getBottom()); - } - - /** - * Starts the activity, using the supplied driver instance. - * - * @param context - * @param driver - */ - static void show(Context context, UsbSerialPort port) { - sPort = port; - final Intent intent = new Intent(context, SerialConsoleActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY); - context.startActivity(intent); - } - -} diff --git a/usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/TerminalFragment.java b/usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/TerminalFragment.java new file mode 100644 index 0000000..e4b18f7 --- /dev/null +++ b/usbSerialExamples/src/main/java/com/hoho/android/usbserial/examples/TerminalFragment.java @@ -0,0 +1,315 @@ +package com.hoho.android.usbserial.examples; + +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.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.method.ScrollingMovementMethod; +import android.text.style.ForegroundColorSpan; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import android.widget.Toast; +import android.widget.ToggleButton; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +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.HexDump; +import com.hoho.android.usbserial.util.SerialInputOutputManager; + +import java.io.IOException; +import java.util.concurrent.Executors; + +public class TerminalFragment extends Fragment implements SerialInputOutputManager.Listener { + + 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 int deviceId, portNum, baudRate; + + private BroadcastReceiver broadcastReceiver; + private Handler mainLooper; + private TextView receiveText; + private ControlLines controlLines; + + private SerialInputOutputManager usbIoManager; + private UsbSerialPort usbSerialPort; + private UsbPermission usbPermission = UsbPermission.Unknown; + private boolean connected = false; + + public TerminalFragment() { + broadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if(intent.getAction().equals(INTENT_ACTION_GRANT_USB)) { + usbPermission = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false) + ? UsbPermission.Granted : UsbPermission.Denied; + connect(); + } + } + }; + mainLooper = new Handler(Looper.getMainLooper()); + } + + /* + * Lifecycle + */ + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + setRetainInstance(true); + deviceId = getArguments().getInt("device"); + portNum = getArguments().getInt("port"); + baudRate = getArguments().getInt("baud"); + } + + @Override + public void onResume() { + super.onResume(); + getActivity().registerReceiver(broadcastReceiver, new IntentFilter(INTENT_ACTION_GRANT_USB)); + + if(usbPermission == UsbPermission.Unknown || usbPermission == UsbPermission.Granted) + mainLooper.post(this::connect); + } + + @Override + public void onPause() { + if(connected) { + status("disconnected"); + disconnect(); + } + getActivity().unregisterReceiver(broadcastReceiver); + super.onPause(); + } + + /* + * UI + */ + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_terminal, container, false); + receiveText = view.findViewById(R.id.receive_text); // TextView performance decreases with number of spans + receiveText.setTextColor(getResources().getColor(R.color.colorRecieveText)); // set as default color to reduce number of spans + receiveText.setMovementMethod(ScrollingMovementMethod.getInstance()); + TextView sendText = view.findViewById(R.id.send_text); + View sendBtn = view.findViewById(R.id.send_btn); + sendBtn.setOnClickListener(v -> send(sendText.getText().toString())); + controlLines = new ControlLines(view); + return view; + } + + @Override + public void onCreateOptionsMenu(@NonNull Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.menu_terminal, menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int id = item.getItemId(); + if (id == R.id.clear) { + receiveText.setText(""); + return true; + } else { + return super.onOptionsItemSelected(item); + } + } + + /* + * Serial + */ + @Override + public void onNewData(byte[] data) { + mainLooper.post(() -> { + receive(data); + }); + } + + @Override + public void onRunError(Exception e) { + mainLooper.post(() -> { + status("connection lost: " + e.getMessage()); + disconnect(); + }); + } + + /* + * Serial + UI + */ + private void connect() { + UsbDevice device = null; + UsbManager usbManager = (UsbManager) getActivity().getSystemService(Context.USB_SERVICE); + for(UsbDevice v : usbManager.getDeviceList().values()) + if(v.getDeviceId() == deviceId) + device = v; + if(device == null) { + status("connection failed: device not found"); + return; + } + UsbSerialDriver driver = UsbSerialProber.getDefaultProber().probeDevice(device); + if(driver == null) { + driver = CustomProber.getCustomProber().probeDevice(device); + } + if(driver == null) { + status("connection failed: no driver for device"); + return; + } + if(driver.getPorts().size() < portNum) { + status("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(getActivity(), 0, new Intent(INTENT_ACTION_GRANT_USB), 0); + usbManager.requestPermission(driver.getDevice(), usbPermissionIntent); + return; + } + if(usbConnection == null) { + if (!usbManager.hasPermission(driver.getDevice())) + status("connection failed: permission denied"); + else + status("connection failed: open failed"); + return; + } + + try { + usbSerialPort.open(usbConnection); + usbSerialPort.setParameters(baudRate, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE); + usbIoManager = new SerialInputOutputManager(usbSerialPort, this); + Executors.newSingleThreadExecutor().submit(usbIoManager); + status("connected"); + connected = true; + controlLines.start(); + } catch (Exception e) { + status("connection failed: " + e.getMessage()); + disconnect(); + } + } + + private void disconnect() { + connected = false; + controlLines.stop(); + if(usbIoManager != null) + usbIoManager.stop(); + usbIoManager = null; + try { + usbSerialPort.close(); + } catch (IOException ignored) {} + usbSerialPort = null; + } + + private void send(String str) { + if(!connected) { + Toast.makeText(getActivity(), "not connected", Toast.LENGTH_SHORT).show(); + return; + } + try { + byte[] data = (str + '\n').getBytes(); + SpannableStringBuilder spn = new SpannableStringBuilder(); + spn.append("send " + data.length + " bytes:\n"); + spn.append(HexDump.dumpHexString(data)+"\n"); + spn.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorSendText)), 0, spn.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + receiveText.append(spn); + usbSerialPort.write(data, WRITE_WAIT_MILLIS); + } catch (Exception e) { + onRunError(e); + } + } + + private void receive(byte[] data) { + String str = new String(data); + SpannableStringBuilder spn = new SpannableStringBuilder(); + spn.append("receive " + data.length + " bytes:\n"); + spn.append(HexDump.dumpHexString(data)+"\n"); + receiveText.append(spn); + } + + void status(String str) { + SpannableStringBuilder spn = new SpannableStringBuilder(str+'\n'); + spn.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorStatusText)), 0, spn.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + receiveText.append(spn); + } + + class ControlLines { + private static final int refreshInterval = 200; // msec + + private Runnable runnable; + private ToggleButton rtsBtn, ctsBtn, dtrBtn, dsrBtn, cdBtn, riBtn; + + ControlLines(View view) { + runnable = this::start; // w/o explicit Runnable, a new lambda would be created on each postDelayed, which would not be found again by removeCallbacks + + rtsBtn = view.findViewById(R.id.controlLineRts); + ctsBtn = view.findViewById(R.id.controlLineCts); + dtrBtn = view.findViewById(R.id.controlLineDtr); + dsrBtn = view.findViewById(R.id.controlLineDsr); + cdBtn = view.findViewById(R.id.controlLineCd); + riBtn = view.findViewById(R.id.controlLineRi); + rtsBtn.setOnClickListener(this::toggle); + dtrBtn.setOnClickListener(this::toggle); + } + + private void toggle(View v) { + ToggleButton btn = (ToggleButton) v; + if (!connected) { + btn.setChecked(!btn.isChecked()); + Toast.makeText(getActivity(), "not connected", Toast.LENGTH_SHORT).show(); + return; + } + String ctrl = ""; + try { + if (btn.equals(rtsBtn)) { ctrl = "RTS"; usbSerialPort.setRTS(btn.isChecked()); } + if (btn.equals(dtrBtn)) { ctrl = "DTR"; usbSerialPort.setDTR(btn.isChecked()); } + } catch (IOException e) { + status("set" + ctrl + " failed: " + e.getMessage()); + } + } + + private boolean refresh() { + String ctrl = ""; + try { + ctrl = "RTS"; rtsBtn.setChecked(usbSerialPort.getRTS()); + ctrl = "CTS"; ctsBtn.setChecked(usbSerialPort.getCTS()); + ctrl = "DTR"; dtrBtn.setChecked(usbSerialPort.getDTR()); + ctrl = "DSR"; dsrBtn.setChecked(usbSerialPort.getDSR()); + ctrl = "CD"; cdBtn.setChecked(usbSerialPort.getCD()); + ctrl = "RI"; riBtn.setChecked(usbSerialPort.getRI()); + } catch (IOException e) { + status("get" + ctrl + " failed: " + e.getMessage() + " -> stopped control line refresh"); + return false; + } + return true; + } + + void start() { + if (connected && refresh()) + mainLooper.postDelayed(runnable, refreshInterval); + } + + void stop() { + mainLooper.removeCallbacks(runnable); + } + } +} diff --git a/usbSerialExamples/src/main/java/com/hoho/android/usbserial/util/HexDump.java b/usbSerialExamples/src/main/java/com/hoho/android/usbserial/util/HexDump.java index 54f6e42..e05d71c 100644 --- a/usbSerialExamples/src/main/java/com/hoho/android/usbserial/util/HexDump.java +++ b/usbSerialExamples/src/main/java/com/hoho/android/usbserial/util/HexDump.java @@ -16,6 +16,8 @@ package com.hoho.android.usbserial.util; +import java.security.InvalidParameterException; + /** * Clone of Android's HexDump class, for use in debugging. Cosmetic changes * only. @@ -32,17 +34,12 @@ public class HexDump { public static String dumpHexString(byte[] array, int offset, int length) { StringBuilder result = new StringBuilder(); - byte[] line = new byte[16]; + byte[] line = new byte[8]; 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 (lineIndex == line.length) { + for (int j = 0; j < line.length; j++) { if (line[j] > ' ' && line[j] < '~') { result.append(new String(line, j, 1)); } else { @@ -50,32 +47,26 @@ public class HexDump { } } - result.append("\n0x"); - result.append(toHexString(i)); + result.append("\n"); lineIndex = 0; } byte b = array[i]; - result.append(" "); result.append(HEX_DIGITS[(b >>> 4) & 0x0F]); result.append(HEX_DIGITS[b & 0x0F]); + result.append(" "); 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("."); - } + for (int i = 0; i < (line.length - lineIndex); 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("."); } } @@ -145,7 +136,7 @@ public class HexDump { if (c >= 'a' && c <= 'f') return (c - 'a' + 10); - throw new RuntimeException("Invalid hex char '" + c + "'"); + throw new InvalidParameterException("Invalid hex char '" + c + "'"); } public static byte[] hexStringToByteArray(String hexString) { diff --git a/usbSerialExamples/src/main/res/drawable-hdpi/ic_launcher.png b/usbSerialExamples/src/main/res/drawable-hdpi/ic_launcher.png deleted file mode 100644 index 8074c4c571b8cd19e27f4ee5545df367420686d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4147 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 diff --git a/usbSerialExamples/src/main/res/drawable-ldpi/ic_launcher.png b/usbSerialExamples/src/main/res/drawable-ldpi/ic_launcher.png deleted file mode 100644 index 1095584ec21f71cd0afc9e0993aa2209671b590c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1723 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 + + diff --git a/usbSerialExamples/src/main/res/drawable/ic_send_white_24dp.xml b/usbSerialExamples/src/main/res/drawable/ic_send_white_24dp.xml new file mode 100644 index 0000000..791e93b --- /dev/null +++ b/usbSerialExamples/src/main/res/drawable/ic_send_white_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/usbSerialExamples/src/main/res/layout/activity_main.xml b/usbSerialExamples/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..8cde2fb --- /dev/null +++ b/usbSerialExamples/src/main/res/layout/activity_main.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + diff --git a/usbSerialExamples/src/main/res/layout/device_list_header.xml b/usbSerialExamples/src/main/res/layout/device_list_header.xml new file mode 100644 index 0000000..25214f4 --- /dev/null +++ b/usbSerialExamples/src/main/res/layout/device_list_header.xml @@ -0,0 +1,17 @@ + + + + + diff --git a/usbSerialExamples/src/main/res/layout/device_list_item.xml b/usbSerialExamples/src/main/res/layout/device_list_item.xml new file mode 100644 index 0000000..5a8c577 --- /dev/null +++ b/usbSerialExamples/src/main/res/layout/device_list_item.xml @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/usbSerialExamples/src/main/res/layout/fragment_terminal.xml b/usbSerialExamples/src/main/res/layout/fragment_terminal.xml new file mode 100644 index 0000000..18c9c7f --- /dev/null +++ b/usbSerialExamples/src/main/res/layout/fragment_terminal.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/usbSerialExamples/src/main/res/layout/main.xml b/usbSerialExamples/src/main/res/layout/main.xml deleted file mode 100644 index 2d24c70..0000000 --- a/usbSerialExamples/src/main/res/layout/main.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/usbSerialExamples/src/main/res/layout/serial_console.xml b/usbSerialExamples/src/main/res/layout/serial_console.xml deleted file mode 100644 index 8e25ee9..0000000 --- a/usbSerialExamples/src/main/res/layout/serial_console.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/usbSerialExamples/src/main/res/menu/menu_devices.xml b/usbSerialExamples/src/main/res/menu/menu_devices.xml new file mode 100644 index 0000000..26860b4 --- /dev/null +++ b/usbSerialExamples/src/main/res/menu/menu_devices.xml @@ -0,0 +1,9 @@ + +

+ + + diff --git a/usbSerialExamples/src/main/res/menu/menu_terminal.xml b/usbSerialExamples/src/main/res/menu/menu_terminal.xml new file mode 100644 index 0000000..77ba443 --- /dev/null +++ b/usbSerialExamples/src/main/res/menu/menu_terminal.xml @@ -0,0 +1,9 @@ + + + + diff --git a/usbSerialExamples/src/main/res/mipmap-hdpi/ic_launcher.png b/usbSerialExamples/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..7b9ba5d2a78473eb8b419a426ccd581dd381d282 GIT binary patch literal 1475 zcmV;!1w8tRP)3;G^U2hNnq1$fnzjsp>qAl`)!-M0<%@W)@;+~nr!+) zvpqiFY>O|Dl(1*!pPktNTl|J3+-R}HEoVwwO;$b0Oj`4qZ9YMA|9vt=4k#?O=v{IW z*i>NBwlfn$J#Ah zM_WH!Spr*q0TlX)Nn0UXK=`Ru=_n_6RW)q&1yERCv9>Z;fXeKNR9(M@&x6&204UqI zvIe&L1ZaCvoF!O*KHL8aUBB@Sp9d3Aj!{$VGoZY}xT;_Pve!RP12;Qqa&nT-Q4U%U zdSA2ijs{dwlT2M_tmJf!@qmz{jO!{OYdjruWRcT3%EJ)^Wn4$Sf&sH`Jojt7JhYvATduW$rGJ=!S_P`UjvI(^no6BEuk0iho4&|Xo1b~mi0v*+sQ z;+2EE4Bk2~0)w(phjwVMC_rXgB9&Js&B%9MCI)6=8qfq^cCSZ!#SZh3j#EVb&G+AwKzcW^!dTp=(r=t zs~m03qPo2=N(&I+w0-*#4G;h3X80tHjr~o%7xqwP%@Yd-WVR)+k<7+V9=!>49%w!mRfUo7~OSgMRF9BWvAr$^-;yYEGYa(B6E|DDS`( z>w~7|K1tNkRYIdL`ShYjG1&nUob{>hN>M-x-{c8rA@d-Nik;tA z(9eTCZh@?eIr|nqEZKA5RcX$okGE|lmuq~+DEKCCan(X*(ztKRw@vASUg(!}sG$N< z0r>~$m?L{;F&+XR0$o`f^(g1xc66}7y2a)$hzwp zK9UavAn1jD$*%|1H@rms106In^5?v3(DMoIhaTvIUfHZDA~5~x$UFQD`ozin{|Q15 z&rrl$JKPUF?t!kl@Dh793TwWeOH@B@tP24 z;ri_u&Ls;73t=to+h}}z*z2Sa*HMpliUee-eQMstebl3!A^{jj(Wvz!4o!*w|C^xKSRHW=0PaqdLTEI zOJ*K~7mbaF-lVQ>3tha@$mb{rV%wc$XVSu&GhP)1VmFyA04>F7AHM;89K^F4O9d#) zud^D(GVVbZ;k1uGJ*aSXvD^>T8FFH(dv*wNex}&V%@JBN9&02bE{X=iV*7Wq0 zWs5!3dl!=xALOm-MpuNwX;6}vDO+@uxlPlbAji~i8Sx^+CDh~(t(HQB~TdUlk? zQAwqapjgU+pVbbNmNK_!dJ_`DUx1CNsazQ6ONx!lAB{DLSyAL+{{fmD5;Y(zv<)cwmNBf}q%vcLw|0-FNyJ&+KYh?>-- dCN)VS{R^2Cvcu>U1c3km002ovPDHLkV1j0^!M6Ya literal 0 HcmV?d00001 diff --git a/usbSerialExamples/src/main/res/mipmap-mdpi/ic_launcher.png b/usbSerialExamples/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..ef22ce24ebd8dda87041dd7d63abd2c5bf97741a GIT binary patch literal 895 zcmV-_1AzRAP)U&DMAY(ll|l=FiEqHU0uUG$0scH^dE^|9hvZy)LMdmqd0eTIf5l zfascLCDni@rg|AH}yJ)}IaVO!GwKYxD1 zJpf{Z#D;_iKxzK-msfDd!!SsUocus{4;()|8JzB4zqtW-Jctbv1IZ1UJg{|F4%`DE z_K?fOL&5`#SGxbdaeM3k7q71Tzj$TY|JjQy@Oog{JpKPyZ>+_@Aam&Mf!T|#Ff!}2 z7w6$+J~j``m~VuUxj}f%rYQP*VDEuytd3c+E@)_Y;J}e)yp9?49+?G4~%HB)S*{ zsRfCH^bUAEFyuY({=-ACV?fCQxom&*VS zx4}{3O3;}k7JO4o9Cd9ft0vCW_z%(u87dzb46}RU42}QgwF>KiZsR0oj*MAFg-5%r zMsZ`u1hscPlhi(TO;-N^qUniYc7ohcQl+p-Nr@Yje3*%yspJG=MJ+vUXA2uaUu0}* zL0gP&pQbLi3&<@5Lm%A}+S&|kKqfa3^9?ZO2Dyc-iFZ(DNlPI$btwukXL8GyW{pCf`J?rYnZWVrg5g6ilOo!nId z@8{X)dG@)Rdl&`-0|NsC0|NsCXI-eS71FSlB-2c7kH!E!-i9R5_p=~*Aq`NFTFZ{A3)rz- ztwN7d=)nu{1iZ=Gt!PY2mU>fr68MX#3)yr-%`aqiTtO39<4rW7;k?>pm6R97(f8R0DPJwA6&QI_et=M27m=`zZ>{C0uT=1lU?$G z_}6@wfp;_jIB!e}cme^;p$W>C55AbNcsY3I&;X7e-)0a3u!AbTeSwVXh75vz1Ykqu z?~Nfnz0G8NeB2<|hcpCWBVB3y@viy2APoW7sNJ7#J}-Os2M!N_Z}%+$uy=pp&;X{l z`<7(S{=lIDm}~bf$zJ_|!vdJ8-M^Rm1BV1KTf2WR^#=|K;84{Ta{6rUf7I1|*~D;2 zo1PEOMF3XN<%S1&p_nwa947TmKau0r9}{iaN-6+$ z7l)I5->ns-;__AE0M1k)VT&-rKI zue--9zIk4pb3xrbjV8v-RQvz$WE@;``Z-Xx=qKY400KY&2*92IZq=I@105#cIhs>@ z$61qeAZ?~|%yq(0w&(%eXsw>}S59aN$`(BU7;@SRz-+@^Q2;3XVi_42=(M@{P$ra( zAIfw3`oPO%V6e+}=5u91nfRgn)Mf00e*l5P+q*qthy)(+!)xh;eCf3;|eCr_QKn zoo0YM2*3*ZYX2Id*Xw2l0C^xU0-&sO7fS_Cwn1J5Kv}KrHG%;^UIai{Z5?L>1Ax2; zfU@eY>=z6G@*)7rI&g5kU;vO80a!szR}alf0DJ#^VpgmlE)Dy8Z9j1qrgRcOl$uHc$1|GC2wsG+6$f;y<=zqaEprah)Lfm zz4>{;Bm}NW8iPlU`&-lk4`3N9@C3a1ASI-Yjd%n)V0W(eKfq83r?4=?ia-IYpYu-m zX#3JORc;wZYyP3k7wT46jYI% z64IQWDec>#k_~03?*O!5X+^DW82_#)5l85}E z08SB}o{M6mV!U2j`IP4?%VWI~#3;CT@PPAT6?g*P7(H^OS^N2b5z&J_KFned4uKn9+GH{g-cE2{)hg--clcX#G7Z*Rs|B4PYE`HNJ3-~o66o*2DxVr&pl wh_kVsTPSk57`?EG@fa8w7#J8B7>*JD0u_F+a&LniAOHXW07*qoM6N<$f-iON$p8QV literal 0 HcmV?d00001 diff --git a/usbSerialExamples/src/main/res/mipmap-xxhdpi/ic_launcher.png b/usbSerialExamples/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..b71377c8b5ebbe3e410b88e1b38e531f12a64437 GIT binary patch literal 2462 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 + + + 2400 + 9600 + 19200 + 57600 + 115200 + + diff --git a/usbSerialExamples/src/main/res/values/colors.xml b/usbSerialExamples/src/main/res/values/colors.xml new file mode 100644 index 0000000..2f18fb4 --- /dev/null +++ b/usbSerialExamples/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #949C29 + #61671B + #D8E33B + + #00FF00 + #82CAFF + #FFDB58 + diff --git a/usbSerialExamples/src/main/res/values/strings.xml b/usbSerialExamples/src/main/res/values/strings.xml index c818764..f7e0a8e 100644 --- a/usbSerialExamples/src/main/res/values/strings.xml +++ b/usbSerialExamples/src/main/res/values/strings.xml @@ -1,10 +1,6 @@ - - USB Serial Example - Serial Example - Refreshing... - RTS - Request To Send - DTR - Data Terminal Ready - + USB Serial For Android Example + USB Serial Example + USB Devices diff --git a/usbSerialExamples/src/main/res/values/styles.xml b/usbSerialExamples/src/main/res/values/styles.xml new file mode 100644 index 0000000..5f4a5d7 --- /dev/null +++ b/usbSerialExamples/src/main/res/values/styles.xml @@ -0,0 +1,7 @@ + + +