android - how to check if device is connected with Bluetooth - java

i have following function run on start and work perfectly.
i would like to add if condition in other function in order to check if device is still connected.
here is code
private final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BluetoothService.MESSAGE_STATE_CHANGE:
switch (msg.arg1) {
case BluetoothService.STATE_CONNECTED:
Toast.makeText(getApplicationContext(), "Connect successful",
Toast.LENGTH_SHORT).show();
btnClose.setEnabled(true);
btnSend.setEnabled(true);
btnSendDraw.setEnabled(true);
break;
case BluetoothService.STATE_CONNECTING:
Log.d("À¶ÑÀµ÷ÊÔ","ÕýÔÚÁ¬½Ó.....");
break;
case BluetoothService.STATE_LISTEN:
case BluetoothService.STATE_NONE:
Log.d("À¶ÑÀµ÷ÊÔ","µÈ´ýÁ¬½Ó.....");
break;
}
break;
case BluetoothService.MESSAGE_CONNECTION_LOST:
Toast.makeText(getApplicationContext(), "Device connection was lost",
Toast.LENGTH_SHORT).show();
btnClose.setEnabled(false);
btnSend.setEnabled(false);
btnSendDraw.setEnabled(false);
break;
case BluetoothService.MESSAGE_UNABLE_CONNECT:
Toast.makeText(getApplicationContext(), "Unable to connect device",
Toast.LENGTH_SHORT).show();
break;
}
}
};
other function is start like this
#Override
protected void onPostExecute(String result){
please help me!!
Thanks

ACL_CONNECTED/DISCONNECTED is not exactly reliable, I have learned by experience, because this might happen several times during a device's connection (example, if pin is required, you will get "connected", and then "disconnected" if timeout/wrong pin supplied. This does not necessarily indicate connection proper). This indicates the lower layer connection.
If you want to use a broadcast receiver, it would be better to use the broadcast that is specific to the profile that you have used (example A2DP). Each has it's own broadcast. Another thing you can listen to is Connectivity_state_changed from ConnectivityManager, for the type BLUETOOTH (haven't really tried this one).
Also, the way to check if it is connected, without a broadcast receiver, say, when you want to check in the background before updating an activity, would be to obtain the profile object, via something like:
mBluetoothAdapter.getProfileProxy(mContext, mA2DPProfileListener, BluetoothProfile.A2DP);
where mA2DPProfileListener is a ServiceListener object:
<code>
private ServiceListener mA2DPProfileListener = new ServiceListener(){
//anonymous inner type. etc.
public void onServiceConnected(int profile, BluetoothProfile proxy) {
//cast the BluetoothProfile object to the profile you need, say
//BluetoothA2DP proxyA2DP = (BluetoothA2DP) proxy;
int currentState = proxyA2DP.getConnectionState(mDevice);
//mDevice is the BluetoothDevice object you can get from
//BluetoothAdapter.getRemote...
}
public void onServiceDisconnected(int profile) {
}
}
</code>
you can check what currentState points to, and determine if the device is connected/disconnected/connecting, etc.
HTH,
Sreedevi.

Related

How to connect paired bluetooth device on app startup in Android Studio?

Is there any way to automatically connect a specific device via Bluetooth LE on app startup?
I've been scrolling through stack overflow for the past few hours and have seen a number of similar questions, although majority are quite outdated and deal with reflections or other complex methods that I can't quite comprehend (these methods I've tried to implement, but not successfully, as I didn't really understand what was going on).
So far, I've managed to find the device by its friendly name, although I have no clue what to execute in that if statement. This is within my MainActivity:
protected void onCreate(Bundle savedInstanceState) {
...
if (bluetoothAdapter == null) {
Toast.makeText(getApplicationContext(),"Bluetooth not supported",Toast.LENGTH_SHORT).show();
} else {
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
if(pairedDevices.size()>0){
for(BluetoothDevice device: pairedDevices){
if (deviceName.equals(device.getName())) {
//Device found!
//Now how do I pair it?
break;
}
...
Assuming you've successfully identified the BlueToothDevice, you now need to connect to the GATT(Generic Attribute Profile), which allows you to transfer data.
Use the BlueToothDevice.connectGatt method. Using the first overload, the method takes in a Context , a boolean (false = directly connect, true = connect when available), and a BlueToothGhattCallback. The callback receives info from the device.
BlueToothGatt blueToothGatt = device.connectGatt(this, false, blueToothGattCallback);
An example to implement the callback:
BluetoothGattCallback blueToothGattCallback =
new BluetoothGattCallback()
{
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if(newState == BlueToothProfile.STATE_CONNECTED){
/* do stuff */
}
}
}
More details on the callbacks here.
Ended up scrolling through the source code for this app, particularly the SerialSocket, SerialService and SerialListener files which completely solved my problem.

What does the class LocationSettingsStates do when receiving location requests?

In the docs here I'm following how to receive location requests and two unusual things I noticed are in these two blocks of code:
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
final LocationSettingsStates = result.getLocationSettingsStates(); //<--This line I don't understand
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
...
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user
// a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(
OuterClass.this,
REQUEST_CHECK_SETTINGS);
} catch (SendIntentException e) {
// Ignore the error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
...
break;
}
}
});
And in the second block:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
final LocationSettingsStates states = LocationSettingsStates.fromIntent(intent); //<--And this line
switch (requestCode) {
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
// All required changes were successfully made
...
break;
case Activity.RESULT_CANCELED:
// The user was asked to change settings, but chose not to
...
break;
default:
break;
}
break;
}
}
I've added some arrows pointing to the lines I don't understand. In particular, these two:
final LocationSettingsStates = result.getLocationSettingsStates();
final LocationSettingsStates states = LocationSettingsStates.fromIntent(intent);
The first line is something I haven't seen before. How is this valid, assigning a value to a data type? Then that class is no longer used anywhere else in that block of code, so what's the purpose of the assignment?
In the other line, now it's assigning a value to an instance called states of that data type but that instance is not used anywhere else in onActivityResult().
So what is going on here? Thanks.
The first line is definitely a typo; it should be something like:
final LocationSettingsStates states = result.getLocationSettingsStates();
And yeah, it isn't used in either place, which is weird, but you can call things like isBleUsable() on it to determine what exactly is present and usable right now. In the latter case, it's what's usable after the attempted resolution.

android connecting to wifi WifiManager.SUPPLICANT_STATE_CHANGED_ACTION strange issue

I am having an issue when try to connect to wireless network.
My code works ok I sucessfully connect to the network whit the problems described below.
I have a listview whit the wifi scan results.
When I click the first time my receiver is not getting the "completed" state.
After clicking the second time , and , without chosing any network it get connected and my code inside the "complete" is executed.
The code below is called from another class that thre reason why it is static
Coonect Code:
public static boolean connect(String ssid,String password)
{
String networkSSID = ssid;
String networkPass = password;
WifiConfiguration conf = new WifiConfiguration();
conf.SSID = "\"" + networkSSID + "\"";
conf.preSharedKey = "\""+ networkPass +"\"";
//WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
int netid=mainWifi.addNetwork(conf);
mainWifi.disconnect();
mainWifi.enableNetwork(netid, true);
//mainWifi.reconnect(); <-- exact the same issue discommenting this line
return true;
}
On the class were the connect is been called I have registered BradcastReceiver as follow:
public void onClick(View v)
{
mainWifi = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiinfo = mainWifi.getConnectionInfo();
AuthWifi authWifi = new AuthWifi();
IntentFilter mIntentFilter = new IntentFilter();
mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
getApplicationContext().registerReceiver(authWifi, mIntentFilter);
ClientManager.scan(CameraActivity.this, mainWifi);
}
my broadcast receiver
public class AuthWifi extends BroadcastReceiver {
#Override
public void onReceive(Context c, Intent intent) {
String action = intent.getAction();
if (action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)) {
SupplicantState supl_state = ((SupplicantState) intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE));
switch (supl_state) {
case COMPLETED:
/////////////IF I AM CONNECTED THE WIFI SSID I CHOSE FROM A LISTVIEW THEN ---->
if(wifiinfo != null & wifiinfo.getSSID()!=null & ClientManager.getSSID() !=null& !conectado ) {
if (wifiinfo.getSSID().contains(ClientManager.getSSID().trim())) ///I know here is better .equals() /// I have contain for my own reasons
conectado = true;
/*HERE I DO SOME THINGS WHEN CONNECTED (I CALL A RUNNABLE TO MAKE A SERVER SOCKET)*/
}
}
break;
case DISCONNECTED:
Log.i("SupplicantState", "Disconnected");
conectado = false;
if (ClientStartReceive.isStopped)
{
ClientStartReceive.stop();
}
break;
default:
Log.i("SupplicantState", "Unknown");
break;
}
int supl_error = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1);
if (supl_error == WifiManager.ERROR_AUTHENTICATING) {
/////HERE I MANAGE AUTHENTICATION ERROR
}
}
}
}
Hope someone is able to help :( if you need more code to troubleshoot please let me know.
If you have some reference to help me even if i need to rebuild the code is accepted also.. My goal is be able to connect to a network ,show for authentication errors and execute some code on connection susscess.
Sorry for my english I think you have gessed I am not native.
Regards
As doc indicate that “COMPLETED“ use as follow:
This state indicates that the supplicant has completed its processing for the association phase and that data connection is fully configured. Note, however, that there may not be any IP address associated with the connection yet.
You should not rely this state to ensure your connection is completed. Instead, you can register an BroadcastReceiver listener for network status change.

Communicate from Service to Activity via bound service

I've already bound an activity to my service following this tutorial.
http://developer.android.com/guide/components/bound-services.html
I'm able to call service functions, but what if I want to for example, change some of my textviews or disable some of the toggle buttons because of work done on the service (and from the service). Would there be an easy to way to do this?
You can use messages to send information between activities and services. This is an easy way to send simple data, but may not be the best option if you need to send data very frequently, or send complicated data. This is an example of some code I have in one of my apps with a service and an activity which communicate:
Code in the activity:
//this is where you set what you want to happen
class IncomingHandler extends Handler {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
//this switch reads the information in the message (usually just
//an integer) and will do something depending on which integer is sent
case 1: do_something();
case 2: do_something_2(); //etc.
default:
super.handleMessage(msg);
}
}
}
final Messenger myMessenger = new Messenger(new IncomingHandler());
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
myService = new Messenger(service);
myCallbackText = (TextView)findViewById(R.id.tv01); //This is a text view which will display status information as needed
myCallbackText.setText("Attached.");
try {
Message msg = Message.obtain(null,
1);
msg.replyTo = mMessenger; //here we send an instance of our messenger implementation as the replyTo address
mService.send(msg);
msg = Message.obtain(null,
3, this.hashCode(), 0);
mService.send(msg); //send a message with the value "3"
} catch (RemoteException e) {
//nothing you can do if the server isn't active
}
Toast.makeText(Service_testActivity.this, R.string.remote_service_connected,
Toast.LENGTH_SHORT).show();//confirmation that the connection happened successfully
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
mCallbackText = (TextView)findViewById(R.id.tv01);//same textview as before
mCallbackText.setText("Disconnected.");
Toast.makeText(Service_testActivity.this, R.string.remote_service_disconnected,
Toast.LENGTH_SHORT).show();
}
};
Code in the service:
In the service, you will want to have code (very similar to the code in the activity) to receive a message and save the msg.replyTo field as a Messenger object. There is an example somewhere which will have you make an object and then use an IncomingHandler like this:
ArrayList<Messenger> mClients = new ArrayList<Messenger>();
class IncomingHandler extends Handler {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REGISTER_CLIENT:
mClients.add(msg.replyTo);
break;
case MSG_UNREGISTER_CLIENT:
mClients.remove(msg.replyTo);
break;
default:
super.handleMessage(msg);
}
}
}
This can allow your service to keep track of multiple clients at once and send messages to specified clients. To send a message simply use something like this:
mClients.get(1).send(Message.obtain(null, 3, new Random().nextInt(), 0));
//sends a message to the first client saved in the list

Return value from child thread

I'm writing an Android app that communicates with a website. Any time I hit the website, I'm displaying a ProcessDialog so that the user knows something's happening. Most of my website communication is one-way, so I don't usually expect any return data.
There is one point however where I need to get information back, but the results are not being stored when I exit the child thread. In a nutshell, I need to call a thread, let it process the results, and store the results in a couple of fields.
Here's what I've got so far - I have two variables, String[] Account and boolean AccountRetrievalSuccess:
public void GetAccount() {
MyDialog = ProgressDialog.show( MyContext, "Retrieving Account" , "We're retrieving your account information. Please wait...", true);
Thread T = new GetAccountThread();
T.start();
}
public class GetAccountThread extends Thread {
#Override
public void run() {
try {
String resp = GetPage(BaseURL+MainPage+"?P="+PhoneID+"&K="+WebAccessKey+"&A=ACCOUNT");
if (resp.contains("FAILURE|")){
failhandler.sendEmptyMessage(0);
} else {
resp = resp.replace("SUCCESS|", "");
Account = resp.split("\\|");
handler.sendEmptyMessage(0);
}
} catch (Exception e) {
failhandler.sendEmptyMessage(0);
}
};
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
AccountRetrievalSuccess = true;
MyDialog.dismiss();
}
};
private Handler failhandler = new Handler() {
#Override
public void handleMessage(Message msg) {
AccountRetrievalSuccess = false;
MyDialog.dismiss();
ShowWtf();
}
};
}
Any idea what I'd need to do to be able to store the Account and AccountRetrievalSuccess values so that I can access them from elsewhere in the code?
Looks like a perfect job for AsyncTask!
This class allows you to run a task on a background thread and return the results back to the UI thread whilst reporting progress on the task at hand.
Not expecting a result in a mobile app might be a bad idea by the way, due to nature of mobile network connections you'd never know for sure if your server actually got the thing you sent it (and the server might have failed while processing and your app would never know...)
Do not use threads. You should use executors for that. Implement a Callable<> interface, create an ExecutorService and run it. Have a look to the java.util.concurrent package.
Make those global variables in the containing Activity and then pass them to the handler:
Message m = Message.obtain();
m.obj = Account;
handler.sendMessageDelayed(m, 1);
Then in the handler you can cast m.obj back to the Account type and its nice and available.
Scott.. You should not have more than one handler per activity. Instead switch on what. You can send data (or objects) in messages as in:
Message msg= Message.obtainMessage(0);
Bundle b= new Bundle();
b.putString("stringData",outString);
msg.setData(b);
handler.sendMessage(msg);
You can switch on multiple messages in the handler as in.
public void handleMessage(Message msg){
switch(msg.what){
case BUTTON_ONE_UP_SELECTED:
this.removeMessages(BUTTON_ONE_UP_SELECTED);
buttonLarger01.setImageResource(R.drawable.btn_zoom_up_selected);
break;
case BUTTON_ONE_UP_NORMAL:
this.removeMessages(BUTTON_ONE_UP_NORMAL);
buttonLarger01.setImageResource(R.drawable.btn_zoom_up_normal);
break;
case BUTTON_TWO_UP_SELECTED:
this.removeMessages(BUTTON_TWO_UP_SELECTED);
buttonLarger02.setImageResource(R.drawable.btn_zoom_up_selected);
break;
case BUTTON_TWO_UP_NORMAL:
this.removeMessages(BUTTON_TWO_UP_NORMAL);
buttonLarger02.setImageResource(R.drawable.btn_zoom_up_normal);
break;
case BUTTON_ONE_DOWN_SELECTED:
this.removeMessages(BUTTON_ONE_DOWN_SELECTED);
buttonSmaller01.setImageResource(R.drawable.btn_zoom_down_selected);
break;
case BUTTON_ONE_DOWN_NORMAL:
this.removeMessages(BUTTON_ONE_DOWN_NORMAL);
buttonSmaller01.setImageResource(R.drawable.btn_zoom_down_normal);
break;
case BUTTON_TWO_DOWN_SELECTED:
this.removeMessages(BUTTON_TWO_DOWN_SELECTED);
buttonSmaller02.setImageResource(R.drawable.btn_zoom_down_selected);
break;
case BUTTON_TWO_DOWN_NORMAL:
this.removeMessages(BUTTON_TWO_DOWN_NORMAL);
buttonSmaller02.setImageResource(R.drawable.btn_zoom_down_normal);
break;
default:
super.handleMessage(msg);
break;
}
}
};
So in your case you could define SUCCESS as what 0 and FAILURE as what 1 etc.

Categories

Resources