I'm programming a code to open my room's door. But I have an issue.
The TextView.setText does not keep the new String I can see the String changed when the system ask to the user if allow enable Bluetooth textViewBluetooth.setText works, but when the bluetooth is enabled the textViewBluetooth returns to the original String setted on activity_main.xml and I never see it update again even setting text on an special button.
I already debug my code, i can see the setText called in TextView but still have no update string.
I try to add a new TextView but I get the same issue in both TextView.
I comment the bluetoothThread class but the problem persist.
Thanks for your time.
public class MainActivity extends ActionBarActivity {
private static final int REQUEST_ENABLE_BT = 1;
private static final int RESULT_SETTINGS = 1;
private BluetoothAdapter mBTadapter = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice>pairedDevices;
private BluetoothThread mBluetoothThread = null;
final String deviceAddress = "98:D3:31:20:0B:C9";
String SN = null;
TextView textViewBluetooth;
ImageView imageViewBT;
ImageView imageViewAbrir;
ImageView imageViewCerrar;
boolean NewDevice = false;
ArrayList listNoBondedDevices = new ArrayList();
ArrayAdapter<String> mNewDevicesArrayAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textViewBluetooth = (TextView) findViewById(R.id.textView01);
imageViewBT = (ImageView) findViewById(R.id.imageViewBT);
imageViewAbrir = (ImageView) findViewById(R.id.imageViewAbrir);
imageViewCerrar = (ImageView) findViewById(R.id.imageViewCerrar);
mNewDevicesArrayAdapter = new ArrayAdapter<String>
(this,android.R.layout.simple_list_item_1,listNoBondedDevices);
registerReceiver(mReceiver,new IntentFilter(BluetoothDevice.ACTION_FOUND));
mBluetoothThread = new BluetoothThread();
}
#Override
protected void onResume(){
super.onResume();
if(mBTadapter.isEnabled()){
if(!mBluetoothThread.btSocketConnected) {
setContentView(R.layout.activity_main);
tryConnectBTdevice(deviceAddress);
}
}
else {
intentEnableBT();
}
}
void intentEnableBT(){
textViewBluetooth.setText("Encendiendo bluetooth");
Intent intentEnableBT = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intentEnableBT, REQUEST_ENABLE_BT);
}
void tryConnectBTdevice(String address){
if(address != null && address != "00:00:00:00:00:00") {
BluetoothDevice mBTdevice = mBTadapter.getRemoteDevice(address);
if (!mBluetoothThread.btSocketConnected) {
textViewBluetooth.setText("Conectando a\n" + address.toString());
mBluetoothThread.connect(mBTdevice);
}
}
}
protected void onActivityResult(int requestCode, int resultCode, Intent data){
switch (requestCode){
case REQUEST_ENABLE_BT:
if(resultCode == Activity.RESULT_OK){
textViewBluetooth.setText("Bluetooth encendido");
tryConnectBTdevice(deviceAddress);
}
else if(resultCode == Activity.RESULT_CANCELED){
textViewBluetooth.setText("No se logró encender Bluetooth");
}
break;
}
}
}
My BluetoothThread:
public class BluetoothThread {
boolean bconnectedthread = false;
boolean bconnectthread = false;
boolean bconnectthreadstart = false;
boolean brun = false;
boolean bconnectedsynchronized = false;
boolean btSocketConnected = false;
private BluetoothAdapter mBluetoothAdapter = null;
private static final UUID MY_UUID =
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private ConnectedThread mConnectedThread;
private ConnectThread mConnectThread;
public void write(byte[] out) {
ConnectedThread r;
synchronized (this) {
r = mConnectedThread;
}
r.write(out);
}
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
BluetoothSocket tmp = null;
mmDevice = device;
bconnectthread = true;
try {
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.cancelDiscovery();
brun=true;
try {
mmSocket.connect();
btSocketConnected = true;
} catch (IOException connectException) {
try {
mmSocket.close();
} catch (IOException closeException) { }
return;
}
connected(mmSocket);
}
public void cancel() {
try {
mmSocket.close();
btSocketConnected = false;
} catch (IOException e) { }
}
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public Handler mHandler = null;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
bconnectedthread = true;
Message message;
Handler mHandler;
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024];
int bytes; // bytes returned from read()
while (true) {
try {
bytes = mmInStream.read(buffer);
//mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
// .sendToTarget();
} catch (IOException e) {
break;
}
}
}
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) {
}
}
public void disconnectDevice() {
if (mmSocket.isConnected()) {
try {
mmSocket.close();
btSocketConnected = false;
} catch (IOException e) {
}
}
}
}
public synchronized void disconnect(){
mConnectedThread.disconnectDevice();
}
public synchronized void connect(BluetoothDevice device)
{
bconnectthreadstart=true;
mConnectThread = new ConnectThread(device);
mConnectThread.start();
}
public synchronized void connected(BluetoothSocket socket) {
bconnectedsynchronized=true;
mConnectedThread = new ConnectedThread(socket);
mConnectedThread.start();
}
}
My activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="com.example.automovil.app.MainActivity">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imageViewBT"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:src="#drawable/bluetooth"
android:onClick="onSyncBT" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="#+id/textView01"
android:layout_below="#+id/imageViewBT"
android:layout_centerHorizontal="true"
android:layout_marginTop="39dp"
android:textColor="#00026a"
android:text="Bluetooth"
android:enabled="true"
android:editable="false"
android:clickable="false"
android:autoText="false"
android:autoLink="none" />
</RelativeLayout>
Sorry for my English grammar :\
Thanks a lot for your time again.
Abraham Jaime
You're calling 'setContentView' in onResume. Call that in onCreate.
onActivityResult is called BEFORE onResume, and you're doing your own multithreading here, which can be rough. Especially in this case.
tryConnectBTdevice is called from onActivityResult, which then starts a thread, but 99% of the time you'll probably wind up in in onResume before all of that happens, which means your code calls setContentView again, AND tryConnectBTdevice again.
You're referencing boolean primitives from multiple threads to check for status, which isn't great. Should probably use AtomicBoolean, but that's probably not a huge issue.
What would get a long talk from me if we were working together is eating your IOException's. Error control is very important. Those are being thrown for a reason. Its probably blowing up because you're already connected, which would've tipped you off to the double-call situation.
Simple answer, assuming you're going to ignore all my warnings about exceptions. Don't call setContentView in onResume, and don't call tryConnectBTdevice in onActivityResult, because you're calling it from onResume anyway.
If this is for your room, OK. If you're making a product, I'd strongly advise a rewrite of the threading code.
Related
I am working with my diploma thesis and I have problem with communication Arduino -> Android using bluetooth.
This is my app:
Activity where I want to display distance to obstruction
In the TextView, I want to put data from Arduino with the distance and I need idea, I can't find something, how sending data from different sensors to different Views (for example front , back bumper, left and right).
Here you have arduino code:
#include <SoftwareSerial.h>
// Mid-back sensor
#define trigPinLeft 11
#define echoPinLeft 10
// Right-back sensor (looking from back)
#define trigPinRight 7
#define echoPinRight 6
SoftwareSerial btSerial = SoftwareSerial(0,1);
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
btSerial.begin(115200);
// Mid-back sensor
pinMode(trigPinLeft, OUTPUT);
pinMode(echoPinLeft, INPUT);
// Right-back sensor
pinMode(trigPinRight, OUTPUT);
pinMode(echoPinRight, INPUT);
}
void loop() {
// put your main code here, to run repeatedly:
long durationLeft, distanceLeft;
digitalWrite(trigPinLeft, LOW);
delayMicroseconds(5);
digitalWrite(trigPinLeft, HIGH);
delayMicroseconds(5);
digitalWrite(trigPinLeft, LOW);
durationLeft = pulseIn(echoPinLeft, HIGH);
distanceLeft = (durationLeft *0.034 / 2);
if (distanceLeft>=400 || distanceLeft<=18){
Serial.println("Out of range");
btSerial.println("Out of range");
}
else{
Serial.print("BACK LEFT: ");
Serial.print(distanceLeft);
Serial.println(" cm");
btSerial.println(distanceLeft + "cm");
}
//delayMicroseconds(1);
long durationRight, distanceRight;
digitalWrite(trigPinRight, LOW);
delayMicroseconds(5);
digitalWrite(trigPinRight, HIGH);
delayMicroseconds(10);
digitalWrite(trigPinRight, LOW);
durationRight = pulseIn(echoPinRight, HIGH);
distanceRight = (durationRight *0.034 / 2);
if (distanceRight>=400 || distanceRight<=18){
Serial.println("Out of range");
btSerial.println("Out of range");
}
else{
Serial.print("BACK RIGHT: ");
Serial.print(distanceRight);
Serial.println(" cm");
btSerial.println(distanceRight + "cm");
}
delay(10000);
}
This is Android-Studio code where I want one time get data from Arduino to one textView (not working):
public class HomeActivity extends AppCompatActivity {
ImageView imageView;
TextView rearLeft,rearMid,rearRight,frontLeft,frontMid,frontRight;
public static final String PREFS_NAME = "ParkingPrefsFile";
public static final String FIRST_TIME = "firstTime";
public static final String IMAGE_VAL = "imageValue";
private BluetoothServerSocket mmServerSocket;
private BluetoothAdapter mAdapter;
private BluetoothDevice mDevice;
private static final UUID MY_UUID = UUID.fromString("5951c386-e2e7-485d-aebe-a32eec769f7b");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
imageView = (ImageView) findViewById(R.id.carView);
rearLeft = (TextView) findViewById(R.id.rearLeftText);
rearMid = (TextView) findViewById(R.id.rearMidText);
rearRight = (TextView) findViewById(R.id.rearRightText);
frontLeft = (TextView) findViewById(R.id.frontLeftText);
frontMid = (TextView) findViewById(R.id.frontMidText);
frontRight = (TextView) findViewById(R.id.frontRightText);
BluetoothSocket socket = null;
mAdapter = BluetoothAdapter.getDefaultAdapter();
SharedPreferences sharedPreferences = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
boolean firstTime = sharedPreferences.getBoolean(FIRST_TIME,false);
if(!firstTime){
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean(FIRST_TIME,true);
int image = getIntent().getIntExtra("image", R.drawable.ic_default);
imageView.setImageResource(image);
editor.putString(IMAGE_VAL, String.valueOf(getIntent().getIntExtra("image",R.drawable.ic_default)));
editor.commit();
}
else {
SharedPreferences.Editor editor = sharedPreferences.edit();
int image = getIntent().getIntExtra("image", Integer.parseInt(sharedPreferences.getString(IMAGE_VAL,null )));
imageView.setImageResource(image);
editor.putString(IMAGE_VAL, String.valueOf(getIntent().getIntExtra("image",image)));
editor.commit();
}
/*try{
//mmServerSocket = mAdapter.listenUsingInsecureRfcommWithServiceRecord("My Adapter", MY_UUID);
mmServerSocket.accept();
} catch (IOException e) {
e.printStackTrace();
}*/
/*byte[] buffer = new byte[256];
int bytes;
try{
mmServerSocket.close();
InputStream inputStream = null;
OutputStream outputStream = null;
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
DataInputStream mmInputStream = new DataInputStream(inputStream);
DataOutputStream mmOutputStream = new DataOutputStream(outputStream);
bytes = mmInputStream.read(buffer);
String readMessage = new String(buffer, 0 , bytes);
rearLeft.setText(readMessage);
} catch (IOException e) {
e.printStackTrace();
}*/
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.home_activity_menu,menu);
return true;
}
}
I compiled and runed app, but after I saw splashscreen, I had white screen and lag on the phone.
I hadn't errors in Android-Studio.
Thanks for help.
You clearly seem to have threading issue.
In your HomeActivity you have commented out the code that allows to open a Bluetooth Server on your Phone so that your Arduino device may connect to it, supplying the relevant UUID and other relevant parameters in RFCOM mode.
That code, however, is network-related and blocking and therefore should never be executed on the app UI Thread which is responsible to handle all UI tasks such as displaying views, monitoring user interactions (touch events) etc.
This is the reason why your phone displays a white screen with lag.
So you should definitely execute the Bluetooth logic on a separate thread.
I'd propose the following class to handle all bluetooth-related logic. It's very straightforward.
public class BluetoothHandler {
private final Handler handler;
private final BluetoothAdapter bluetoothAdapter;
#Nullable
private BluetoothServerSocket serverSocket;
private BluetoothSocket bluetoothSocket;
public BluetoothHandler(Context context) {
final HandlerThread ht = new HandlerThread("Bluetooth Handler Thread", Thread.NORM_PRIORITY);
ht.start(); // starting thread
this.handler = new Handler(ht.getLooper());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
this.bluetoothAdapter = ((BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter();
} else {
this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
}
}
public void startBluetoothServer() {
// execute code in our background worker thread
this.handler.post(new Runnable() {
#Override
public void run() {
try {
serverSocket = bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord("name", "your UUID");
bluetoothSocket = serverSocket.accept(); // will wait as long as possible (no timeout) so there is blocking
// do your logic to retrieve in and out put streams to read / write data from / to your Arduino device
} catch (IOException ioe) {
}
}
});
}
#AnyThread
public void writeData(byte[] data) {
// remember, all network operation are to be executed in a background thread
this.handler.post(new Runnable() {
#Override
public void run() {
// write data in output stream
}
});
}
#AnyThread
public void readData(OnDataReadCallback callback) {
// remember, all network operation are to be executed in a background thread
this.handler.post(new Runnable() {
#Override
public void run() {
// read data and notify via callback.
}
});
}
#AnyThread // should be call from your Activity onDestroy() to clear resources and avoid memory leaks.
public void termainte() {
try {
if (serverSocket != null) {
serverSocket.close();
}
if (bluetoothSocket != null) {
bluetoothSocket.close();
}
} catch (IOException ioe) {
}
this.handler.getLooper().quit(); // will no longer be usable. Basically, this class instance is now trash.
}
public interface OnDataReadCallback {
#WorkerThread // watch out if you need to update some view, user your Activity#runOnUiThread method !
void onDataRead(byte[] data);
}
}
I'm working on a OBDII reading app to read basic data such as (in this case) voltage. I've tried other apps and it works just fine to read the voltage of the OBDII adapter, so there's nothing wrong with the adapter itself.
I'm using the OBDII api from pires on github. When connection to my OBDII via Bluetooth successfully I get 0,0V and after that I get a Error saying: "Error running 01 42, response: ...UNABLETOCONNECT" (you can see this in the log cat below)
BTHandler.java
public class BTHandler {
public static final int STATE_NONE = 0; // we're doing nothing
public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
public static final int STATE_CONNECTED = 3; // now connected to a remote device
final ArrayList<String> devices = new ArrayList();
private final Handler mHandler;
private BluetoothAdapter mAdapter;
private BluetoothDevice device;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
private BluetoothSocket socket;
private String status;
private int pPlatform = Constants.SPA;
private int mState;
private boolean connectionStatus = false;
public BTHandler(Context context, Handler handler) { // Konstruktor
mAdapter = BluetoothAdapter.getDefaultAdapter();
mHandler = handler;
}
public void write(String s) {
mConnectedThread.sendRawCommand(s);
Log.v("write", "write");
}
public void connect(String deviceAddress) {
mConnectThread = new ConnectThread(deviceAddress);
mConnectThread.start();
}
private void guiHandler(int what, int arg1, String obj) {
Message msg = mHandler.obtainMessage();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.sendToTarget();
}
private class ConnectThread extends Thread {
BluetoothSocket tmp = null;
private BluetoothSocket mmSocket;
public ConnectThread(String deviceAddress) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
device = mAdapter.getRemoteDevice(deviceAddress);
BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device = mAdapter.getRemoteDevice(deviceAddress);
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
try {
tmp = device.createRfcommSocketToServiceRecord(uuid);
//socket.connect();
//Log.v("connect", "connect");
} catch (IOException e) {
//e.printStackTrace();
//Log.v("exception", "e");
}
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
mAdapter.cancelDiscovery();
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes;
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
Log.v("connect", "connect");
} catch (IOException connectException) {
Log.v("connectException", "e");
try {
mmSocket.close();
Log.v("close", "close");
} catch (IOException closeException) {
Log.v("closeException", "e");
}
guiHandler(Constants.TOAST, Constants.SHORT, "Connection Failed");
return;
}
guiHandler(Constants.CONNECTION_STATUS, Constants.STATE_CONNECTED, "");
mConnectedThread = new ConnectedThread(mmSocket);
mConnectedThread.start();
}
}
private class ConnectedThread extends Thread {
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private BluetoothSocket mmSocket;
private ObdMultiCommand multiCommand;
public ConnectedThread(BluetoothSocket socket) {
connectionStatus = true;
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
switch (pPlatform) {
case Constants.SPA:
multiCommand = new ObdMultiCommand();
multiCommand.add(new OdbRawCommand(SPA.VOLTAGE));
break;
}
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.v("e", "e");
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
OBDcmds();
// Keep listening to the InputStream until an exception occurs
try {
ModuleVoltageCommand voltageCommand = new ModuleVoltageCommand();
while (!Thread.currentThread().isInterrupted()) {
//System.out.println("Inside while");
// TODO handle commands result
Log.d("d", "Voltage: " + voltageCommand.getFormattedResult());
try {
voltageCommand.run(mmInStream, mmOutStream);
voltageCommand.getFormattedResult();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("inside catch before while");
}
// Get the input and output streams, using temp objects because
// member streams are final
/*
try {
ModuleVoltageCommand voltageCommand = new ModuleVoltageCommand();
while (!Thread.currentThread().isInterrupted()) {
voltageCommand.run(mmSocket.getInputStream(), mmSocket.getOutputStream());
voltageCommand.getFormattedResult();
Log.d("Log", "Voltage:" + voltageCommand.getFormattedResult());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
*/
//ModuleVoltageCommand voltageCommand = new ModuleVoltageCommand();
/*while (!Thread.currentThread().isInterrupted()) {
try {
voltageCommand.run(socket.getInputStream(), socket.getOutputStream());
voltageCommand.getCalculatedResult();
Log.d("Log", "Voltage:" + voltageCommand.getResultUnit());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}*/
}
private void OBDcmds() { // execute commands
try {
new EchoOffCommand().run(mmInStream, mmOutStream);
new LineFeedOffCommand().run(mmInStream, mmOutStream);
new TimeoutCommand(100).run(mmInStream, mmOutStream);
new SelectProtocolCommand(ObdProtocols.AUTO).run(mmInStream, mmOutStream);
//ISO_15765_4_CAN
} catch (Exception e) {
Log.v("OBDcmds", "e");
// handle errors
}
}
// CALL this to MainActivity
public void sendRawCommand(String s) {
try {
} catch (Exception e) {
Log.v("sendRawCommand", "e");
}
}
/*
// Call this from the main activity to send data to the remote device
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) {
}
}
*/
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button b1;
BluetoothAdapter mAdapter;
FragmentHostCallback mHost;
BTHandler btHandler;
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case Constants.MESSAGE_STATE_CHANGE:
switch (msg.arg1) {
case BTHandler.STATE_CONNECTED:
setContentView(R.layout.activity_connected);
Toast.makeText(getApplicationContext(), R.string.title_connected_to, Toast.LENGTH_SHORT).show();
Log.v("Log", "Connected");
break;
case BTHandler.STATE_NONE:
Toast.makeText(getApplicationContext(), R.string.title_not_connected, Toast.LENGTH_SHORT).show();
break;
}
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btHandler = new BTHandler(MainActivity.this, mHandler);
b1 = (Button) findViewById(R.id.connect);
b1.setOnClickListener(this);
mAdapter = BluetoothAdapter.getDefaultAdapter();
//init();
if (mAdapter == null) {
Toast.makeText(getApplicationContext(), R.string.device_not_supported, Toast.LENGTH_LONG).show();
finish();
} else {
if (!mAdapter.isEnabled()) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 1);
}
}
//BTHandler btHandler = new BTHandler(MainActivity.this, mHandler);
//btHandler.connect("");
}
public void onClick(View v) {
int id = v.getId();
//String voltage = ("ATRV");
switch (id) {
case R.id.connect:
onConnect(); //Operation
Log.v("Log", "Pressed onClick");
break;
case R.id.getValue:
btHandler.write(SPA.VOLTAGE);
Log.v("getValue","" + SPA.VOLTAGE);
break;
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_CANCELED) {
Toast.makeText(getApplicationContext(), R.string.enable_bluetooth, Toast.LENGTH_SHORT).show();
finish();
}
}
private void onConnect() {
ArrayList deviceStrs = new ArrayList();
final ArrayList<String> devices = new ArrayList();
BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
Set pairedDevices = mAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (Object device : pairedDevices) {
BluetoothDevice bdevice = (BluetoothDevice) device;
deviceStrs.add(bdevice.getName() + "\n" + bdevice.getAddress());
devices.add(bdevice.getAddress());
}
}
// show list
final AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.select_dialog_singlechoice,
deviceStrs.toArray(new String[deviceStrs.size()]));
alertDialog.setSingleChoiceItems(adapter, -1, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
int position = ((AlertDialog) dialog).getListView().getCheckedItemPosition();
String deviceAddress = devices.get(position);
btHandler.connect(deviceAddress);
//btHandler.write();
}
});
alertDialog.setTitle("Paired devices");
alertDialog.show();
}
#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);
}
}
Constants.java
public interface Constants {
int MESSAGE_STATE_CHANGE = 1;
int TOAST = 1;
int SHORT = 0;
int STATE_CONNECTED = 3;
int CONNECTION_STATUS = 1;
int MESSAGE_DEVICE_NAME = 4;
String DEVICE_NAME = "device_name";
int SPA = 1;
}
SPA.java
public interface SPA {
String VOLTAGE = "AT RV";
}
I cant connect to remote Bluetooth device. i can see paired and founded devices in ListView, but when i click on item(name of my PC or nexus 5) in the ListView nothing happens. Bluetoth pairing request window dont appears.
Manifest.xml
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
activity_main.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp">
<LinearLayout
android:layout_gravity="center_horizontal"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="#+id/button_enable_BT"
android:layout_marginRight="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/enableBT"/>
<Button
android:id="#+id/button_start_discovery"
android:layout_marginRight="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/start_discovery_button"/>
<Button
android:id="#+id/button_stop_discovery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/stop_discovery_button"/>
</LinearLayout>
<TextView
android:id="#+id/status"
android:hint="#string/status"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:text="#string/paired_devices"/>
<ListView
android:id="#+id/paired_list"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<LinearLayout
MainActivity.java
public class MainActivity extends Activity {
private final static int REQUEST_ENABLE_BT = 1;
private final static int REQUEST_COARSE_LOCATION_PERMISSIONS = 2;
UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
BluetoothAdapter mBluetoothAdapter;
ListView pairedList;
ListView newList;
Button mStart;
Button mStop;
Button mEnableBT;
TextView status;
ArrayAdapter<String> mArrayAdapter;
ArrayList<BluetoothDevice> devices;
IntentFilter filter;
String[] names;
ConnectThread mConnectThread;
ConnectedThread mConnectedThread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
devices.add(device);
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
pairedList.setAdapter(mArrayAdapter);
mStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
doDiscovery();
}
});
mStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mBluetoothAdapter.cancelDiscovery();
}
});
mEnableBT.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
});
AdapterView.OnItemClickListener itemClickListener = new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(mBluetoothAdapter.isDiscovering()){
mBluetoothAdapter.cancelDiscovery();
}
BluetoothDevice selectedDevice = devices.get(position);
mConnectThread = new ConnectThread(selectedDevice);
mConnectThread.start();
}
};
pairedList.setOnItemClickListener(itemClickListener);
filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
registerReceiver(mReceiver, filter);
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mReceiver, filter);
filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
registerReceiver(mReceiver, filter);
}
#Override
protected void onDestroy() {
super.onDestroy();
mBluetoothAdapter.cancelDiscovery();
unregisterReceiver(mReceiver);
}
public void init(){
names = new String[10];
devices = new ArrayList<>();
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
status = (TextView)findViewById(R.id.status);
mStart = (Button)findViewById(R.id.button_start_discovery);
mStop = (Button)findViewById(R.id.button_stop_discovery);
mEnableBT = (Button)findViewById(R.id.button_enable_BT);
pairedList = (ListView)findViewById(R.id.paired_list);
mArrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1);
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
if(BluetoothAdapter.STATE_ON == state){
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
devices.add(device);
}
}
}
if(BluetoothAdapter.STATE_OFF == state){
mArrayAdapter.clear();
devices.clear();
}
}
if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){
status.setText("Discovery started");
}
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
status.setText("Device found");
if(device.getBondState() != BluetoothDevice.BOND_BONDED) {
if(mArrayAdapter.getPosition(device.getName()+"\n"+device.getAddress()) < 0){
mArrayAdapter.add(device.getName()+"\n"+device.getAddress());
devices.add(device);
status.setText("!!!");
}
}
}
if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
status.setText("Discovery stopped");
}
}
};
public void doDiscovery(){
int hasPermission = checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION);
if (hasPermission == PackageManager.PERMISSION_GRANTED) {
if(mBluetoothAdapter.isDiscovering()){
mBluetoothAdapter.cancelDiscovery();
}
mBluetoothAdapter.startDiscovery();
}
requestPermissions(new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION},
REQUEST_COARSE_LOCATION_PERMISSIONS);
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_COARSE_LOCATION_PERMISSIONS: {
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if(mBluetoothAdapter.isDiscovering()){
mBluetoothAdapter.cancelDiscovery();
}
mBluetoothAdapter.startDiscovery();
} else {
Toast.makeText(this,
getResources().getString(R.string.permission_failure),
Toast.LENGTH_LONG).show();
mBluetoothAdapter.cancelDiscovery();
}
return;
}
}
}
public synchronized void connected(BluetoothSocket socket) {
// Cancel the thread that completed the connection
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
// Cancel any thread currently running a connection
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(socket);
mConnectedThread.start();
}
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mmDevice = device;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
mBluetoothAdapter.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
mmSocket.close();
} catch (IOException closeException) { }
return;
}
// Do work to manage the connection (in a separate thread)
connected(mmSocket);
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = 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[1024]; // 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);
// Send the obtained bytes to the UI activity
} catch (IOException e) {
break;
}
}
}
/* Call this from the main activity to send data to the remote device */
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
}
For 6.0 (API 23) up, now you need to ask permissions on runtime, declaring them on the manifest is not enough. Because of that, you need to do something like this: https://stackoverflow.com/a/33052902/2328012
Hope it helps!
I'm making a OBDII Bluetooth Android app and i'm having some issues sending out commands. I've already made a successfully connection between my mobile device and my OBDII adapter, but when I click on another activity, the Bluetooth connection seems to quit?
When you open up the app you'll see a button that says "Connect Device". When you press that, a ListAdapter will show up with paired Bluetooth devices. Then when you have succesfully connected to the device (OBDII Adapter) it will take you to another layout where there is 3 activities that are 3 different powerplatforms for cars. This is where the problem occurs. For now, I just want to be able to read the voltage from the OBDII. But when I click my button getValue inside one of the 3 activities. I get an logcat error. And I think it's because I haven't initiated my BluetoothHandler properly. I have no idea how to do this.
MainActivity:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button b1;
BluetoothAdapter mAdapter;
FragmentHostCallback mHost;
BTHandler btHandler;
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case Constants.MESSAGE_STATE_CHANGE:
switch (msg.arg1) {
case BTHandler.STATE_CONNECTED:
//setContentView(R.layout.activity_connected);
Intent intent = new Intent(MainActivity.this, Connected.class);
startActivity(intent);
Toast.makeText(getApplicationContext(), R.string.title_connected_to, Toast.LENGTH_SHORT).show();
Log.v("Log", "Connected");
break;
case BTHandler.STATE_NONE:
Toast.makeText(getApplicationContext(), R.string.title_not_connected, Toast.LENGTH_SHORT).show();
break;
}
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btHandler = new BTHandler(MainActivity.this, mHandler);
b1 = (Button) findViewById(R.id.connect);
b1.setOnClickListener(this);
mAdapter = BluetoothAdapter.getDefaultAdapter();
//init();
if (mAdapter == null) {
Toast.makeText(getApplicationContext(), R.string.device_not_supported, Toast.LENGTH_LONG).show();
finish();
} else {
if (!mAdapter.isEnabled()) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 1);
}
}
//BTHandler btHandler = new BTHandler(MainActivity.this, mHandler);
//btHandler.connect("");
}
public void onClick(View v) {
int id = v.getId();
//String voltage = ("ATRV");
switch (id) {
case R.id.connect:
onConnect(); //Operation
Log.v("Log", "Pressed onClick");
break;
/*case R.id.getValue:
btHandler.write(voltage);
Log.v("Log", "getValue" + voltage);
break;*/
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_CANCELED) {
Toast.makeText(getApplicationContext(), R.string.enable_bluetooth, Toast.LENGTH_SHORT).show();
finish();
}
}
private void onConnect() {
ArrayList deviceStrs = new ArrayList();
final ArrayList<String> devices = new ArrayList();
BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
Set pairedDevices = mAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (Object device : pairedDevices) {
BluetoothDevice bdevice = (BluetoothDevice) device;
deviceStrs.add(bdevice.getName() + "\n" + bdevice.getAddress());
devices.add(bdevice.getAddress());
}
}
// show list
final AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.select_dialog_singlechoice,
deviceStrs.toArray(new String[deviceStrs.size()]));
alertDialog.setSingleChoiceItems(adapter, -1, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
int position = ((AlertDialog) dialog).getListView().getCheckedItemPosition();
String deviceAddress = devices.get(position);
btHandler.connect(deviceAddress);
//btHandler.write();
}
});
alertDialog.setTitle("Paired devices");
alertDialog.show();
}
BTHandler:
public class BTHandler {
public static final int STATE_NONE = 0; // we're doing nothing
public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
public static final int STATE_CONNECTED = 3; // now connected to a remote device
final ArrayList<String> devices = new ArrayList();
private final Handler mHandler;
private BluetoothAdapter mAdapter;
private BluetoothDevice device;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
private BluetoothSocket socket;
private String status;
private int mState;
private boolean connectionStatus = false;
public BTHandler(Context context, Handler handler) { // Konstruktor
mAdapter = BluetoothAdapter.getDefaultAdapter();
mHandler = handler;
}
public void write(String s) {
mConnectedThread.sendRawCommand(s);
Log.v("write", "write");
}
/*
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) {
}
}
*/
public void connect(String deviceAddress) {
mConnectThread = new ConnectThread(deviceAddress);
mConnectThread.start();
}
private void guiHandler(int what, int arg1, String obj) {
Message msg = mHandler.obtainMessage();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.sendToTarget();
}
private class ConnectThread extends Thread {
BluetoothSocket tmp = null;
private BluetoothSocket mmSocket;
public ConnectThread(String deviceAddress) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
device = mAdapter.getRemoteDevice(deviceAddress);
BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device = mAdapter.getRemoteDevice(deviceAddress);
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
try {
tmp = device.createRfcommSocketToServiceRecord(uuid);
//socket.connect();
//Log.v("connect", "connect");
} catch (IOException e) {
//e.printStackTrace();
//Log.v("exception", "e");
}
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
mAdapter.cancelDiscovery();
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes;
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
Log.v("connect", "connect");
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
mmSocket.close();
Log.v("close", "close");
} catch (IOException closeException) {
}
guiHandler(Constants.TOAST, Constants.SHORT, "Connection Failed");
return;
}
guiHandler(Constants.CONNECTION_STATUS, Constants.STATE_CONNECTED, "");
mConnectedThread = new ConnectedThread(mmSocket);
mConnectedThread.start();
}
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private ObdMultiCommand multiCommand;
public ConnectedThread(BluetoothSocket socket) {
connectionStatus = true;
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
try {
//RPMCommand engineRpmCommand = new RPMCommand();
//SpeedCommand speedCommand = new SpeedCommand();
ModuleVoltageCommand voltageCommand = new ModuleVoltageCommand();
while (!Thread.currentThread().isInterrupted()) {
//engineRpmCommand.run(mmInStream, mmOutStream); //(socket.getInputStream(), socket.getOutputStream());
//speedCommand.run(mmInStream, mmOutStream); //(socket.getInputStream(), socket.getOutputStream());
voltageCommand.run(socket.getInputStream(), socket.getOutputStream());
// TODO handle commands result
//Log.d("Log", "RPM: " + engineRpmCommand.getFormattedResult());
//Log.d("Log", "Speed: " + speedCommand.getFormattedResult());
Log.v("Log", "Voltage: " + voltageCommand.getFormattedResult());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
OBDcmds();
// Keep listening to the InputStream until an exception occurs
while (connectionStatus) {
sendMultiCommand();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// CALL this to MainActivity
public void sendRawCommand(String command) {
try {
new OdbRawCommand(command);
} catch (Exception e) {
Log.v("sendRawCommand", "e");
}
}
private void OBDcmds() { // execute commands
try {
new EchoOffCommand().run(socket.getInputStream(), socket.getOutputStream());
new LineFeedOffCommand().run(socket.getInputStream(), socket.getOutputStream());
new TimeoutCommand(100).run(socket.getInputStream(), socket.getOutputStream());
new SelectProtocolCommand(ObdProtocols.AUTO).run(socket.getInputStream(), socket.getOutputStream()); //ISO_15765_4_CAN
} catch (Exception e) {
Log.v("OBDcmds", "e");
// handle errors
}
}
/*
// Call this from the main activity to send data to the remote device
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) {
}
}
*/
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
public void sendMultiCommand() {
try {
// RUN some code here
} catch (Exception e) {
}
}
}
}
SPA: One of the power platforms mentioned before.
public class SPA extends AppCompatActivity implements View.OnClickListener {
Button b2;
BTHandler btHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sp);
b2 = (Button) findViewById(R.id.getValue);
b2.setOnClickListener(this);
}
public void onClick(View v) {
int id = v.getId();
String voltage = ("AT RV");
switch (id) {
case R.id.getValue:
btHandler.write(voltage);
Log.v("Log", "getValue" + voltage);
break;
}
}
}
Logcat:
The reason of the error is here:
BTHandler btHandler;
and you are doing this:
btHandler.write(voltage);
but the object is null referenced....
you need to initialize the BTHandler in the oncreate...
or maybe better:
use a service so you can Bind all the activities to that...
PS:
Note that the BTHandler of the MainActivity is not the same as the one declared in the SPA Class... so although that btHandler is constructed and works in MainActivity doesnt mean it will work in other activities/classes
I've created an app which by clicking on a list Item, downloads an image from the Internet on a button click (also it places the url on to the EditText for user to see what the url is).
Initially I'm setting the ProgressBar and TextView (indicating Loading....) in a hide mode. But as the download starts, I would like to bring both TextView and ProgressBar on to the UI and once the download completes, would like to make both of them invisible.
There is NO error message on the LogCat to post. I believe I'm missing something which is tricky :). Let me know if any additional information is required. Thanks SO in advance.
Below is the XML: for LinearLayout which should be ON/OFF
<LinearLayout
android:id="#+id/loadingSection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/downloadImage"
android:visibility="gone"
android:orientation="vertical" >
<TextView
android:id="#+id/loadingMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Loading....."
android:gravity="center"
android:textAppearance="?android:attr/textAppearanceSmall" />
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyleSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="true" />
</LinearLayout>
And below is the Java file:
public class DownloadImages_HandlerMainActivity extends Activity implements OnItemClickListener {
private EditText editText;
private ListView listView;
private TextView textView;
private String[] listOfImages;
private Button downloadImage;
private ProgressBar progressBar;
private LinearLayout loadingSection = null;
private Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.downloadimages_main);
editText = (EditText) findViewById(R.id.downloadURL);
textView = (TextView) findViewById(R.id.loadingMessage);
listView = (ListView) findViewById(R.id.urlList);
downloadImage = (Button) findViewById(R.id.downloadImage);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
listOfImages = getResources().getStringArray(R.array.imageURLs);
listView.setOnItemClickListener(this);
handler = new Handler();
}
#Override
public void onItemClick(AdapterView<?> arg0, View view, int position,
long id) {
editText.setText(listOfImages[position]);
}
public void downloadImage(View view) {
String url = editText.getText().toString();
Thread myThread = new Thread(new DownloadImagesThread(url));
myThread.start();
}
public boolean downloadImageUsingThreads(String url) {
boolean successful = false;
URL downloadURL = null;
HttpURLConnection connection = null;
InputStream inputStream = null;
File file = null;
FileOutputStream fileOutputStream = null;
try {
downloadURL = new URL(url);
connection = (HttpURLConnection) downloadURL.openConnection();
inputStream = connection.getInputStream();
file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES).getAbsolutePath()
+ "/" + Uri.parse(url).getLastPathSegment());
fileOutputStream = new FileOutputStream(file);
int read = -1;
byte[] buffer = new byte[1024];
while ((read = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, read);
//Log.d("BRK0018", " " + read);
successful = true;
}
} catch (MalformedURLException e) {
e.printStackTrace();
Log.d("BRK0018", " " + e);
} catch (IOException e) {
e.printStackTrace();
Log.d("BRK0018", " " + e);
} finally {
// This is the HANDLER INSTANCE in place of thread
handler.post(new Runnable() {
#Override
public void run() {
try {
loadingSection.setVisibility(View.GONE); // Making the ProgressBar INVISIBLE
} catch (Exception e) {
Log.d("BRK0018", " " + e);
}
}
});
if (connection != null) {
connection.disconnect();
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
Log.d("BRK0018", " " + e);
}
}
}
return successful;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private class DownloadImagesThread implements Runnable {
private String url;
public DownloadImagesThread(String url) {
this.url = url;
}
// This is the HANDLER INSTANCE in place of thread
#Override
public void run() {
handler.post(new Runnable() {
#Override
public void run() {
try {
// TODO Auto-generated method stub
loadingSection.setVisibility(View.VISIBLE); // Making the ProgressBar VISIBLE
} catch (Exception e) {
Log.d("BRK0018", " " + e);
}
}
});
downloadImageUsingThreads(url);
}
}
}
The problem here is loadingSection which is null. And since you change its visibility in try/catch block, the app doesn't crash. Initialize the layout in onCreate():
loadingSection = (LinearLayout) findViewById(R.id.loadingSection);
First of all, when you call
handler.post(new Runnable() {
#Override
public void run() {
try {
// TODO Auto-generated method stub
loadingSection.setVisibility(View.VISIBLE);
Thread.sleep(1000);
} catch (Exception e) {
Log.d("BRK0018", " " + e);
}
}
});
Handler.class runs above code in UI thread.
You must not call Thread.sleep(1000) in UI thread.
(but anyway remember that loadingSection.setVisibility(View.VISIBLE); must be called in UI thread)
Fix it. And whether it helps or not write me.