FTDI Android - create new activity - android

This code is able to make the android device as a USB host for the hardware model. It also can read data from the hardware correctly in Main Activity. However, as soon as I moved it to another activity, everything still works but the data reading is incorrect.
For instance, I'm trying to write the data read into file. First activity is to input filename and just a button to send to another activity. The code below is in the second activity
public class Temp extends Activity {
private FileOutputStream outputStream;
public static D2xxManager ftD2xx= null;
Handler mHandler = new Handler();
FT_Device ftDev = null;
int devCount = 0;
UsbDevice device = null;
TextView Text =null;
String temp = null;
_4DPoint P = null;
int rd = 0;
byte[] byt = null;
byte[] Fdata = null;
String outp = "";
String From_Serial = "";
int Min = -1;
String fileName;
Context c;
final Runnable updateResults = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
Text.setText("" + Min + '\n' + temp);
}
};
public void getData(){
try {
outputStream = openFileOutput(fileName, Context.MODE_PRIVATE);
byt = new byte[256];//{(byte)'a','b','c','d',};
Toast.makeText(getBaseContext(), "start " + fileName , Toast.LENGTH_LONG).show();
Text = (TextView)findViewById(R.id.test2);
device = (UsbDevice) getIntent().getParcelableExtra("USB");
ftD2xx = D2xxManager.getInstance(c);
ftD2xx.addUsbDevice(device);
devCount = ftD2xx.createDeviceInfoList(c);
if (devCount > 0) {
ftDev = ftD2xx.openByUsbDevice(c, device);
}
if( ftDev.isOpen() == true ) {
ftDev.setBitMode((byte)0 , D2xxManager.FT_BITMODE_RESET);
ftDev.setBaudRate(38400);
ftDev.setDataCharacteristics(D2xxManager.FT_DATA_BITS_8, D2xxManager.FT_STOP_BITS_1, D2xxManager.FT_PARITY_NONE);
ftDev.setFlowControl(D2xxManager.FT_FLOW_NONE, (byte) 0x0b, (byte) 0x0d);
Thread t = new Thread() {
public void run() {
int i;
while(true){
rd=0;
while (rd==0){
rd = ftDev.read(byt, 14);
}
for(i=0; i<rd; i++)
outp += (char)byt[i];
From_Serial = new String(outp);
P = new _4DPoint(From_Serial);
temp = String.format("%s: %f %f %f %f %d\n", From_Serial, P.R, P.G, P.B, P.L, P.camera);
try {
outputStream.write(temp.getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
outp = "";
mHandler.post(updateResults);
}
}
};
t.start();
}
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (D2xxException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_color);
// Show the Up button in the action bar.
setupActionBar();
Intent intent = getIntent();
fileName = intent.getStringExtra("File Name");
c = this;
getData();
}
The set up should be fine since it's reading data from hardware, but the data read is incorrect.
Also, I'm wondering why we need to create new thread while reading data. I tried not creating new thread and it didn't work well, but still have no idea why? I tried to contact the person who wrote the code to read data but no reply.
Any help would be really appreciated :)

You state that you receive data, therefor I think you should look at your ftDev settings. Try for example to set ftDev.setBaudRate(115200) (this worked for me) or try playing with your other ftDev Settings a little bit.
The settings I use in my programm are:
int baudRate = 115200;
byte stopBit = 1; /*1:1stop bits, 2:2 stop bits*/
byte dataBit = 8; /*8:8bit, 7: 7bit*/
byte parity = 0; /* 0: none, 1: odd, 2: even, 3: mark, 4: space*/
byte flowControl = 1; /*0:none, 1: flow control(CTS,RTS)*/
If this won't work, it is wise to first check this data communication with a computer program e.g. or to analyse the incomming 'wrong' data.

Related

AndroidThings UsbToUart cannot Rx data when run long times [close]

Hello I use android thing on raspberry pi 3, I have a problem my app use UsbToSerial and then my app can Tx but cannot Rx data when app run longtime but in first period of work my app can Rx data and app can Tx alway times
How can I fix the problem?
And this is my code
MainActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
UartService uart_api = new UartService();
uart_api.UartInit("USB1-1.2:1.0", 9600);
}
UartService.java
public class UartService extends Activity {
private static final String TAG = "LoopbackActivity";
// UART Configuration Parameters
private static final int DATA_BITS = 8;
private static final int STOP_BITS = 1;
private static final int CHUNK_SIZE = 512;
private UartDevice mLoopbackDevice;
private void openUart(String name, int baudRate) throws IOException {
mLoopbackDevice = PeripheralManager.getInstance().openUartDevice(name);
// Configure the UART
mLoopbackDevice.setBaudrate(baudRate);
mLoopbackDevice.setDataSize(DATA_BITS);
mLoopbackDevice.setParity(UartDevice.PARITY_NONE);
mLoopbackDevice.setStopBits(STOP_BITS);
}
public void UartInit(String UartName, int baudrate){
PeripheralManager manager = PeripheralManager.getInstance();
List<String> deviceList = manager.getUartDeviceList();
if (deviceList.isEmpty()) {
Log.i(TAG, "No UART port available on this device.");
} else {
Log.i(TAG, "List of available devices: " + deviceList);
}
// Attempt to access the UART device
try {
openUart(UartName, baudrate);
// Read any initially buffered data
Thread thread_read = new Thread(new ThreadUart(123));
thread_read.start();
} catch (IOException e) {
Log.e(TAG, "Unable to open UART device", e);
}
}
public class ThreadUart implements Runnable {
private int data_in;
public ThreadUart(int in) {
this.data_in = in;
}
#Override
public void run() {
while(true){
///////// Test Rx //////
if (mLoopbackDevice != null) {
// Loop until there is no more data in the RX buffer.
try {
byte[] buffer = new byte[CHUNK_SIZE];
int read;
while ((read = mLoopbackDevice.read(buffer, buffer.length)) > 0) { // <<<< when run long time this cannot Rx data
mLoopbackDevice.write(buffer, read);
}
} catch (IOException e) {
Log.w(TAG, "Unable to transfer data over UART", e);
}
}
// sleep 1 sec.
///////// Test Tx //////
String string = "Hello\r\n";
byte[] b = string.getBytes(StandardCharsets.UTF_8);
try {
mLoopbackDevice.write(b, b.length); // <<<< can Tx work!! always time
} catch (IOException e) {
e.printStackTrace();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
finarly I follow Example example, It work !! in example use felHR85’s USBSerial library
however I don't know cause of Rx lost when use UART API and then run long time

Using android nfc adaptor in android library

i wrote a sample code to sending APDU to contactless smartcard by phone nfc reader and it worked succesfully. Now i want to write a android library to perform some operations like verify PIN and etc. these functions must connect to contactless smartcard and send apdu to it and return the result. The problem is here :(
This is my sample code which works:
public class MainActivity extends Activity {
private NfcAdapter mAdapter = null;
static IsoDep myTag;
private TextView lblStatus;
private Button btnSelectApplet;
private PendingIntent mPendingIntent;
boolean mFirstDetected=false;
boolean mShowAtr=false;
private String[][] mTechLists;
private IntentFilter[] mFilters;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lblStatus = (TextView) findViewById(R.id.lblStatus);
btnSelectApplet = (Button) findViewById(R.id.btnSelect);
btnSelectApplet.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
byte[] select = new byte[] {0x00, (byte)0xa4, 0x04, 0x00, 0x09, (byte)0xa0, 0x00,
0x00, 0x03, 0x08, 0x00, 0x00, 0x10, 0x00, 0x1a};
byte[] res = transceives(select);
}
});
resolveIntent(getIntent());
mAdapter = NfcAdapter.getDefaultAdapter(this);
mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
try
{
ndef.addDataType("*/*");
}
catch (IntentFilter.MalformedMimeTypeException e)
{
throw new RuntimeException("fail", e);
}
mFilters = new IntentFilter[] { ndef, };
mTechLists = new String[][] { new String[] { IsoDep.class.getName() } };
}
private static byte[] transceives (byte[] data)
{
byte[] ra = null;
try
{
ra = myTag.transceive(data);
}
catch (IOException e)
{
}
try
{
}
catch (Exception e1)
{
e1.printStackTrace();
}
return (ra);
}
private void resolveIntent(Intent intent)
{
String action = intent.getAction();
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) || NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
Parcelable tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
final Tag t = (Tag) tag;
myTag = IsoDep.get(t);
mFirstDetected = true;
if (myTag != null) {
if (!myTag.isConnected()) {
try {
myTag.connect();
myTag.setTimeout(5000);
} catch (IOException e) {
e.printStackTrace();
return;
}
}
if (myTag.isConnected()) {
String szATR = null;
try {
mShowAtr = true;
szATR = " 3B " + getATRLeString(myTag.getHistoricalBytes()) + "80 01 " + getHexString(myTag.getHistoricalBytes()) + "" + getATRXorString(myTag.getHistoricalBytes());
} catch (Exception e) {
mShowAtr = false;
szATR = "CARD DETECTED ";
}
lblStatus.setText(szATR);
} else {
lblStatus.setText("Not Connected!");
}
if (mFirstDetected == true && myTag.isConnected()) {
} else {
lblStatus.setText("Not Connected!");
}
}
}
}
private static String getATRLeString(byte[] data) throws Exception
{
return String.format("%02X ", data.length | 0x80);
}
private static String getATRXorString(byte[] b) throws Exception
{
int Lrc=0x00;
Lrc = b.length | 0x80;
Lrc = Lrc^0x81;
for (int i=0; i < b.length; i++)
{
Lrc = Lrc^(b[i] & 0xFF);
}
return String.format("%02X ", Lrc);
}
private static String getHexString(byte[] data) throws Exception
{
String szDataStr = "";
for (int ii=0; ii < data.length; ii++)
{
szDataStr += String.format("%02X ", data[ii] & 0xFF);
}
return szDataStr;
}
#Override
protected void onNewIntent(Intent intent)
{
setIntent(intent);
resolveIntent(intent);
}
#Override
public void onResume()
{
super.onResume();
if (mAdapter != null)
{
mAdapter.enableForegroundDispatch(this, mPendingIntent, mFilters, mTechLists);
}
}
}
Sample code used enableForegroundDispatch function to detect smartcard in NFC field. When smartcard detected, onNewIntent is called.
I want put all of the code in android library module X and use it in Activity Y like
Activity Y extend X
or
X x = new X()
and call it functions. how could i implement it?
I have a problem when i want to call
mAdapter = NfcAdapter.getDefaultAdapter(this);
if i use this code:
mAdapter = NfcAdapter.getDefaultAdapter(context);// context pass from Y Activity to X(Android library)
the function
mAdapter.enableForegroundDispatch(this , mPendingIntent, mFilters, mTechLists); // In X (Android library)
doesn't work correctly because it doesn't use Y activity (it used X axtivity).
How can i solve my problem such way all code will be in X(android library)?
Thanks.
as per my understanding, you are trying to access some of the methods from other activity,
here I suggest you to create third class for that NFC module methods,
create singleton method that returns a static instance of that model class.
you can access that instance from any of your Activity.
you also can set a callback in a class and another method call from another class of activity.
Hope this will help you. ask if anything not clear.
Happy Coding :)

Writing to storage from handler

I'm trying to write the stream of my array that is coming from Bluetooth module and read from (HandleRead), to the internal storage directly. Is that possible in the first place?
Note that I am reading 100 samples per second. That means the file will fill up quickly. I am not familiar with storage, and my code isn't executed as I expected.
public class MainActivity extends ActionBarActivity implements SensorEventListener {
File Root = Environment.getExternalStorageDirectory();
File Dir = new File (Root.getAbsolutePath()+"/myAppFile");
File file = new File(Dir,"Message.txt");
#Override
protected void onCreate(Bundle savedInstanceState){
String state;
state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)){
if (!Dir.exists()){
Dir.mkdir();
}
}
private void handleRead(Message msg) {
byte[] readBuf = (byte[]) msg.obj;
String readMessage = new String(readBuf);
ByteBuffer buffer = ByteBuffer.wrap(readBuf, 0, readBuf.length);
buffer.order(ByteOrder.BIG_ENDIAN);
buffer.clear();
final String[] strNumbers = readMessage.split("\n");
for (int j = 1; j <= strNumbers.length - 2; j++) {
pressure = Integer.parseInt(readMessage2);
MyFinalPressure = (float) (9.677 +0.831 * pressure);
// trying to store directly to internal sotrage
activity.save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
FileOutputStream fileOutputStream = new FileOutputStream(activity.file);
fileOutputStream.write((int) MyFinalPressure);
fileOutputStream.close();
Toast.makeText(activity.getApplicationContext(),"Message saved ", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
}
}
It appears you are not setting the FileOutputStream to 'append' (you need to add 'true' as 2nd parameter in constructor.)
This would write over the file from the file-start every time
also your 'setOnClickListener' is INSIDE your loop. This doesn't do anything for you as far as I can tell.
I recommend always setting up UI elements in a private void setupUI() {...} method that onCreate calls. The public void onClick(View v) {buttonForSavingPresssed()} where buttonForSavingPressed(){...} is the 'logic' of your onClick() method.
This will help you clean up the class and not have stray onClickListener assignments, etc.
My guess is that either your multiple assignments is very inefficient, since clickListeners aren't cheap, or... the clickListener might not even work at all because of a timing issue (if your loop is long running and you press the button and the listener has already been swapped for a new one)
I've cleaned up your code some, There are some suggestions and some log statements that should help you figure out what is going on.
// this is inside your onCreate()
...
activity.save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) { buttonPressed();}
});
...
// Here is where you would put your logic when the button is presssed
public void buttonPressed(){
Toast.makeText(activity.getApplicationContext(),"Button Pressed ",
Toast.LENGTH_SHORT).show();
}
// you should make 'helper' functions that consolidate separate pieces of logic like this,
// that way you can more easily track what is happening in each method.
// Plus it helps keep each method shorter for ease of understanding, etc.
public void writeToFile(float finalPressure){
Log.d(LOG_TAG // where LOG_TAG is the String name of this class
"writeToFile(float) called." );
try{
// true here for 'append'
FileOutputStream fileOutputStream = new
FileOutputStream(activity.file, true);
fileOutputStream.write((int) finalPressure);
fileOutputStream.close();
}catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// now back to your handleRead, is this method called async wenever
// a message is read? Then wouldn't this be called a lot? I'm lost as to why
// you had the button in here at all.
private void handleRead(Message msg) {
Log.d(LOG_TAG // where LOG_TAG is the String name of this class
"handleRead(Message) called." );
byte[] readBuf = (byte[]) msg.obj;
String readMessage = new String(readBuf);
ByteBuffer buffer = ByteBuffer.wrap(readBuf, 0, readBuf.length);
buffer.order(ByteOrder.BIG_ENDIAN);
buffer.clear();
final String[] strNumbers = readMessage.split("\n");
Log.d(LOG_TAG // where LOG_TAG is the String name of this class
"strNumbers length: " + strNumbers.length );
for (int j = 1; j <= strNumbers.length - 2; j++) {
pressure = Integer.parseInt(readMessage2);
MyFinalPressure = (float) (9.677 +0.831 * pressure);
// trying to store directly to internal sotrage
writeToFile(MyFinalPressure);
}
}

Variables that are needed for Bluetooth Connection

Currently, I'm trying to figure out how to stay connected with a device via Bluetooth throughout Activities. I have a few variables that I initialize to get the connection going.
My previous activity flow is Main Page > User input Text page > Bluetooth Connection(SENDING INFO).
So in this way, every time I go back to the User Input Text Page, the Bluetooth connection will be reset because when I go the next page, it'll rerun all the receivers and stuffs.
Now I'm moving the Bluetooth Connection forward. Meaning now it is Main Page > Bluetooth Connection > User Input Text Page(SEND).
But after I connect on my Bluetooth Connection page, I'm not sure what variables I should bring over/save inside SharedPreferences, so that the Bluetooth connection stays and I can send right away.
//This method runs when I click a device on my ListView.
private OnItemClickListener mDeviceClickListener = new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// Cancel discovery because it's costly and we're about to connect
bluetoothAdapter.cancelDiscovery();
System.out.println("Bluetooth Adapter2 = "
+ bluetoothAdapter.cancelDiscovery());
SiriListItem item = delist.get(arg2);
mAdapter.notifyDataSetChanged();
// When device being clicked
count++;
click = 1;
// Get the device MAC address, which is the last 17 chars in the
// View
String info = item.message;
String address = info.substring(info.length() - 17);
BlueToothAddress = address;
if (click == 1) {
clientThread ct = new clientThread();
ct.start();
}
};
};
//This is the clientThread if click == 1, it'll start this.
private class clientThread extends Thread {
public void run() {
try {
//
bdDevice = bluetoothAdapter.getRemoteDevice(BlueToothAddress);
socket = bdDevice.createRfcommSocketToServiceRecord(UUID
.fromString("00001101-0000-1000-8000-00805F9B34FB"));
Message msg2 = new Message();
msg2.obj = "Please wait, connecting to server: "
+ BlueToothAddress;
msg2.what = 0;
LinkDetectedHandler.sendMessage(msg2);
socket.connect();
Log.i("tag", "This is the pairing section");
Message msg = new Message();
msg.obj = "Device connected. Sending message is allowed.";
msg.what = 0;
LinkDetectedHandler.sendMessage(msg);
readThread = new readThread();
readThread.start();
click++;
} catch (IOException e) {
Message msg = new Message();
msg.obj = "Error! Can't connect to device. Please try again.";
msg.what = 0;
LinkDetectedHandler.sendMessage(msg);
click--;
}
}
};
public class readThread extends Thread {
public void run() {
byte[] buffer = new byte[1024];
int bytes;
InputStream mmInStream = null;
String tmp = null;
try {
mmInStream = socket.getInputStream();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
while (true) {
try {
// read the data from the inputStream
if ((bytes = mmInStream.read(buffer)) > 0) {
for (int i = 0; i < bytes; i++) {
tmp = "" + buffer[i];
String st = new String(tmp);
tmp = null;
Message msg = new Message();
msg.obj = st;
msg.what = 1;
}
}
} catch (IOException e) {
try {
mmInStream.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
break;
}
}
}
}
//On Click it'll send the message stored in the editText.
buttonConnect.setOnClickListener(new View.OnClickListener() {
#SuppressLint("NewApi")
#Override
public void onClick(View arg0) {
if (count == 0) {
Toast.makeText(bluetoothtest.this,
"Please connect to a device first.",
Toast.LENGTH_LONG).show();
}
// Need API=14
else if (!socket.isConnected()) {
Toast.makeText(bluetoothtest.this,
"Connecting! Please wait.", Toast.LENGTH_LONG)
.show();
} else {
try {
sendMessageHandle(contentRow1.getText().toString(),
contentRow2.getText().toString(), contentRow3
.getText().toString(), contentRow4
.getText().toString());
// sendMessageHandle(contentRow2.getText().toString());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
So the main thing is. What method should I have in my User Input Text Page? Must I have all this method in my User Input Text Page or can I just bring over variables via SharedPreferences?
Thanks.
It is probably bad practice to be handling bluetooth connections on the main thread. You should really handle the bluetooth connection/maintenance through a Service/background thread. Your activities can then talk to the service via a BroadcastReceiver and Handles.

How to get an InputStream via bluetooth and put in a Textview?

This is my first question in SO. I am new (and excited) in Android programming and here is my PROBLEM: I am building a project using my android phone and a microcontroller. The microcontroller has a distance sensor and transmits its value. I have managed to get connected to the microcontroller and send correct signals, but I can't get the distance mesurment, or anything else. The application doesn't crash or anything it just won't get the data from the microcontroller (my computer gets the data from microcontroler (data is a string)). My code from the android app is this:
public class Accelerometer extends Activity {
// Intent request codes
private static final int REQUEST_CONNECT_DEVICE = 1;
private static final int REQUEST_ENABLE_BT = 2;
private static final int RECIEVE_MESSAGE = 3;
// Program variables
private byte microcOut;
private boolean ledStat;
private boolean connectStat = false;
private Button btnled;
private Button connect_button;
private TextView yAccel, xAccel, incoming;
protected static final int MOVE_TIME = 80;
private long lastWrite = 0;
OnClickListener myClickListener;
ProgressDialog myProgressDialog;
private Toast failToast;
private Handler mHandler,h;
private StringBuilder sb = new StringBuilder();
// Sensor object used to handle accelerometer
private SensorManager mySensorManager;
private List<Sensor> sensors;
private Sensor accSensor;
// Bluetooth Stuff
private BluetoothAdapter btAdapter = null;
private BluetoothSocket btSocket = null;
private OutputStream outStream = null;
private InputStream inStream = null;
private ConnectThread mConnectThread = null;
private ConnectedThread mConnectedThread;
private String deviceAddress = null;
// Well known SPP UUID (will *probably* map to RFCOMM channel 1 (default) if not in use);
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
//Sound Clip to make app prettier
MediaPlayer myclip;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_accelerometer);
myclip = MediaPlayer.create(this, R.raw.cartcar);
myclip.start();
// Finds buttons in .xml layout file
btnled = (Button) findViewById(R.id.led_button1);
connect_button = (Button) findViewById(R.id.connect_button1);
yAccel = (TextView) findViewById(R.id.accText1);
xAccel = (TextView) findViewById(R.id.accText2);
incoming = (TextView) findViewById(R.id.incoming);
// Set Sensor
mySensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
sensors = mySensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
if(sensors.size() > 0) accSensor = sensors.get(0);
myProgressDialog = new ProgressDialog(this);
failToast = Toast.makeText(this, R.string.failedToConnect, Toast.LENGTH_SHORT);
mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (myProgressDialog.isShowing()) {
myProgressDialog.dismiss();
}
// Check if bluetooth connection was made to selected device
if (msg.what == 1) {
// Set button to display current status
connectStat = true;
connect_button.setText(R.string.connected);
// Reset the BluCar
microcOut = 0;
ledStat = false;
write(microcOut);
}else {
// Connection failed
failToast.show();
}
}
};
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECIEVE_MESSAGE: // if receive massage
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1); // create string from bytes array
sb.append(strIncom); // append string
int endOfLineIndex = sb.indexOf("\r\n"); // determine the end-of-line
if (endOfLineIndex > 0) { // if end-of-line,
String sbprint = sb.substring(0, endOfLineIndex); // extract string
sb.delete(0, sb.length()); // and clear
incoming.setText("Data from Arduino: " + sbprint); // update TextView
}
//Log.d(TAG, "...String:"+ sb.toString() + "Byte:" + msg.arg1 + "...");
break;
}
};
};
// Check whether bluetooth adapter exists
btAdapter = BluetoothAdapter.getDefaultAdapter();
if (btAdapter == null) {
Toast.makeText(this, R.string.no_bt_device, Toast.LENGTH_LONG).show();
finish();
return;
}
// If BT is not on, request that it be enabled.
if (!btAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
}
/**********************************************************************
* Buttons for controlling BluCar
*/
connect_button.setOnClickListener(new View.OnClickListener() {
// Connect to Bluetooth Module
#Override
public void onClick(View v) {
if (connectStat) {
// Attempt to disconnect from the device
disconnect();
}else{
// Attempt to connect to the device
connect();
}
}
});
// Toggle Headlights
btnled.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (ledStat) {
microcOut = (byte) (microcOut & 124);
btnled.setText(R.string.ledbuttonON);
ledStat = false;
}else{
microcOut = (byte) (microcOut | 128);
btnled.setText(R.string.ledbuttonOFF);
ledStat = true;
}
write(microcOut);
}
});
}
/** Thread used to connect to a specified Bluetooth Device */
public class ConnectThread extends Thread {
private String address;
private boolean connectionStatus;
ConnectThread(String MACaddress) {
address = MACaddress;
connectionStatus = true;
}
public void run() {
// When this returns, it will 'know' about the server,
// via it's MAC address.
try {
BluetoothDevice device = btAdapter.getRemoteDevice(address);
// We need two things before we can successfully connect
// (authentication issues aside): a MAC address, which we
// already have, and an RFCOMM channel.
// Because RFCOMM channels (aka ports) are limited in
// number, Android doesn't allow you to use them directly;
// instead you request a RFCOMM mapping based on a service
// ID. In our case, we will use the well-known SPP Service
// ID. This ID is in UUID (GUID to you Microsofties)
// format. Given the UUID, Android will handle the
// mapping for you. Generally, this will return RFCOMM 1,
// but not always; it depends what other BlueTooth services
// are in use on your Android device.
try {
btSocket = device.createRfcommSocketToServiceRecord(SPP_UUID);
} catch (IOException e) {
connectionStatus = false;
}
}catch (IllegalArgumentException e) {
connectionStatus = false;
}
// Discovery may be going on, e.g., if you're running a
// 'scan for devices' search from your handset's Bluetooth
// settings, so we call cancelDiscovery(). It doesn't hurt
// to call it, but it might hurt not to... discovery is a
// heavyweight process; you don't want it in progress when
// a connection attempt is made.
btAdapter.cancelDiscovery();
// Blocking connect, for a simple client nothing else can
// happen until a successful connection is made, so we
// don't care if it blocks.
try {
btSocket.connect();
} catch (IOException e1) {
try {
btSocket.close();
} catch (IOException e2) {
}
}
// Create a data stream so we can talk to server.
try {
outStream = btSocket.getOutputStream();
} catch (IOException e2) {
connectionStatus = false;
}
// Send final result
if (connectionStatus) {
mHandler.sendEmptyMessage(1);
}else {
mHandler.sendEmptyMessage(0);
}
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CONNECT_DEVICE:
// When DeviceListActivity returns with a device to connect
if (resultCode == Activity.RESULT_OK) {
// Show please wait dialog
myProgressDialog = ProgressDialog.show(this, getResources().getString(R.string.pleaseWait), getResources().getString(R.string.makingConnectionString), true);
// Get the device MAC address
deviceAddress = data.getExtras().getString(DeviceList.EXTRA_DEVICE_ADDRESS);
// Connect to device with specified MAC address
mConnectThread = new ConnectThread(deviceAddress);
mConnectThread.start();
}else {
// Failure retrieving MAC address
Toast.makeText(this, R.string.macFailed, Toast.LENGTH_SHORT).show();
}
break;
case REQUEST_ENABLE_BT:
// When the request to enable Bluetooth returns
if (resultCode == Activity.RESULT_OK) {
// Bluetooth is now enabled
} else {
// User did not enable Bluetooth or an error occured
Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();
finish();
}
}
}
public void write(byte data) {
if (outStream != null) {
try {
outStream.write(data);
} catch (IOException e) {
}
}
}
public void emptyOutStream() {
if (outStream != null) {
try {
outStream.flush();
} catch (IOException e) {
}
}
}
public void connect() {
// Launch the DeviceListActivity to see devices and do scan
Intent serverIntent = new Intent(this, DeviceList.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
}
public void disconnect() {
if (outStream != null) {
try {
outStream.close();
connectStat = false;
connect_button.setText(R.string.disconnected);
} catch (IOException e) {
}
}
}
private final SensorEventListener mSensorListener = new SensorEventListener() {
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
#Override
public void onSensorChanged(SensorEvent event) {
// Checks whether to send steering command or not
long date = System.currentTimeMillis();
if (date - lastWrite > MOVE_TIME) {
yAccel.setText(" " + event.values[1]);
xAccel.setText(" " + event.values[0]);
if (event.values[1] > 2.5) {
// Turn right
microcOut = (byte) (microcOut & 248);
microcOut = (byte) (microcOut | 4);
}else if (event.values[1] < -2.5) {
// Turn left
microcOut = (byte) (microcOut & 244);
microcOut = (byte) (microcOut | 8);
}else {
// Center the steering servo
microcOut = (byte) (microcOut & 240);
}
write(microcOut);
lastWrite = date;
}
}
};
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_accelerometer, menu);
return true;
}
public void onResume() {
super.onResume();
mySensorManager.registerListener(mSensorListener, accSensor, SensorManager.SENSOR_DELAY_GAME);
}
#Override
public void onDestroy() {
emptyOutStream();
disconnect();
if (mSensorListener != null) {
mySensorManager.unregisterListener(mSensorListener);
}
super.onDestroy();
myclip.release();
}
private class ConnectedThread extends Thread {
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[256]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer); // Get number of bytes and message in "buffer"
h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget(); // Send to message queue Handler
} catch (IOException e) {
break;
}
}
}
/* Call this from the main activity to send data to the remote device */
public void write(String message) {
byte[] msgBuffer = message.getBytes();
try {
mmOutStream.write(msgBuffer);
} catch (IOException e) {
}
}
}
}
I have read everything over the subject (BluetoothChat, projects of people on the internet ...) and I am very tired. Any help is much appreciated.
--EDIT--
I have managed to get the inputstream into my texteview. My problem now is that my application when it is trying to connect to my device (microcontroller or my pc) gets stuck in the progressdialog (it is connected to the device but the progressdialog will not go away)and waits for something to come in. After a while (like 5-6 secs) even if something comes in it remains stuck and I have to force it to close. I think the problem is in the way the handler handles the thread. In the debugger there is no problem all threads run ok.
The changes in my code are:
In my ConnectThread:
`/** Thread used to connect to a specified Bluetooth Device */
public class ConnectThread extends Thread {
private String address;
private boolean connectionStatus;
ConnectThread(String MACaddress) {
address = MACaddress;
connectionStatus = true;
}
public void run() {
// When this returns, it will 'know' about the server,
// via it's MAC address.
try {
BluetoothDevice device = btAdapter.getRemoteDevice(address);
// We need two things before we can successfully connect
// (authentication issues aside): a MAC address, which we
// already have, and an RFCOMM channel.
// Because RFCOMM channels (aka ports) are limited in
// number, Android doesn't allow you to use them directly;
// instead you request a RFCOMM mapping based on a service
// ID. In our case, we will use the well-known SPP Service
// ID. This ID is in UUID (GUID to you Microsofties)
// format. Given the UUID, Android will handle the
// mapping for you. Generally, this will return RFCOMM 1,
// but not always; it depends what other BlueTooth services
// are in use on your Android device.
try {
btSocket = device.createRfcommSocketToServiceRecord(SPP_UUID);
} catch (IOException e) {
connectionStatus = false;
}
}catch (IllegalArgumentException e) {
connectionStatus = false;
}
// Discovery may be going on, e.g., if you're running a
// 'scan for devices' search from your handset's Bluetooth
// settings, so we call cancelDiscovery(). It doesn't hurt
// to call it, but it might hurt not to... discovery is a
// heavyweight process; you don't want it in progress when
// a connection attempt is made.
btAdapter.cancelDiscovery();
// Blocking connect, for a simple client nothing else can
// happen until a successful connection is made, so we
// don't care if it blocks.
try {
btSocket.connect();
} catch (IOException e1) {
try {
btSocket.close();
} catch (IOException e2) {
}
}
// Create a data stream so we can talk to server.
try {
outStream = btSocket.getOutputStream();
} catch (IOException e2) {
connectionStatus = false;
}
try{
inStream = btSocket.getInputStream();
}catch (IOException e2){
connectionStatus = false;
}
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (connectionStatus) {
try {
byte[] b = new byte[64]; // buffer store for the stream
// Read from the InputStream
bytes = inStream.read(b); // Get number of bytes and message in "buffer"
mHandler.obtainMessage(RECIEVE_MESSAGE, bytes, -1, b).sendToTarget(); // Send to message queue Handler
} catch (IOException e) {
break;
}
}
// Send final result
if (connectionStatus) {
mHandler.obtainMessage(1);
}else {
mHandler.sendEmptyMessage(0);
}
}
}
`
And in my mHandler in my onCreate method:
mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (myProgressDialog.isShowing()) {
myProgressDialog.dismiss();
}
// Check if bluetooth connection was made to selected device
if (msg.what == 1) {
// Set button to display current status
connectStat = true;
connect_button.setText(R.string.connected);
// Reset the BluCar
microcOut = 0;
ledStat = false;
write(microcOut);
}else if (msg.what == 2){
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1); // create string from bytes array
sb.append(strIncom); // append string
int endOfLineIndex = sb.indexOf("."); // determine the end-of-line
if (endOfLineIndex > 0) { // if end-of-line,
String sbprint = sb.substring(0, endOfLineIndex); // extract string
sb.delete(0, sb.length()); // and clear
incoming.setText(sbprint); // update TextView
connectStat = true;
connect_button.setText(R.string.connected);
}else{
incoming.setText("Problem!");
}
}else {
// Connection failed
failToast.show();
}
}
};
Another thing I need is how to empty the buffer when it is full.
PS: Thanks EVERYONE for his/her help I am really grateful.
As an alternative to using the handler, just get the information in the run of the thread..
I have done it this way and it works for me.
public void run() {
byte[] buffer = new byte[128]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
bytes = mmInStream.read(buffer);
byte[] readBuf = (byte[]) buffer;
String strIncom = new String(readBuf, 0, bytes); // create string from bytes array
sb.append(strIncom); // append string
int endOfLineIndex = sb.indexOf("\r\n"); // determine the end-of-line
if (endOfLineIndex > 0) {
// add the current string to eol to a local string
String sbprint = sb.substring(0, endOfLineIndex);
// get the start and end indexes of the heading
int startHeading = sb.indexOf("HE");
int endHeading = sb.indexOf("/HE");
// set the heading
Henry.this.setCurrentHeading(sb.substring((startHeading + 2), endHeading));
// get the start and end indexes of the front range
int startFrontRange = sb.indexOf("FR");
int endFrontRange = sb.indexOf("/FR");
// get the front range
Henry.this.currentFrontRange = sb.substring((startFrontRange + 2), endFrontRange);
... ( grab all the information you need here ) ...
// debugging output what we have
// System.out.println("recv: " + sbprint);
// clean out the sb to ready next run
sb.delete(0, sb.length());
}
I save all the information retrieved from the serial connection in my Application (Henry), then any Activity that wants to use the info gets it from the application. If the view needs to have a updated perspective on the information, I add a timer to the view to kick of a refresh method as often as I like. This has the added advantage of being able to use the information from anywhere in your android application.
I send about 10 data points from the arduino to the device and about 3 data points from the device to the arduino this way. I added my own markup around the datapoints to identify them.
Hope this helps!

Categories

Resources