├── .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 |
--------------------------------------------------------------------------------
/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 | }
--------------------------------------------------------------------------------