I am trying to debug an app with eclipse. I am using the USB to connect to an accessory so USB in not Available to debug. I am using ADB connect to wirelessly debug, but with this app I have to unplug and plug in USB cable to get app to run and when I do this I lose connection to eclipse.
SO the only thing I can think is to try and use Toast to figure out what is going on in a class.
Maybe there is a better way?
But When I try to call toast app crashes.. I want to be able to toast messages in vaious methods like BroadcastReceiver, and ResumeAccessory
Call anyone tell me how to implement toast in this class?:
//
User must modify the below package with their package name
package com.UARTDemo;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
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.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.util.Log;
/******************************FT311 GPIO interface class******************************************/
public class FT311UARTInterface extends Activity
{
private static final String ACTION_USB_PERMISSION = "com.UARTDemo.USB_PERMISSION";
public UsbManager usbmanager;
public UsbAccessory usbaccessory;
public PendingIntent mPermissionIntent;
public ParcelFileDescriptor filedescriptor;
public FileInputStream inputstream;
public FileOutputStream outputstream;
public boolean mPermissionRequestPending = true;
public handler_thread handlerThread;
private byte [] usbdata;
private byte [] writeusbdata;
private byte [] readBuffer; /*circular buffer*/
private int readcount;
private int totalBytes;
private int writeIndex;
private int readIndex;
private byte status;
private byte maxnumbytes = (byte)64;
public boolean datareceived = false;
/*constructor*/
public FT311UARTInterface(Context context){
super();
/*shall we start a thread here or what*/
usbdata = new byte[64];
writeusbdata = new byte[64];
/*128(make it 256, but looks like bytes should be enough)*/
readBuffer = new byte [maxnumbytes];
readIndex = 0;
writeIndex = 0;
/***********************USB handling******************************************/
usbmanager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
// Log.d("LED", "usbmanager" +usbmanager);
mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
context.registerReceiver(mUsbReceiver, filter);
inputstream = null;
outputstream = null;
}
/*reset method*/
public void Reset()
{
/*create the packet*/
writeusbdata[0] = 0x49;
writeusbdata[1] = 0x00;
writeusbdata[2] = 0x00;
writeusbdata[3] = 0x00;
/*send the packet over the USB*/
SendPacket(4);
}
public void SetConfig(int baud, byte dataBits, byte stopBits,
byte parity, byte flowControl)
{
/*prepare the baud rate buffer*/
writeusbdata[0] = (byte)baud;
writeusbdata[1] = (byte)(baud >> 8);
writeusbdata[2] = (byte)(baud >> 16);
writeusbdata[3] = (byte)(baud >> 24);
/*data bits*/
writeusbdata[4] = dataBits;
/*stop bits*/
writeusbdata[5] = stopBits;
/*parity*/
writeusbdata[6] = parity;
/*flow control*/
writeusbdata[7] = flowControl;
/*send the UART configuration packet*/
SendPacket((int)8);
}
/*write data*/
public byte SendData(byte numBytes, char[] buffer)
{
status = 0x00; /*success by default*/
/*
* if num bytes are more than maximum limit
*/
if(numBytes < 1){
/*return the status with the error in the command*/
return status;
}
/*check for maximum limit*/
if(numBytes > 64){
numBytes = 64;
}
/*prepare the packet to be sent*/
for(int count = 0;count<numBytes;count++)
{
writeusbdata[count] = (byte)buffer[count];
}
SendPacket((int)numBytes);
return status;
}
/*read data*/
public byte ReadData(byte numBytes,char[] buffer, byte [] actualNumBytes)
{
status = 0x00; /*success by default*/
/*should be at least one byte to read*/
if((numBytes < 1) || (totalBytes == 0)){
actualNumBytes[0] = 0x00;
return status;
}
/*check for max limit*/
if(numBytes > 64){
numBytes = 64;
}
if(numBytes > 64){
numBytes = 64;
}
if(numBytes > totalBytes)
numBytes = (byte)totalBytes;
/*update the number of bytes available*/
totalBytes -= numBytes;
actualNumBytes[0] = numBytes;
/*copy to the user buffer*/
for(int count = 0; count<numBytes;count++)
{
buffer[count] = (char)readBuffer[readIndex];
readIndex++;
/*shouldnt read more than what is there in the buffer,
* so no need to check the overflow
*/
readIndex %= maxnumbytes;
}
return status;
}
/*method to send on USB*/
private void SendPacket(int numBytes)
{
try {
if(outputstream != null){
outputstream.write(writeusbdata, 0,numBytes);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*resume accessory*/
public void ResumeAccessory()
{
// Intent intent = getIntent();
if (inputstream != null && outputstream != null) {
return;
}
UsbAccessory[] accessories = usbmanager.getAccessoryList();
UsbAccessory accessory = (accessories == null ? null : accessories[0]);
if (accessory != null) {
if (usbmanager.hasPermission(accessory)) {
OpenAccessory(accessory);
}
else
{
synchronized (mUsbReceiver) {
if (!mPermissionRequestPending) {
usbmanager.requestPermission(accessory,
mPermissionIntent);
mPermissionRequestPending = true;
}
}
}
} else {}
}
/*destroy accessory*/
public void DestroyAccessory(){
unregisterReceiver(mUsbReceiver);
CloseAccessory();
}
/*********************helper routines*************************************************/
public void OpenAccessory(UsbAccessory accessory)
{
filedescriptor = usbmanager.openAccessory(accessory);
if(filedescriptor != null){
usbaccessory = accessory;
FileDescriptor fd = filedescriptor.getFileDescriptor();
inputstream = new FileInputStream(fd);
outputstream = new FileOutputStream(fd);
/*check if any of them are null*/
if(inputstream == null || outputstream==null){
return;
}
}
handlerThread = new handler_thread(handler, inputstream);
handlerThread.start();
}
private void CloseAccessory()
{
try{
if(filedescriptor != null)
filedescriptor.close();
}catch (IOException e){}
try {
if(inputstream != null)
inputstream.close();
} catch(IOException e){}
try {
if(outputstream != null)
outputstream.close();
}catch(IOException e){}
/*FIXME, add the notfication also to close the application*/
filedescriptor = null;
inputstream = null;
outputstream = null;
System.exit(0);
}
/***********USB broadcast receiver*******************************************/
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action))
{
synchronized (this)
{
UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false))
{
OpenAccessory(accessory);
}
else
{
Log.d("LED", "permission denied for accessory "+ accessory);
}
mPermissionRequestPending = false;
}
}
else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action))
{
UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (accessory != null )//&& accessory.equals(usbaccessory))
{
CloseAccessory();
}
}else
{
Log.d("LED", "....");
}
}
};
final Handler handler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
for(int count = 0;count<readcount;count++){
readBuffer[writeIndex] = usbdata[count];
/*move to the next write location*/
writeIndex++;
writeIndex %= maxnumbytes;
/*FIXME,check for overflow*/
//if(writeIndex == readIndex){
//}
}
/*caluclate the available bytes to read*/
if(writeIndex >= readIndex)
totalBytes = writeIndex-readIndex;
else
totalBytes = (maxnumbytes-readIndex)+writeIndex;
}
};
/*usb input data handler*/
private class handler_thread extends Thread {
Handler mHandler;
FileInputStream instream;
handler_thread(Handler h,FileInputStream stream ){
mHandler = h;
instream = stream;
}
public void run()
{
while(true)
{
Message msg = mHandler.obtainMessage();
try{
if(instream != null)
{
readcount = instream.read(usbdata,0,64);
if(readcount > 0)
{
datareceived = true;
msg.arg1 = usbdata[0];
msg.arg2 = usbdata[1];
}
mHandler.sendMessage(msg);
}
}catch (IOException e){}
}
}
}
}
Its better to use Log.d(TAG, text)
OR
In any subclass of activity you can do:
Toast.makeText(getApplicationContext(), "text", Toast.LENGTH_LONG).show();
Related
I have created an application which gives statistics for the UDP packet loss in android. This is my architecture of the applications.
1) An application which multicast the UDP packets. Below is the code for it:
package rockwell.multicastserverproj;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
public class MainActivity extends AppCompatActivity {
EditText txtMsg;
EditText txtPackets;
EditText txtMs;
EditText txtBytes;
EditText txtCount;
byte[] rtpData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
/*Thread thrClient = new Thread(new ReceiveMulticast());
thrClient.start();*/
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void onBtnClicked(View view)
{
Thread threadTotalPackets = new Thread(new SendMulticast());
threadTotalPackets.start();
Thread thread = new Thread(new MulticastPackets());
thread.start();
//Toast.makeText(this,"Message multicasted",Toast.LENGTH_LONG).show();
}
public class MulticastPackets implements Runnable{
#Override
public void run() {
InetAddress group = null;
MulticastSocket multiSocket = null;
int PORT = 6500;
txtPackets =(EditText)findViewById(R.id.txtPackets);
txtMs = (EditText)findViewById(R.id.txtMs);
txtBytes = (EditText)findViewById(R.id.txtBytes);
txtCount = (EditText)findViewById(R.id.txtCount);
int noOfPackets = Integer.parseInt(txtPackets.getText().toString());
int delayMS = Integer.parseInt(txtMs.getText().toString());
int packetSize = Integer.parseInt(txtBytes.getText().toString());
int cntPacket = Integer.parseInt(txtCount.getText().toString());
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock mLock = wifi.createMulticastLock("mylock");
mLock.acquire();
try{
group = InetAddress.getByName("230.0.0.1");
multiSocket = new MulticastSocket(PORT);
} catch (IOException e) {
e.printStackTrace();
}
for(int pcktCnt=1; pcktCnt<=noOfPackets; pcktCnt++) {
rtpData = new byte[packetSize];
int cnt = unsigned_int(pcktCnt);
byte[] seqArr = null;
seqArr = toBytes(cnt);
byte varFirst = 0xa;
byte varSecond = 0x5;
for(int i=4;i<packetSize;i+=2)
{
if(i%4 ==0) {
rtpData[i] = varFirst;
rtpData[i + 1] = varFirst;
}
else {
rtpData[i] = varSecond;
rtpData[i + 1] = varSecond;
}
}
for(int i=0;i<4;i++)
{
rtpData[i] = seqArr[i];
}
DatagramPacket requestPacket = new DatagramPacket(rtpData, rtpData.length, group, PORT);
try {
for(int i=0;i<cntPacket;i++) {
multiSocket.send(requestPacket);
Thread.sleep(delayMS, 0);
}
int test = fromByteArray(seqArr);
Log.i("Multicast", "Packet send. Sequence number is: " + test);
} catch (Exception e) {
e.printStackTrace();
}
int test = fromByteArray(seqArr);
}
try{
multiSocket.leaveGroup(group);
multiSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
mLock.release();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this,"Packet sent",Toast.LENGTH_LONG).show();
}
});
}
}
public class SendMulticast implements Runnable{
#Override
public void run() {
InetAddress group = null;
MulticastSocket multiSocket = null;
int PORT = 5500;
txtPackets =(EditText)findViewById(R.id.txtPackets);
txtBytes = (EditText)findViewById(R.id.txtBytes);
String requestString = txtPackets.getText().toString();
String strPackSize = txtBytes.getText().toString();
requestString = requestString +";" + strPackSize;
Log.i("reqstring",requestString);
byte[] requestData = new byte[requestString.length()];
requestData = requestString.getBytes();
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock mLock = wifi.createMulticastLock("mylock");
mLock.acquire();
try{
group = InetAddress.getByName("230.0.0.1");
multiSocket = new MulticastSocket(PORT);
multiSocket.joinGroup(group);
} catch (IOException e) {
e.printStackTrace();
}
try{
DatagramPacket requestPacket = new DatagramPacket(requestData, requestData.length, group, PORT);
multiSocket.send(requestPacket);
Log.i("multicastproj","message multicasted");
} catch (IOException e) {
e.printStackTrace();
}
try{
multiSocket.leaveGroup(group);
multiSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
mLock.release();
}
}
static int unsigned_int(int nb) {
if (nb >= 0)
return (nb);
else
return (256 + nb);
}
public byte[] toBytes(int i)
{
byte[] result = new byte[4];
result[0] = (byte) (i >> 24);
result[1] = (byte) (i >> 16);
result[2] = (byte) (i >> 8);
result[3] = (byte) (i /*>> 0*/);
return result;
}
public int fromByteArray(byte[] bytes) {
return bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF);
}
public class ReceiveMulticast implements Runnable{
#Override
public void run() {
byte[] requestData = new byte[1024];
InetAddress group = null;
MulticastSocket multiSocket = null;
int PORT = 4500;
WifiManager wifi = (WifiManager) getSystemService(getApplicationContext().WIFI_SERVICE);
WifiManager.MulticastLock mLock = wifi.createMulticastLock("mylock");
mLock.acquire();
try{
group = InetAddress.getByName("230.0.0.1");
multiSocket = new MulticastSocket(PORT);
multiSocket.joinGroup(group);
} catch (IOException e) {
e.printStackTrace();
}
try{
while(true)
{
DatagramPacket requestPacket = new DatagramPacket(requestData, requestData.length);
multiSocket.receive(requestPacket);
String requestString = new String(requestPacket.getData(), 0, requestPacket.getLength());
Log.d("CreateMulticastServer", "Got request = " + requestString);
/*txtMsg = (EditText)findViewById(R.id.txtMsg);
txtMsg.setText(requestString);*/
}
} catch (IOException e) {
e.printStackTrace();
}
try{
multiSocket.leaveGroup(group);
multiSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
mLock.release();
}
}
}
Another application which receives those multicast UDP packets
Service which runs continuously and receives the multicast packet:
package rockwell.packetstatistics;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiManager;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
/**
* Created by mmjoshi on 2/10/2016.
*/
public class PacketReceive_Service extends IntentService {
boolean flag = true;
int packetSize = 0;
public PacketReceive_Service() {
super("PacketReceive_Service");
}
#Override
protected void onHandleIntent(Intent intent) {
String strVar = intent.getStringExtra("vari");
Log.i("onstartservice","string is " + strVar);
Thread thread = new Thread(new PacketThread());
thread.setPriority(Thread.MAX_PRIORITY);
thread.start();
Thread thread1 = new Thread(new TotalPackets());
thread1.start();
}
public class PacketThread implements Runnable
{
#Override
public void run() {
InetAddress group = null;
MulticastSocket multiSocket = null;
WifiManager.MulticastLock mLock = null;
int prevSeqNo=0;
String strMissingPackets="";
int TotalpacketsReceived = 0;
try {
if(packetSize == 0)
packetSize = 1036;
byte[] requestData = new byte[packetSize];
int PORT = 6500;
byte varFirst = 0xa;
byte varSecond = 0x5;
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
mLock = wifi.createMulticastLock("mylock");
mLock.setReferenceCounted(true);
mLock.acquire();
try{
group = InetAddress.getByName("230.0.0.1");
multiSocket = new MulticastSocket(PORT);
multiSocket.joinGroup(group);
} catch (IOException e) {
e.printStackTrace();
}
while (flag) {
final DatagramPacket requestPacket = new DatagramPacket(requestData, requestData.length);
multiSocket.receive(requestPacket);
byte[] resultData = requestPacket.getData();
byte[] seqArr = new byte[4];
for(int i=0;i<4;i++){
seqArr[i] = resultData[i];
}
int seqNo = fromByteArray(seqArr);
Log.i("RecvPackets","multiple packet received # is: " + seqNo);
if(prevSeqNo!=seqNo)
{
TotalpacketsReceived++;
if(prevSeqNo!=0)
{
if((seqNo - prevSeqNo)>1)
{
for(int k=(prevSeqNo+1);k<seqNo;k++)
{
strMissingPackets += k + ", ";
sendResultMessage("Missing;" + String.valueOf(k));
Log.i("RecvPackets","Packet missing. Missing# is: " + k);
}
}
}
for(int i=4;i<packetSize;i+=2)
{
if(i%4 ==0) {
if(resultData[i] != varFirst || resultData[i+1] != varFirst)
{
if(seqNo != 1) {
sendResultMessage("DataError;" + String.valueOf(seqNo));
Log.i("DataCheck", "Error in data");
}
}
}
else {
if(resultData[i] != varSecond || resultData[i+1] != varSecond)
{
if(seqNo != 1) {
sendResultMessage("DataError;" + String.valueOf(seqNo));
Log.i("DataCheck", "Error in data");
}
}
}
}
prevSeqNo = seqNo;
Log.i("MulticastService", "Packet size is: " + packetSize + " Packet receive. Sequence number is: " + seqNo);
sendResultMessage("TotalPacketsReceived;" + String.valueOf(TotalpacketsReceived));
}
}
} catch (IOException e) {
Log.i("DEU Service", "In cache");
flag = false;
e.printStackTrace();
}
finally {
try {
if(multiSocket != null) {
if(group != null)
multiSocket.leaveGroup(group);
multiSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if(mLock != null)
mLock.release();
}
}
}
private void sendResultMessage(String strPacks) {
Intent intent = new Intent("intData");
intent.putExtra("result",strPacks);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
private void sendTotalPackets(String strPacks) {
Intent intent = new Intent("intPacket");
intent.putExtra("result",strPacks);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
public int fromByteArray(byte[] bytes) {
return bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF);
}
public class TotalPackets implements Runnable{
#Override
public void run() {
byte[] requestData = new byte[1024];
InetAddress group = null;
MulticastSocket multiSocket = null;
int PORT = 5500;
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock mLock = wifi.createMulticastLock("mylock");
mLock.acquire();
try{
group = InetAddress.getByName("230.0.0.1");
multiSocket = new MulticastSocket(PORT);
multiSocket.joinGroup(group);
} catch (IOException e) {
e.printStackTrace();
}
try{
while(true)
{
DatagramPacket requestPacket = new DatagramPacket(requestData, requestData.length);
multiSocket.receive(requestPacket);
String requestString = new String(requestPacket.getData(), 0, requestPacket.getLength());
Log.i("requestString",requestString);
String[] spltStr = requestString.split(";");
packetSize = Integer.parseInt(spltStr[1].toString());
Log.i("service","Packet size is: " + spltStr[1].toString() + " Total Packs: " + spltStr[0]);
sendTotalPackets(spltStr[0].toString());
/*txtMsg = (EditText)findViewById(R.id.txtMsg);
txtMsg.setText(requestString);*/
}
} catch (IOException e) {
e.printStackTrace();
}
try{
multiSocket.leaveGroup(group);
multiSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
mLock.release();
}
}
}
So, my question is, at the service side when I receives the packet mostly 5-7% of packets are loss. It means, if I send 1000 packets of 512 bytes at 5ms of interval 50-70 packet losses at the receiving end.
Is there a way I can reduce this packet loss? Or Is there any chances of my code for improvement so that packet loss can be reduced?
Thanks in advance.
There's not much you can do.
UDP is a transport layer that does not have delivery guarantees.
Packet loss over wifi will vary based on the different makes/models/configurations of the access points and the device it runs on.
For example, 5ghz may perform better as the air waves are usually cleaner but it does not penetrate through walls as well as 2.4 ghz.
Not all Android devices use the same wifi radios.
You can actually get practically 0% packet loss if you use an access point that does multicast to unicast conversion at the MAC layer. So you use UDP in your application software. Then the access point internally does retransmissions at the 802.11 layer. For example, Cisco, and Xirrus have multicast to unicast conversion options and yield practically 0% packet loss. However, there is a price to pay as it does not scale very well because each multicast stream is sent individually to each subscribed device.
Well... What can you do in software....
Ways to "deal" with packet loss in multicast:
Forward error correction.
You can send each packet twice. AABBCCDDEE
You can send each packet twice but delayed: ABACBDCED
You can send part of the data twice: AABCCDE
Any forward error correction scheme ads more bandwidth and also increases latency.
Loss concealment
You can try to estimate the data between losses.
You haven't really stated your application so it is difficult to make suggestions on dealing with losses. With your 5ms limitation, it sounds like you are transmitting 240 frame packets of 48khz audio.
Did you try to increase the interval to >5ms? Also did you try to test this application where there was no kind of interference for wifi?
I have an application that communicates over Bluetooth Serial Port with another terminal. It can send and receive data, more specifically text.
I can send and receive data successfully when the app is on foreground, however, I would like to know how I can make it so the app can receive data when in background and show it in the activity once it comes to foreground.
I'm currently using a service with the doInBackground(). However, I don't know what else I'm missing. Please assist me.
This is my service class
package com.boson.BTComms;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.app.Service;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class BtService extends Service
{
Bluetooth bt = new Bluetooth();
static ConnectTask cTask;
Bundle bndl;
int action;
public class rxBluetooth
{
public String rxdMsg;
public boolean newData;
public boolean workerStatus;
OutputStream mmOutputStream; // Stream de salida de la conexión
InputStream mmInputStream; // Stream de entrada de la conexión
Thread workerThread; // Thread de escucha
BluetoothSocket mmSocket; // Socket que se utiliza para comunicacion entre los dispositivos Bluetooth
int readBufferPosition = 0; // Variable para bufer de lectura
}
rxBluetooth rxBT = new rxBluetooth();
#Override
public IBinder onBind(Intent intent)
{
return null;
}
public int onStartCommand(Intent intent, int flags, int startId)
{
bndl = intent.getExtras();
action = bndl.getInt("act");
//MAIN SERVICE STATE-MACHINE
switch (action)
{
case 0://Conexión
try
{
String remDev = bndl.getString("_remDev");
cTask = (ConnectTask) new ConnectTask().execute(remDev);
}
catch(Exception e)
{
Toast.makeText(this, "Could not open connection!", Toast.LENGTH_LONG).show();
Intent i = new Intent(getApplicationContext(), HomeActivity.class);
startActivity(i);
}
break;
case 1://Enviar Datos
try
{
if(rxBT.mmSocket != null && rxBT.mmSocket.isConnected() == true)
{
String msg = bndl.getString("_message");
rxBT.mmOutputStream.write(msg.getBytes());
rxBT.mmOutputStream.flush();
}
}
catch(Exception e)
{
Toast.makeText(this, "Could not send data!", Toast.LENGTH_LONG).show();
}
break;
case 2://Cerrar Conexión
rxBT.workerStatus = false;
if (rxBT.mmInputStream != null)
{
try
{
rxBT.mmInputStream.close();
}
catch (Exception e) {Log.e("BOSON", e.getMessage());}
rxBT.mmInputStream = null;
}
if (rxBT.mmOutputStream != null)
{
try
{
rxBT.mmOutputStream.close();
}
catch (Exception e) {Log.e("BOSON", e.getMessage());}
rxBT.mmOutputStream = null;
}
if (rxBT.mmSocket != null)
{
try
{
rxBT.mmSocket.close();
}
catch (Exception e) {Log.e("BOSON", e.getMessage());}
rxBT.mmSocket = null;
}
if (cTask != null)
{
cTask.cancel(true);
cTask = null;
}
break;
}
return startId;
}
private class ConnectTask extends AsyncTask<String, Void, Void>
{
protected Void doInBackground(String... params)
{
try
{
BluetoothDevice mmDevice = bt.btAdpt.getRemoteDevice(params[0]);
try
{
rxBT.mmSocket = mmDevice.createInsecureRfcommSocketToServiceRecord(mmDevice.getUuids()[0].getUuid());
rxBT.mmSocket.connect();
rxBT.mmOutputStream = rxBT.mmSocket.getOutputStream();
rxBT.mmInputStream = rxBT.mmSocket.getInputStream();
Log.e("BOSON", rxBT.mmSocket.getRemoteDevice().toString());
Log.e("BOSON", rxBT.mmOutputStream.toString());
}
catch (IOException e)
{
Log.e("BOSON", "COULD NOT OPEN SOCKET CONNECTION");
}
rxBT.workerStatus = true;
Runnable rbleReceiver = new Runnable()
{
public void run()
{
final byte delimiter = '\r';
final byte[] readBuffer = new byte[1024];
int bytesAvailable;
String rxdMsgT = "";
while(rxBT.workerStatus == true)
{
try
{
if(rxBT.mmInputStream.available() > 0)
{
bytesAvailable = rxBT.mmInputStream.available();
byte[] packetBytes = new byte[bytesAvailable];
rxBT.mmInputStream.read(packetBytes);
for(int i=0;i<bytesAvailable;i++)
{
byte b = packetBytes[i];
if(b == delimiter)
{
byte[] encodedBytes = new byte[rxBT.readBufferPosition];
System.arraycopy(readBuffer, 0, encodedBytes, 0, encodedBytes.length);
final String data = new String(encodedBytes, "US-ASCII");
rxBT.readBufferPosition = 0;
rxdMsgT = "Tu: " + data + "\n";
rxBT.newData = true;
if (rxBT.newData == true)
{
Intent intent = new Intent("com.boson.BTComms.MainActivity");
intent.putExtra("Mensaje", rxdMsgT);
sendBroadcast(intent);
rxBT.newData = false;
}
}
else
{
readBuffer[rxBT.readBufferPosition++] = b;
}
}
}
else
{
//Log.e("BOSON", "INACTIVE");
}
}
catch (IOException ex)
{
rxBT.workerStatus = false;
}
}
}
};
rxBT.workerThread = new Thread(rbleReceiver);
rxBT.workerThread.start();
}
catch(Exception e)
{
Toast.makeText(BtService.this, "Could not open connection!", Toast.LENGTH_LONG).show();
Intent i = new Intent(getApplicationContext(), HomeActivity.class);
startActivity(i);
}
return null;
}
}
public void onDestroy()
{
super.onDestroy();
}
I am attempting to connect a PIC microprocessor to a tablet app via usb. A Send button should trigger the sending of a string consist of "$$$" to the PIC. By a process of elimination, it appears to work down to the "requestWait" line at the bottom. The button stays highlighted and the app appears to hang. I suspect that no answer is arriving for the requestWait and so it waits indefinitely. I would appreciate some help. I have looked at the AdbTest and Missile Launcher apps but there is too much going on in them for my level of Android expertise.
Added later:
Looking at the code for UsbRequest queue(..), result = native_queue_direct(...).
I gather that this is native code. Where do I find it please?
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Iterator;
import android.content.Context;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbRequest;
import android.view.View;
import android.widget.Toast;
#Override
protected void onResume() {
super.onResume();
mManager = (UsbManager) getSystemService(Context.USB_SERVICE);
// check for existing devices
UsbDevice device;
HashMap<String, UsbDevice> deviceList = mManager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while (deviceIterator.hasNext()) {
device = deviceIterator.next();
if (device.getVendorId() == 1027) {
UsbInterface intf = device.getInterface(0);
if (setUsbInterface(device, intf)) {
break;
}
}
}
private UsbManager mManager;
private UsbDevice mDevice;
private UsbDeviceConnection mDeviceConnection;
private UsbInterface mInterface;
private ScorerDevice mScorerDevice ;
// ***********************************
// Sets the current USB device and interface
private boolean setUsbInterface(UsbDevice device, UsbInterface intf) {
if (mDeviceConnection != null) {
if (mInterface != null) {
mDeviceConnection.releaseInterface(mInterface);
mInterface = null;
}
mDeviceConnection.close();
mDevice = null;
mDeviceConnection = null;
}
if (device != null && intf != null) {
UsbDeviceConnection connection = mManager.openDevice(device);
if (connection != null) {
if (connection.claimInterface(intf, true)) {
toast = Toast.makeText(getApplicationContext(), "claim interface succeeded", Toast.LENGTH_SHORT);
toast.show();
mDevice = device;
mDeviceConnection = connection;
mInterface = intf;
mScorerDevice = new ScorerDevice(this, mDeviceConnection, intf);
toast = Toast.makeText(getApplicationContext(), "USB started", Toast.LENGTH_SHORT);
toast.show();
mScorerDevice.start();
return true;
} else {
toast = Toast.makeText(getApplicationContext(), "claim interface failed", Toast.LENGTH_SHORT);
toast.show();
connection.close();
}
} else {
toast = Toast.makeText(getApplicationContext(), "USB failed", Toast.LENGTH_SHORT);
toast.show();
}
}
if (mDeviceConnection == null && mScorerDevice != null) {
mScorerDevice.stop();
mScorerDevice = null;
}
return false;
}
// ***********************************
public int onClick_Send(View view) {
String dollars = "$$$";
byte[] bytes = dollars.getBytes();
int len = bytes.length;
int offset = 0;
int PacketSize = mScorerDevice.mEndpointOut.getMaxPacketSize();
if ((len > PacketSize) || (offset < 0) || (len < 0) || ((offset + len) > bytes.length))
throw new IndexOutOfBoundsException();
ByteBuffer sendBuffer = ByteBuffer.allocate(PacketSize);
UsbRequest request = new UsbRequest();
Boolean ret = request.initialize(mDeviceConnection, mScorerDevice.mEndpointOut);
if (!ret ) {
return -1;
}
ret = request.queue(sendBuffer, len);
if (!ret ) {
return -1;
}
request = mDeviceConnection.requestWait();
if (request == null) {
return -1;
}
}
I'm using a Freeduino (Arduino Uno compatible) with a Samsung Galaxy Tab 10.1 running ICS (4) and I have succeeded in writing from the Arduino to the Android, but I have not been able to read from the Android in the Arduino sketch.
Here's the Android class for the USB Accessory:
package com.kegui.test;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.util.ArrayList;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import com.kegui.test.Scripto;
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.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class USBAccess extends Activity implements Runnable, OnClickListener {
private static final String ACTION_USB_PERMISSION = "com.google.android.DemoKit.action.USB_PERMISSION";
protected static final String TAG = "KegUI";
private UsbManager mUsbManager;
private PendingIntent mPermissionIntent;
private boolean mPermissionRequestPending;
private TextView debugtext = null;
private Button button1 = null;
private Button button2 = null;
private boolean button2visible = false;
UsbAccessory mAccessory;
ParcelFileDescriptor mFileDescriptor;
FileInputStream mInputStream;
FileOutputStream mOutputStream;
private static final int MESSAGE_BUTTON_PRESSED = 1;
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.i("KegApp", "***********************Received*************************");
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (intent.getBooleanExtra(
UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
openAccessory(accessory);
} else {
Log.d(TAG, "permission denied for accessory "
+ accessory);
}
mPermissionRequestPending = false;
}
} else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (accessory != null && accessory.equals(mAccessory)) {
closeAccessory();
}
}
}
};
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(
ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
setContentView(R.layout.main);
final Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
new TempUpdateTask().execute("testing");
}
});
registerReceiver(mUsbReceiver, filter);
Log.d(TAG,"on Create'd");
}
#Override
public void onResume() {
super.onResume();
if (mInputStream != null && mOutputStream != null) {
return;
}
UsbAccessory[] accessories = mUsbManager.getAccessoryList();
UsbAccessory accessory = (accessories == null ? null : accessories[0]);
if (accessory != null) {
if (mUsbManager.hasPermission(accessory)) {
openAccessory(accessory);
} else {
synchronized (mUsbReceiver) {
if (!mPermissionRequestPending) {
mUsbManager.requestPermission(accessory,
mPermissionIntent);
mPermissionRequestPending = true;
}
}
}
} else {
Log.d(TAG, "mAccessory is null");
}
}
#Override
public void onPause() {
super.onPause();
closeAccessory();
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(mUsbReceiver);
}
private void openAccessory(UsbAccessory accessory) {
mFileDescriptor = mUsbManager.openAccessory(accessory);
if (mFileDescriptor != null) {
mAccessory = accessory;
FileDescriptor fd = mFileDescriptor.getFileDescriptor();
mInputStream = new FileInputStream(fd);
mOutputStream = new FileOutputStream(fd);
Thread thread = new Thread(null, this, "KegApp");
thread.start();
//enableControls(true);
} else {
Log.d(TAG, "accessory open fail");
}
}
public void run() {
int ret = 0;
byte[] buffer = new byte[16384];
int i;
Log.i("KegApp", "***********************in run*************************");
while (ret >= 0) {
try {
ret = mInputStream.read(buffer); // this will be always positive, as long as the stream is not closed
} catch (IOException e) {
break;
}
i = 0;
while (i < ret) {
Message m = Message.obtain(messageHandler, MESSAGE_BUTTON_PRESSED);
m.obj = buffer[i];
messageHandler.sendMessage(m);
i++;
}
}
}
private void closeAccessory() {
//enableControls(false);
try {
if (mFileDescriptor != null) {
mFileDescriptor.close();
}
} catch (IOException e) {
} finally {
mFileDescriptor = null;
mAccessory = null;
}
}
public void sendCommand(FileOutputStream mStream) {
BufferedOutputStream bo = new BufferedOutputStream(mStream);
// if (mStream != null && message.length > 0) {
try {
Log.i("KegApp", "***********************sending command now*************************");
bo.write(1); //message, 0, 3);
} catch (IOException e) {
Log.e(TAG, "write failed", e);
}
// }
}
#Override
public void onClick(View v) {
// Send some message to Arduino board, e.g. "13"
Log.e(TAG, "write failed");
}
// Instantiating the Handler associated with the main thread.
private Handler messageHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
Log.i("KegApp", "***********************message handler before " + msg.what + "************************");
try {
String load = msg.obj.toString();
Log.i("KegApp", "***********************in message handler*************************");
/*
if (button2visible==false) {
debugtext.setText("Received message: "+String.valueOf(load));
button2.setVisibility(View.VISIBLE);
button2visible = true;
} else {
debugtext.setText("");
button2.setVisibility(View.GONE);
button2visible = false;
}
*/
new TempUpdateTask().execute(load);
} catch (Exception e) {
Log.e(TAG, "message failed", e);
}
}
};
// UpdateData Asynchronously sends the value received from ADK Main Board.
// This is triggered by onReceive()
class TempUpdateTask extends AsyncTask<String, String, String> {
// Called to initiate the background activity
protected String doInBackground(String... sensorValue) {
try {
Log.i("KegApp", "***********************calling sendcommand*********************");
sendCommand(mOutputStream);
Log.i("KegApp", "*********************incoming-sensorValue*********************" );
ArduinoMessage arduinoMessage = new ArduinoMessage(sensorValue[0]);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String returnString = String.valueOf(sensorValue[0]);//String.valueOf(sensorValue[0]) + " F";
publishProgress(String.valueOf(sensorValue[0]));
return (returnString); // This goes to result
}
// Called when there's a status to be updated
#Override
protected void onProgressUpdate(String... values) {
// Init TextView Widget to display ADC sensor value in numeric.
TextView tvAdcvalue = (TextView) findViewById(R.id.tvTemp);
tvAdcvalue.setText(String.valueOf(values[0]));
// Not used in this case
}
// Called once the background activity has completed
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
closeAccessory();
}
}
}
Here's my Arduino Sketch:
#include <FHB.h>
#include <Max3421e.h>
#include <Max3421e_constants.h>
#include <Max_LCD.h>
#include <Usb.h>
//FREEDUINO ONLY------------------------------------
//END FREEDUINO ONLY------------------------------------
int pin_light_sensor_1=A0;
int pin_output_sensor=9;
int currLightLevel=0;
//int prevLightLevel=0;
//int lightStableRange=90;
int delayTime=3000;
int loopCtr=0;
char cSTX=char(2);
char cSOH=char(1);
char cEOT=char(4);
char cGS=char(29);
char cRS=char(30);
char cCR=char(13);
char cLF=char(10);
//FREEDUINO ONLY------------------------------------
AndroidAccessory acc("Company Inc.",
"Kegbot5K datawriter",
"Kegbot 5000 data writer",
"1.0",
"http://companyinc.com",
"0000000012345678");
//END FREEDUINO ONLY------------------------------------
void setup()
{
pinMode(pin_light_sensor_1, INPUT);
pinMode(pin_output_sensor, OUTPUT);
Serial.begin(57600);
//FREEDUINO ONLY------------------------------------
Serial.println("pre-power");
acc.powerOn();
Serial.println("post-power");
//END FREEDUINO ONLY------------------------------------
}
void loop()
{
byte msg[3];
if (acc.isConnected()) {
currLightLevel = analogRead(pin_light_sensor_1);
//sysPrint(delayTime*loopCtr);
//sysPrint(",");
//sysPrint(currLightLevel);
writeDataMessage("LGH01", currLightLevel);
}
delay(1000);
if (acc.isConnected()) {
int len = acc.read(msg, sizeof(msg), 1);
Serial.println(len);
if (len > 0){
for (int index=0; index < len; index++){
digitalWrite(pin_output_sensor, 1);
delay(500);
digitalWrite(pin_output_sensor, 0);
}
}
}
loopCtr++;
delay(delayTime);
}
void writeHeader(String msgType)
{
sysPrint(cSTX);
sysPrint(cSTX);
sysPrint(cSOH);
sysPrint(msgType);
sysPrint(cGS);
}
void writeFooter()
{
sysPrint(cEOT);
sysPrintLn(cEOT);
}
void writeDataMessage(String sensorID, int value)
{
writeHeader("DATA");
sysPrint(sensorID);
sysPrint(cRS);
sysPrint(value);
writeFooter();
}
void writeAlarmMessage(String sensorID, String message)
//Do we need to enforce the 5 char sensorID here? I don't think so...
{
writeHeader("ALRM");
sysPrint(sensorID);
sysPrint(cRS);
sysPrint(message);
writeFooter();
}
void sysPrint(String whatToWrite)
{
int len=whatToWrite.length();
char str[len];
whatToWrite.toCharArray(str, len);
acc.write((void *)str, len);
// acc.write(&whatToWrite, whatToWrite.length());
}
void sysPrint(char whatToWrite)
{
acc.write((void *)whatToWrite, 1);
// acc.write(&whatToWrite, 1);
}
void sysPrint(int whatToWrite)
{
acc.write((void *)&whatToWrite, 1);
// acc.write(&whatToWrite, 1);
}
void sysPrintLn(String whatToWrite)
{
int len=whatToWrite.length();
char str[len];
whatToWrite.toCharArray(str, len);
acc.write((void *)str, len);
acc.write((void *)&cCR, 1);
acc.write((void *)&cLF, 1);
// acc.write(&whatToWrite, whatToWrite.length());
// acc.write(&cCR, 1);
// acc.write(&cLF, 1);
}
void sysPrintLn(char whatToWrite)
{
acc.write((void *)whatToWrite, 1);
acc.write((void *)&cCR, 1);
acc.write((void *)&cLF, 1);
// acc.write(&whatToWrite, 1);
// acc.write(&cCR, 1);
// acc.write(&cLF, 1);
}
The sendCommand function in the Android is logging that it was sent. The acc.read function is printing length to Serial output as -1, as in no input. Speaking of which, the Android logs do not show errors, so I'm thinking this might be an Arduino thing.
My Manifest has an Intent filter that's registering the device, although permissions might have something to do with it.
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="#xml/accessory_filter" />
</activity>
Thanks in advance for any thoughts,
Sara
I have developed an RC helicopter that can be controlled using android by sending messages from the android to the arduino located on top of the Helicopter using Bluetooth Stick, i did not use usb yet for any project but when you are sending messages to the arduino you are using serial communication weather connected threw USB or Bluetooth i suggest to simply use Serial.read and every message you send to arduino end it with some symbol '#' for example just to separate messages and get the message character by character
this is the code to read the full message ended with '#' from the Serial port:
String getMessage()
{
String msg=""; //the message starts empty
byte ch; // the character that you use to construct the Message
byte d='#';// the separating symbol
if(Serial.available())// checks if there is a new message;
{
while(Serial.available() && Serial.peek()!=d)// while the message did not finish
{
ch=Serial.read();// get the character
msg+=(char)ch;//add the character to the message
delay(1);//wait for the next character
}
ch=Serial.read();// pop the '#' from the buffer
if(ch==d) // id finished
return msg;
else
return "NA";
}
else
return "NA"; // return "NA" if no message;
}
this function checks if there any message in the buffer if not it returns "NA".
if that did not help please inform.
Figured out what's going wrong - sendCommand is executing from the asynchronous TempTask so it doesn't get passed a valid reference to the FileOutputStream. I can execute sendCommand onClick from the main thread and receive on the Arduino just fine.
I have closely followed this tutorial: http://assets.en.oreilly.com/1/event/68/Building%20Android%20Accessories%20using%20the%20Open%20Accessory%20Development%20Kit%20and%20Arduino%20Presentation%201.pdf
However, I have made a few modifications so that I send ASCII values each time my text is updated. I still am unable to connect my Android devices (yes, I have multiple, from versions 2.2.3 to 2.2.7). I keep receiving the error in the onscreen Log that the Outputstreams are null. Any help would be greatly appreciated!
OpenAccessoryTest.java
package org.simonmonk.duinodroid;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import com.android.future.usb.UsbAccessory;
import com.android.future.usb.UsbManager;
public class OpenAccessoryTest extends Activity implements Runnable {
private EditText mByteField;
private EditText mResponseField;
private Button mSendButton;
private static final String ACTION_USB_PERMISSION = "com.google.android.DemoKit.action.USB_PERMISSION";
private UsbManager mUsbManager;
private PendingIntent mPermissionIntent;
private boolean mPermissionRequestPending;
private UsbAccessory mAccessory;
private ParcelFileDescriptor mFileDescriptor;
private FileInputStream mInputStream;
private FileOutputStream mOutputStream;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mByteField = (EditText) findViewById(R.id.streamingTextView1);
mResponseField = (EditText) findViewById(R.id.arduinoresponse);
mSendButton = (Button) findViewById(R.id.sendButton);
// String valueStr = mByteField.getText().toString();
mSendButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
sendMessageToArduino();
}
});
setupAccessory();
}
#Override
public Object onRetainNonConfigurationInstance() {
if (mAccessory != null) {
return mAccessory;
} else {
return super.onRetainNonConfigurationInstance();
}
}
#Override
public void onResume() {
log("Resuming");
super.onResume();
if (mInputStream != null && mOutputStream != null) {
log("Resuming: streams were not null");
return;
}
log("Resuming: streams were null");
UsbAccessory[] accessories = mUsbManager.getAccessoryList();
UsbAccessory accessory = (accessories == null ? null : accessories[0]);
if (accessory != null) {
if (mUsbManager.hasPermission(accessory)) {
openAccessory(accessory);
} else {
synchronized (mUsbReceiver) {
if (!mPermissionRequestPending) {
mUsbManager.requestPermission(accessory,
mPermissionIntent);
mPermissionRequestPending = true;
}
}
}
} else {
log("onResume:mAccessory is null");
}
}
#Override
public void onPause() {
log("Pausing");
super.onPause();
}
#Override
public void onDestroy() {
log("Destroying");
unregisterReceiver(mUsbReceiver);
super.onDestroy();
}
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
ValueMsg t = (ValueMsg) msg.obj;
log("Arduino sent: " + t.getFlag() + " " + t.getReading());
}
};
private void log(String string) {
String contents = mResponseField.getText().toString();
mResponseField.setText(contents + "\n" + string);
}
private void setupAccessory() {
log("In setupAccessory");
mUsbManager = UsbManager.getInstance(this);
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(
ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
registerReceiver(mUsbReceiver, filter);
if (getLastNonConfigurationInstance() != null) {
mAccessory = (UsbAccessory) getLastNonConfigurationInstance();
openAccessory(mAccessory);
}
}
private void openAccessory(UsbAccessory accessory) {
log("In openAccessory");
mFileDescriptor = mUsbManager.openAccessory(accessory);
if (mFileDescriptor != null) {
mAccessory = accessory;
FileDescriptor fd = mFileDescriptor.getFileDescriptor();
mInputStream = new FileInputStream(fd);
mOutputStream = new FileOutputStream(fd);
Thread thread = new Thread(null, this, "OpenAccessoryTest");
thread.start();
alert("openAccessory: Accessory openned");
log("Attached");
} else {
log("openAccessory: accessory open failed");
}
}
private void closeAccessory() {
log("In closeAccessory");
try {
if (mFileDescriptor != null) {
mFileDescriptor.close();
}
} catch (IOException e) {
} finally {
mFileDescriptor = null;
mAccessory = null;
}
}
private int composeInt(byte hi, byte lo) {
int val = hi & 0xff;
val *= 256;
val += lo & 0xff;
return val;
}
#Override
public void run() {
int ret = 0;
byte[] buffer = new byte[16384];
int i;
while (true) { // keep reading messages forever. There are prob lots of
// messages in the buffer, each 4 bytes
try {
ret = mInputStream.read(buffer);
} catch (IOException e) {
break;
}
i = 0;
while (i < ret) {
int len = ret - i;
if (len >= 2) {
Message m = Message.obtain(mHandler);
int value = composeInt(buffer[i], buffer[i + 1]);
m.obj = new ValueMsg('a', value);
mHandler.sendMessage(m);
}
i += 2;
}
}
}
public void sendMessageToArduino() {
String valueStr = mByteField.getText().toString();
try {
for (int x = 0; x < valueStr.length(); x++) {
sendCommand((byte) valueStr.charAt(x));
log("Sending to Arduino: " + (byte) valueStr.charAt(x));
}
} catch (NumberFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
alert("The Byte should be a number between 0 and 255");
}
}
public void sendCommand(byte value) {
log("Sent: " + value);
byte[] buffer = new byte[1];
buffer[0] = value;
if (mOutputStream != null) {
try {
mOutputStream.write(buffer);
} catch (IOException e) {
log("Send failed: " + e.getMessage());
}
} else {
log("Send failed: mOutStream was null");
}
}
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbAccessory accessory = UsbManager.getAccessory(intent);
if (intent.getBooleanExtra(
UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
openAccessory(accessory);
} else {
log("USB permission denied");
}
}
} else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
UsbAccessory accessory = UsbManager.getAccessory(intent);
if (accessory != null && accessory.equals(mAccessory)) {
log("Detached");
closeAccessory();
}
}
}
};
public void alert(String message) {
AlertDialog alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Alert");
alertDialog.setMessage(message);
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
return;
}
});
alertDialog.show();
}
}`
StreamingTextView.java
package org.simonmonk.duinodroid;
import android.content.Context;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.EditText;
public class StreamingTextView extends EditText {
public StreamingTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public StreamingTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public StreamingTextView(Context context) {
super(context);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
((OpenAccessoryTest) super.getContext()).sendCommand(toAscii(event));
return super.onKeyDown(keyCode, event);
}
private byte toAscii(KeyEvent event) {
byte ch = (byte) event.getUnicodeChar();
if (ch == 0) {
switch(event.getKeyCode()){
case KeyEvent.KEYCODE_DEL:
ch = 8;
break;
case KeyEvent.KEYCODE_ENTER:
ch = 10;
break;
}
}
return ch;
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Byte 0 (decimal)" />
<org.simonmonk.duinodroid.StreamingTextView
android:id="#+id/streamingTextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="StreamingTextView" >
<requestFocus />
</org.simonmonk.duinodroid.StreamingTextView>
<Button
android:id="#+id/sendButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Send to Arduino" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Log" />
<EditText
android:id="#+id/arduinoresponse"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:editable="false"
android:lines="10" />
</LinearLayout>
android version must be > to 2.2 . That start working with Google api version 2.3.4 I think