├── .gitignore ├── AndroidManifest.xml ├── README.md ├── res ├── drawable-hdpi │ └── ic_launcher.png ├── drawable-ldpi │ └── ic_launcher.png ├── drawable-mdpi │ └── ic_launcher.png ├── drawable-xhdpi │ └── ic_launcher.png ├── menu │ └── options.xml ├── values │ └── strings.xml └── xml │ └── device_filter.xml └── src └── com └── primavera └── arduino └── listener ├── ArduinoCommunicatorActivity.java ├── ArduinoCommunicatorService.java └── ByteArray.java /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # generated files 12 | bin/ 13 | gen/ 14 | 15 | # Local configuration file (sdk path, etc) 16 | local.properties 17 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 13 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 26 | 27 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Arduino-Communicator 2 | ==================== 3 | 4 | Very simple Android application for communicating with Arduino Uno (with Atmega16U2 or Atmega8U2 programmed as a USB-to-serial converter). 5 | 6 | No need for extra Host Shield or Bluetooth. All you need is a Micro USB OTG to USB Adapter. 7 | 8 | Send data from your Arduino with Serial.println(), Serial.print() or Serial.write() in 9600 baud rate. Receive data with Serial.read(). 9 | 10 | Toggle between hex and ascii by clicking on received/sent data. 11 | 12 | Let your own Android application receive data from Arduino by listening to the "primavera.arduino.intent.action.DATA_RECEIVED" intent. This intent will contain the "primavera.arduino.intent.extra.DATA" byte array with the received data. Call getByteArrayExtra("primavera.arduino.intent.extra.DATA") to retreive the data. 13 | Send data to Arduino from your application by broadcasting an intent with action "primavera.arduino.intent.action.SEND_DATA". Add the data to be sent as byte array extra "primavera.arduino.intent.extra.DATA". 14 | 15 | Please note that this app will not work with Arduino boards with the FTDI USB-to-serial driver chip. 16 | 17 | Source code at: https://github.com/jeppsson/Arduino-Communicator 18 | -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeppsson/Arduino-Communicator/f39cb474d898bdcbfb509412848937ddb1c91b34/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-ldpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeppsson/Arduino-Communicator/f39cb474d898bdcbfb509412848937ddb1c91b34/res/drawable-ldpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeppsson/Arduino-Communicator/f39cb474d898bdcbfb509412848937ddb1c91b34/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeppsson/Arduino-Communicator/f39cb474d898bdcbfb509412848937ddb1c91b34/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/menu/options.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | -------------------------------------------------------------------------------- /res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Arduino Uno Communicator 4 | No data 5 | Help 6 | About 7 | Permission denied! 8 | Receiving! 9 | Opening USB device failed! 10 | Claiming interface failed! 11 | No in endpoint found! 12 | No out endpoint found! 13 | No %1$s extra in intent! 14 | Device detached! 15 | No device found! 16 | found! 17 | -------------------------------------------------------------------------------- /res/xml/device_filter.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/com/primavera/arduino/listener/ArduinoCommunicatorActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Mathias Jeppsson 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.primavera.arduino.listener; 18 | 19 | import java.util.ArrayList; 20 | import java.util.HashMap; 21 | import java.util.Iterator; 22 | 23 | import android.app.ListActivity; 24 | import android.app.PendingIntent; 25 | import android.content.BroadcastReceiver; 26 | import android.content.Context; 27 | import android.content.Intent; 28 | import android.content.IntentFilter; 29 | import android.hardware.usb.UsbDevice; 30 | import android.hardware.usb.UsbManager; 31 | import android.net.Uri; 32 | import android.os.Bundle; 33 | import android.util.Log; 34 | import android.view.Menu; 35 | import android.view.MenuItem; 36 | import android.view.View; 37 | import android.widget.ArrayAdapter; 38 | import android.widget.ListView; 39 | import android.widget.Toast; 40 | 41 | public class ArduinoCommunicatorActivity extends ListActivity { 42 | 43 | private static final int ARDUINO_USB_VENDOR_ID = 0x2341; 44 | private static final int ARDUINO_UNO_USB_PRODUCT_ID = 0x01; 45 | private static final int ARDUINO_MEGA_2560_USB_PRODUCT_ID = 0x10; 46 | private static final int ARDUINO_MEGA_2560_R3_USB_PRODUCT_ID = 0x42; 47 | private static final int ARDUINO_UNO_R3_USB_PRODUCT_ID = 0x43; 48 | private static final int ARDUINO_MEGA_2560_ADK_R3_USB_PRODUCT_ID = 0x44; 49 | private static final int ARDUINO_MEGA_2560_ADK_USB_PRODUCT_ID = 0x3F; 50 | 51 | private final static String TAG = "ArduinoCommunicatorActivity"; 52 | private final static boolean DEBUG = false; 53 | 54 | private Boolean mIsReceiving; 55 | private ArrayList mTransferedDataList = new ArrayList(); 56 | private ArrayAdapter mDataAdapter; 57 | 58 | private void findDevice() { 59 | UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE); 60 | UsbDevice usbDevice = null; 61 | HashMap usbDeviceList = usbManager.getDeviceList(); 62 | if (DEBUG) Log.d(TAG, "length: " + usbDeviceList.size()); 63 | Iterator deviceIterator = usbDeviceList.values().iterator(); 64 | if (deviceIterator.hasNext()) { 65 | UsbDevice tempUsbDevice = deviceIterator.next(); 66 | 67 | // Print device information. If you think your device should be able 68 | // to communicate with this app, add it to accepted products below. 69 | if (DEBUG) Log.d(TAG, "VendorId: " + tempUsbDevice.getVendorId()); 70 | if (DEBUG) Log.d(TAG, "ProductId: " + tempUsbDevice.getProductId()); 71 | if (DEBUG) Log.d(TAG, "DeviceName: " + tempUsbDevice.getDeviceName()); 72 | if (DEBUG) Log.d(TAG, "DeviceId: " + tempUsbDevice.getDeviceId()); 73 | if (DEBUG) Log.d(TAG, "DeviceClass: " + tempUsbDevice.getDeviceClass()); 74 | if (DEBUG) Log.d(TAG, "DeviceSubclass: " + tempUsbDevice.getDeviceSubclass()); 75 | if (DEBUG) Log.d(TAG, "InterfaceCount: " + tempUsbDevice.getInterfaceCount()); 76 | if (DEBUG) Log.d(TAG, "DeviceProtocol: " + tempUsbDevice.getDeviceProtocol()); 77 | 78 | if (tempUsbDevice.getVendorId() == ARDUINO_USB_VENDOR_ID) { 79 | if (DEBUG) Log.i(TAG, "Arduino device found!"); 80 | 81 | switch (tempUsbDevice.getProductId()) { 82 | case ARDUINO_UNO_USB_PRODUCT_ID: 83 | Toast.makeText(getBaseContext(), "Arduino Uno " + getString(R.string.found), Toast.LENGTH_SHORT).show(); 84 | usbDevice = tempUsbDevice; 85 | break; 86 | case ARDUINO_MEGA_2560_USB_PRODUCT_ID: 87 | Toast.makeText(getBaseContext(), "Arduino Mega 2560 " + getString(R.string.found), Toast.LENGTH_SHORT).show(); 88 | usbDevice = tempUsbDevice; 89 | break; 90 | case ARDUINO_MEGA_2560_R3_USB_PRODUCT_ID: 91 | Toast.makeText(getBaseContext(), "Arduino Mega 2560 R3 " + getString(R.string.found), Toast.LENGTH_SHORT).show(); 92 | usbDevice = tempUsbDevice; 93 | break; 94 | case ARDUINO_UNO_R3_USB_PRODUCT_ID: 95 | Toast.makeText(getBaseContext(), "Arduino Uno R3 " + getString(R.string.found), Toast.LENGTH_SHORT).show(); 96 | usbDevice = tempUsbDevice; 97 | break; 98 | case ARDUINO_MEGA_2560_ADK_R3_USB_PRODUCT_ID: 99 | Toast.makeText(getBaseContext(), "Arduino Mega 2560 ADK R3 " + getString(R.string.found), Toast.LENGTH_SHORT).show(); 100 | usbDevice = tempUsbDevice; 101 | break; 102 | case ARDUINO_MEGA_2560_ADK_USB_PRODUCT_ID: 103 | Toast.makeText(getBaseContext(), "Arduino Mega 2560 ADK " + getString(R.string.found), Toast.LENGTH_SHORT).show(); 104 | usbDevice = tempUsbDevice; 105 | break; 106 | } 107 | } 108 | } 109 | 110 | if (usbDevice == null) { 111 | if (DEBUG) Log.i(TAG, "No device found!"); 112 | Toast.makeText(getBaseContext(), getString(R.string.no_device_found), Toast.LENGTH_LONG).show(); 113 | } else { 114 | if (DEBUG) Log.i(TAG, "Device found!"); 115 | Intent startIntent = new Intent(getApplicationContext(), ArduinoCommunicatorService.class); 116 | PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 0, startIntent, 0); 117 | usbManager.requestPermission(usbDevice, pendingIntent); 118 | } 119 | } 120 | 121 | @Override 122 | public void onCreate(Bundle savedInstanceState) { 123 | super.onCreate(savedInstanceState); 124 | if (DEBUG) Log.d(TAG, "onCreate()"); 125 | 126 | IntentFilter filter = new IntentFilter(); 127 | filter.addAction(ArduinoCommunicatorService.DATA_RECEIVED_INTENT); 128 | filter.addAction(ArduinoCommunicatorService.DATA_SENT_INTERNAL_INTENT); 129 | registerReceiver(mReceiver, filter); 130 | 131 | mDataAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, mTransferedDataList); 132 | setListAdapter(mDataAdapter); 133 | 134 | findDevice(); 135 | } 136 | 137 | @Override 138 | protected void onListItemClick(ListView l, View v, int position, long id) { 139 | super.onListItemClick(l, v, position, id); 140 | 141 | if (DEBUG) Log.i(TAG, "onListItemClick() " + position + " " + id); 142 | ByteArray transferedData = mTransferedDataList.get(position); 143 | transferedData.toggleCoding(); 144 | mTransferedDataList.set(position, transferedData); 145 | mDataAdapter.notifyDataSetChanged(); 146 | } 147 | 148 | @Override 149 | protected void onNewIntent(Intent intent) { 150 | if (DEBUG) Log.d(TAG, "onNewIntent() " + intent); 151 | super.onNewIntent(intent); 152 | 153 | if (UsbManager.ACTION_USB_DEVICE_ATTACHED.contains(intent.getAction())) { 154 | if (DEBUG) Log.d(TAG, "onNewIntent() " + intent); 155 | findDevice(); 156 | } 157 | } 158 | 159 | @Override 160 | protected void onDestroy() { 161 | if (DEBUG) Log.d(TAG, "onDestroy()"); 162 | super.onDestroy(); 163 | unregisterReceiver(mReceiver); 164 | } 165 | 166 | @Override 167 | public boolean onCreateOptionsMenu(Menu menu) { 168 | getMenuInflater().inflate(R.menu.options, menu); 169 | return true; 170 | } 171 | 172 | @Override 173 | public boolean onOptionsItemSelected(MenuItem item) { 174 | switch (item.getItemId()) { 175 | case R.id.help: 176 | startActivity(new Intent(Intent.ACTION_VIEW, 177 | Uri.parse("http://ron.bems.se/arducom/usage.html"))); 178 | return true; 179 | case R.id.about: 180 | startActivity(new Intent(Intent.ACTION_VIEW, 181 | Uri.parse("http://ron.bems.se/arducom/primaindex.php"))); 182 | return true; 183 | default: 184 | return super.onOptionsItemSelected(item); 185 | } 186 | } 187 | 188 | BroadcastReceiver mReceiver = new BroadcastReceiver() { 189 | 190 | private void handleTransferedData(Intent intent, boolean receiving) { 191 | if (mIsReceiving == null || mIsReceiving != receiving) { 192 | mIsReceiving = receiving; 193 | mTransferedDataList.add(new ByteArray()); 194 | } 195 | 196 | final byte[] newTransferedData = intent.getByteArrayExtra(ArduinoCommunicatorService.DATA_EXTRA); 197 | if (DEBUG) Log.i(TAG, "data: " + newTransferedData.length + " \"" + new String(newTransferedData) + "\""); 198 | 199 | ByteArray transferedData = mTransferedDataList.get(mTransferedDataList.size() - 1); 200 | transferedData.add(newTransferedData); 201 | mTransferedDataList.set(mTransferedDataList.size() - 1, transferedData); 202 | mDataAdapter.notifyDataSetChanged(); 203 | } 204 | 205 | @Override 206 | public void onReceive(Context context, Intent intent) { 207 | final String action = intent.getAction(); 208 | if (DEBUG) Log.d(TAG, "onReceive() " + action); 209 | 210 | if (ArduinoCommunicatorService.DATA_RECEIVED_INTENT.equals(action)) { 211 | handleTransferedData(intent, true); 212 | } else if (ArduinoCommunicatorService.DATA_SENT_INTERNAL_INTENT.equals(action)) { 213 | handleTransferedData(intent, false); 214 | } 215 | } 216 | }; 217 | } 218 | -------------------------------------------------------------------------------- /src/com/primavera/arduino/listener/ArduinoCommunicatorService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Mathias Jeppsson 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.primavera.arduino.listener; 18 | 19 | import android.app.Service; 20 | import android.content.BroadcastReceiver; 21 | import android.content.Context; 22 | import android.content.Intent; 23 | import android.content.IntentFilter; 24 | import android.hardware.usb.UsbConstants; 25 | import android.hardware.usb.UsbDevice; 26 | import android.hardware.usb.UsbDeviceConnection; 27 | import android.hardware.usb.UsbEndpoint; 28 | import android.hardware.usb.UsbInterface; 29 | import android.hardware.usb.UsbManager; 30 | import android.os.Handler; 31 | import android.os.IBinder; 32 | import android.os.Looper; 33 | import android.os.Message; 34 | import android.util.Log; 35 | import android.widget.Toast; 36 | 37 | public class ArduinoCommunicatorService extends Service { 38 | 39 | private final static String TAG = "ArduinoCommunicatorService"; 40 | private final static boolean DEBUG = false; 41 | 42 | private boolean mIsRunning = false; 43 | private SenderThread mSenderThread; 44 | 45 | private volatile UsbDevice mUsbDevice = null; 46 | private volatile UsbDeviceConnection mUsbConnection = null; 47 | private volatile UsbEndpoint mInUsbEndpoint = null; 48 | private volatile UsbEndpoint mOutUsbEndpoint = null; 49 | 50 | final static String DATA_RECEIVED_INTENT = "primavera.arduino.intent.action.DATA_RECEIVED"; 51 | final static String SEND_DATA_INTENT = "primavera.arduino.intent.action.SEND_DATA"; 52 | final static String DATA_SENT_INTERNAL_INTENT = "primavera.arduino.internal.intent.action.DATA_SENT"; 53 | final static String DATA_EXTRA = "primavera.arduino.intent.extra.DATA"; 54 | 55 | @Override 56 | public IBinder onBind(Intent arg0) { 57 | return null; 58 | } 59 | 60 | @Override 61 | public void onCreate() { 62 | if (DEBUG) Log.d(TAG, "onCreate()"); 63 | super.onCreate(); 64 | IntentFilter filter = new IntentFilter(); 65 | filter.addAction(SEND_DATA_INTENT); 66 | filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); 67 | registerReceiver(mReceiver, filter); 68 | } 69 | 70 | @Override 71 | public int onStartCommand(Intent intent, int flags, int startId) { 72 | if (DEBUG) Log.d(TAG, "onStartCommand() " + intent + " " + flags + " " + startId); 73 | 74 | if (mIsRunning) { 75 | if (DEBUG) Log.i(TAG, "Service already running."); 76 | return Service.START_REDELIVER_INTENT; 77 | } 78 | 79 | mIsRunning = true; 80 | 81 | if (!intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { 82 | if (DEBUG) Log.i(TAG, "Permission denied"); 83 | Toast.makeText(getBaseContext(), getString(R.string.permission_denied), Toast.LENGTH_LONG).show(); 84 | stopSelf(); 85 | return Service.START_REDELIVER_INTENT; 86 | } 87 | 88 | if (DEBUG) Log.d(TAG, "Permission granted"); 89 | mUsbDevice = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); 90 | if (!initDevice()) { 91 | if (DEBUG) Log.e(TAG, "Init of device failed!"); 92 | stopSelf(); 93 | return Service.START_REDELIVER_INTENT; 94 | } 95 | 96 | if (DEBUG) Log.i(TAG, "Receiving!"); 97 | Toast.makeText(getBaseContext(), getString(R.string.receiving), Toast.LENGTH_SHORT).show(); 98 | startReceiverThread(); 99 | startSenderThread(); 100 | 101 | return Service.START_REDELIVER_INTENT; 102 | } 103 | 104 | @Override 105 | public void onDestroy() { 106 | if (DEBUG) Log.i(TAG, "onDestroy()"); 107 | super.onDestroy(); 108 | unregisterReceiver(mReceiver); 109 | mUsbDevice = null; 110 | if (mUsbConnection != null) { 111 | mUsbConnection.close(); 112 | } 113 | } 114 | 115 | private byte[] getLineEncoding(int baudRate) { 116 | final byte[] lineEncodingRequest = { (byte) 0x80, 0x25, 0x00, 0x00, 0x00, 0x00, 0x08 }; 117 | switch (baudRate) { 118 | case 14400: 119 | lineEncodingRequest[0] = 0x40; 120 | lineEncodingRequest[1] = 0x38; 121 | break; 122 | 123 | case 19200: 124 | lineEncodingRequest[0] = 0x00; 125 | lineEncodingRequest[1] = 0x4B; 126 | break; 127 | } 128 | 129 | return lineEncodingRequest; 130 | } 131 | 132 | private boolean initDevice() { 133 | UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE); 134 | mUsbConnection = usbManager.openDevice(mUsbDevice); 135 | if (mUsbConnection == null) { 136 | if (DEBUG) Log.e(TAG, "Opening USB device failed!"); 137 | Toast.makeText(getBaseContext(), getString(R.string.opening_device_failed), Toast.LENGTH_LONG).show(); 138 | return false; 139 | } 140 | UsbInterface usbInterface = mUsbDevice.getInterface(1); 141 | if (!mUsbConnection.claimInterface(usbInterface, true)) { 142 | if (DEBUG) Log.e(TAG, "Claiming interface failed!"); 143 | Toast.makeText(getBaseContext(), getString(R.string.claimning_interface_failed), Toast.LENGTH_LONG).show(); 144 | mUsbConnection.close(); 145 | return false; 146 | } 147 | 148 | // Arduino USB serial converter setup 149 | // Set control line state 150 | mUsbConnection.controlTransfer(0x21, 0x22, 0, 0, null, 0, 0); 151 | // Set line encoding. 152 | mUsbConnection.controlTransfer(0x21, 0x20, 0, 0, getLineEncoding(9600), 7, 0); 153 | 154 | for (int i = 0; i < usbInterface.getEndpointCount(); i++) { 155 | if (usbInterface.getEndpoint(i).getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) { 156 | if (usbInterface.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_IN) { 157 | mInUsbEndpoint = usbInterface.getEndpoint(i); 158 | } else if (usbInterface.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_OUT) { 159 | mOutUsbEndpoint = usbInterface.getEndpoint(i); 160 | } 161 | } 162 | } 163 | 164 | if (mInUsbEndpoint == null) { 165 | if (DEBUG) Log.e(TAG, "No in endpoint found!"); 166 | Toast.makeText(getBaseContext(), getString(R.string.no_in_endpoint_found), Toast.LENGTH_LONG).show(); 167 | mUsbConnection.close(); 168 | return false; 169 | } 170 | 171 | if (mOutUsbEndpoint == null) { 172 | if (DEBUG) Log.e(TAG, "No out endpoint found!"); 173 | Toast.makeText(getBaseContext(), getString(R.string.no_out_endpoint_found), Toast.LENGTH_LONG).show(); 174 | mUsbConnection.close(); 175 | return false; 176 | } 177 | 178 | return true; 179 | } 180 | 181 | BroadcastReceiver mReceiver = new BroadcastReceiver() { 182 | @Override 183 | public void onReceive(Context context, Intent intent) { 184 | final String action = intent.getAction(); 185 | if (DEBUG) Log.d(TAG, "onReceive() " + action); 186 | 187 | if (SEND_DATA_INTENT.equals(action)) { 188 | final byte[] dataToSend = intent.getByteArrayExtra(DATA_EXTRA); 189 | if (dataToSend == null) { 190 | if (DEBUG) Log.i(TAG, "No " + DATA_EXTRA + " extra in intent!"); 191 | String text = String.format(getResources().getString(R.string.no_extra_in_intent), DATA_EXTRA); 192 | Toast.makeText(context, text, Toast.LENGTH_LONG).show(); 193 | return; 194 | } 195 | 196 | mSenderThread.mHandler.obtainMessage(10, dataToSend).sendToTarget(); 197 | } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) { 198 | Toast.makeText(context, getString(R.string.device_detaches), Toast.LENGTH_LONG).show(); 199 | mSenderThread.mHandler.sendEmptyMessage(11); 200 | stopSelf(); 201 | } 202 | } 203 | }; 204 | 205 | private void startReceiverThread() { 206 | new Thread("arduino_receiver") { 207 | public void run() { 208 | byte[] inBuffer = new byte[4096]; 209 | while(mUsbDevice != null ) { 210 | if (DEBUG) Log.d(TAG, "calling bulkTransfer() in"); 211 | final int len = mUsbConnection.bulkTransfer(mInUsbEndpoint, inBuffer, inBuffer.length, 0); 212 | if (len > 0) { 213 | Intent intent = new Intent(DATA_RECEIVED_INTENT); 214 | byte[] buffer = new byte[len]; 215 | System.arraycopy(inBuffer, 0, buffer, 0, len); 216 | intent.putExtra(DATA_EXTRA, buffer); 217 | sendBroadcast(intent); 218 | } else { 219 | if (DEBUG) Log.i(TAG, "zero data read!"); 220 | } 221 | } 222 | 223 | if (DEBUG) Log.d(TAG, "receiver thread stopped."); 224 | } 225 | }.start(); 226 | } 227 | 228 | private void startSenderThread() { 229 | mSenderThread = new SenderThread("arduino_sender"); 230 | mSenderThread.start(); 231 | } 232 | 233 | private class SenderThread extends Thread { 234 | public Handler mHandler; 235 | 236 | public SenderThread(String string) { 237 | super(string); 238 | } 239 | 240 | public void run() { 241 | 242 | Looper.prepare(); 243 | 244 | mHandler = new Handler() { 245 | public void handleMessage(Message msg) { 246 | if (DEBUG) Log.i(TAG, "handleMessage() " + msg.what); 247 | if (msg.what == 10) { 248 | final byte[] dataToSend = (byte[]) msg.obj; 249 | 250 | if (DEBUG) Log.d(TAG, "calling bulkTransfer() out"); 251 | final int len = mUsbConnection.bulkTransfer(mOutUsbEndpoint, dataToSend, dataToSend.length, 0); 252 | if (DEBUG) Log.d(TAG, len + " of " + dataToSend.length + " sent."); 253 | Intent sendIntent = new Intent(DATA_SENT_INTERNAL_INTENT); 254 | sendIntent.putExtra(DATA_EXTRA, dataToSend); 255 | sendBroadcast(sendIntent); 256 | } else if (msg.what == 11) { 257 | Looper.myLooper().quit(); 258 | } 259 | } 260 | }; 261 | 262 | Looper.loop(); 263 | if (DEBUG) Log.i(TAG, "sender thread stopped"); 264 | } 265 | } 266 | } 267 | -------------------------------------------------------------------------------- /src/com/primavera/arduino/listener/ByteArray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Mathias Jeppsson 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.primavera.arduino.listener; 18 | 19 | class ByteArray { 20 | 21 | private byte[] mByteArray = new byte[1]; 22 | private int mUsedLength; 23 | private boolean mShowInAscii; 24 | 25 | void add(byte[] newArray) { 26 | // Make sure we have enough space to store byte array. 27 | while (mUsedLength + newArray.length > mByteArray.length) { 28 | byte[] tmpArray = new byte[mByteArray.length * 2]; 29 | System.arraycopy(mByteArray, 0, tmpArray, 0, mUsedLength); 30 | mByteArray = tmpArray; 31 | } 32 | 33 | // Add byte array. 34 | System.arraycopy(newArray, 0, mByteArray, mUsedLength, newArray.length); 35 | mUsedLength += newArray.length; 36 | } 37 | 38 | void toggleCoding() { 39 | mShowInAscii = !mShowInAscii; 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | StringBuilder hexStr = new StringBuilder(); 45 | 46 | if (mShowInAscii) { 47 | for (int i = 0; i < mUsedLength; i++) { 48 | if (Character.isLetterOrDigit(mByteArray[i])) { 49 | hexStr.append(new String(new byte[] {mByteArray[i]})); 50 | } else { 51 | hexStr.append('.'); 52 | } 53 | } 54 | } else { 55 | for (int i = 0; i < mUsedLength; i++) { 56 | hexStr.append(String.format("%1$02X", mByteArray[i])); 57 | hexStr.append(" "); 58 | } 59 | } 60 | 61 | return hexStr.toString(); 62 | } 63 | } --------------------------------------------------------------------------------