Bluetooth enabling disrupts broadcastreceiver - java

My app is designed to append all scanned Bluetooth devices to a textview. This works great if the phones Bluetooth is on. However, if my app checks to see if the phones Bluetooth is off and turns it on if it is off, then start my the discovery process my broadcastreciever does not pick up an event and so my textview does not populate. Any help is appreciated!
Here is my code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_blue_tooth_main);
txtResults = (TextView) this.findViewById(R.id.txtResults);
mBlueToothAdapter = BluetoothAdapter.getDefaultAdapter();
if (!(mBlueToothAdapter.isEnabled())) {
mBlueToothAdapter.enable();
}
mBlueToothAdapter.startDiscovery();
MY RECEIVER:
public static class BlueToothBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
blueToothName = device.getName();
blueToothAddress = device.getAddress();
blueToothClass = device.getBluetoothClass();
blueToothBondState = device.getBondState();
GetBondStateStr(blueToothBondState);
blueToothUUIDS = device.getUuids();
paramsBlueTooth
.add(new BasicNameValuePair("Name: ", blueToothName));
paramsBlueTooth.add(new BasicNameValuePair("Address: ",
blueToothAddress));
paramsBlueTooth.add(new BasicNameValuePair("Class: ", String
.valueOf(blueToothClass)));
paramsBlueTooth.add(new BasicNameValuePair("Bond State: ",
blueToothBondStateStr));
paramsBlueTooth.add(new BasicNameValuePair("UUIDS: ", String
.valueOf(blueToothUUIDS)));
showBlueToothData();
}
ShowBlueToothData():
private void showBlueToothData() {
StringBuilder results = new StringBuilder();
results.append("-----BLUETOOTH DEVICE INFORMATION-----\n");
results.append("Name: " + blueToothName + "\n");
results.append("Address: " + blueToothAddress + "\n");
results.append("Class: " + blueToothClass + "\n");
results.append("Bond State: " + blueToothBondStateStr + "\n");
results.append("UUIDS: " + blueToothUUIDS + "\n");
txtResults.append(new String(results));
txtResults.append("\n");
}

Your chosen method of enabling the Bluetooth radio via the BluetoothAdapter.enable() method is an asynchronous call. As you can see from the method's documentation, you cannot assume that the radio is up and active as soon as the method returns. You have to wait for the ACTION_STATE_CHANGED broadcast to know that the radio is ready for you to try a scan.
If you read the documentation, notice also that doing it this was is a poor experience because there is no notification to the user. A better choice is the method of sending the user to Settings to enable Bluetooth themselves. You could modify your startup logic to be something more like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_blue_tooth_main);
txtResults = (TextView) this.findViewById(R.id.txtResults);
mBlueToothAdapter = BluetoothAdapter.getDefaultAdapter();
…
}
#Override
protected void onResume() {
super.onResume();
if (!(mBlueToothAdapter.isEnabled())) {
//Take the user to settings first!
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivity(intent);
} else {
mBlueToothAdapter.startDiscovery();
}
}
This modification will check for Bluetooth every time you come to the foreground, and only trigger the scan if you are ready to do so.

Try doing:
Intent enable_intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enable_intent, REQUEST_ENABLE_BT);
inside if (!(mBlueToothAdapter.isEnabled())){...}
OR:
for(int i=0;i<5;i++){
if (!mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.enable();
}
Thread.sleep(100);
}else{
//display error, unsuccessfull , try manually
}

Related

How can i refresh the list of bluetooth devices in java

I am trying to make an android application about localization, i am trying however to make a list of Bluetooth devises found by my smartphone and refresh that lists information every 10 seconds. I want to do that because I am also recording the signal strength (RSSI) and want to record when a beacon is getting out of range when moved or the signal is getting weaker. So refreshing the list will help with that. I have provided some of my code below.
#Override protected void onResume() {
super.onResume();
registerReceiver(devicesFoundReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
registerReceiver(devicesFoundReceiver, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED));
registerReceiver(devicesFoundReceiver, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED));
}
private final BroadcastReceiver devicesFoundReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)){
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
int rssid = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
listAdapter.add(device.getName() + "\n" + device.getAddress() + "\n" + " RSSI: " + rssid + "dBm");
listAdapter.notifyDataSetChanged();
}else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
scanningButton.setText("Scan Bluetooth Devices");
}else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){
scanningButton.setText("Scanning in progress ...");
}
}
};
use a listview then call notifyDataSetChanged() on your Adapter object

Discovering Bluetooth Sample

I'm learning about bluetooth apps and the first sample I've come across, seems to be well documented but I cannot for the life of me get it to reproduce the "Search Devices" part, any help would be greatly appreciated.
public class MainActivity extends AppCompatActivity {
private Button onBtn, offBtn, listBtn, findBtn;
private TextView text;
private ListView myListView;
// Bluetooth global variables
private static final int REQUEST_ENABLE_BT = 1;
private BluetoothAdapter myBluetoothAdapter;
public Set<BluetoothDevice> pairedDevices;
private ArrayAdapter<String> BTArrayAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if(myBluetoothAdapter == null) {
Toast.makeText(getApplicationContext(),"Your device does not support Bluetooth",
Toast.LENGTH_LONG).show();
}
else
{
text = (TextView) findViewById(R.id.text);
onBtn = (Button)findViewById(R.id.turnOn);
offBtn = (Button)findViewById(R.id.turnOff);
listBtn = (Button)findViewById(R.id.paired);
findBtn = (Button)findViewById(R.id.search);
myListView = (ListView)findViewById(R.id.listView1);
// create the arrayAdapter that contains the bluetooth d evices, and set it to the ListView
BTArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
myListView.setAdapter(BTArrayAdapter);
myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String selectedFromList =(String) (myListView.getItemAtPosition(i));
Toast.makeText(getApplicationContext(),"Bluetooth remote device : " + selectedFromList,
Toast.LENGTH_LONG).show();
}
});
}
} // onCreate
public void on(View view){
if (!myBluetoothAdapter.isEnabled()) {
Intent turnOnIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(turnOnIntent, REQUEST_ENABLE_BT);
Toast.makeText(getApplicationContext(),"Bluetooth turned on" ,
Toast.LENGTH_LONG).show();
}
else{
Toast.makeText(getApplicationContext(),"Bluetooth is already on",
Toast.LENGTH_LONG).show();
}
}
public void off(View view){
myBluetoothAdapter.disable();
text.setText("Status: Disconnected");
Toast.makeText(getApplicationContext(),"Bluetooth turned off",
Toast.LENGTH_LONG).show();
}
public void list(View view){
// get paired devices
pairedDevices = myBluetoothAdapter.getBondedDevices();
// put it's one to the adapter
for(BluetoothDevice device : pairedDevices)
BTArrayAdapter.add(device.getName()+ "\n" + device.getAddress());
Toast.makeText(getApplicationContext(),"Show Paired Devices",
Toast.LENGTH_SHORT).show();
}
final BroadcastReceiver bReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// add the name and the MAC address of the object to the arrayAdapter
BTArrayAdapter.add(device.getName() + "\n" + device.getAddress());
BTArrayAdapter.notifyDataSetChanged();
}
}
};
public void find(View view) {
if (myBluetoothAdapter.isDiscovering()) {
// the button is pressed when it discovers, so cancel the discovery
Toast.makeText(getApplicationContext(),"Bluetooth cancelled discovery" ,
Toast.LENGTH_LONG).show();
myBluetoothAdapter.cancelDiscovery();
} else {
BTArrayAdapter.clear();
Toast.makeText(getApplicationContext(),"Bluetooth discovery started" ,
Toast.LENGTH_LONG).show();
myBluetoothAdapter.startDiscovery();
registerReceiver(bReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
}
}
#Override
protected void onDestroy() {
super.onDestroy();
}
}
Using a Oneplus3 & 2 to test this, and neither device can find the other, unless already paired with each other. I want to see if I can search and get the device to populate in a list like the paired devices already do.
If there's anything else you need me to put in let me know, hope you don't mind taking the time to help out with this one!
You need to add one of the following permission to your Manifest.xml to find devices:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
or
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
If you are working on API 23 and higher you must ensure this permission is granted because it is a dangerous level permission.
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app
See this guide to request permission(s).

Bluetooth OnReceive Method Doesn't Get Called

I'm trying to make an android app which has some issues about Bluetooth. I simply enable Bluetooth, find devices, connect one of the devices, send & receive data. First thing is done. But in second, there are some problems. I make a Broadcast Receiver to discover devices nearby my phone. But OnReceive method doesn't get called. The weird thing is, it was getting called at first and I was able to see devices nearby. Then something that I cannot figure out happened and now OnReceive method doesn't get called. I've searched topics about these but none of them could solve my problem. MyDevice and MyAdapter are my own classes to show Bluetooth devices in listview with my own layout. Here is my code:
public class FoundDevicesActivity extends AppCompatActivity {
BluetoothAdapter bluetoothAdapter;
ListView foundedDevicesListView;
MyDeviceAdapter deviceAdapter;
List<MyDevice> foundedDevicesList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_found_devices);
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
foundedDevicesListView = (ListView) findViewById(R.id.foundDevicesListview);
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(receiver, filter);
bluetoothAdapter.startDiscovery();
deviceAdapter = new MyDeviceAdapter(this, foundedDevicesList);
foundedDevicesListView.setAdapter(deviceAdapter);
}
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
Toast.makeText(FoundDevicesActivity.this, "Discovery is started !!", Toast.LENGTH_SHORT).show();
Log.d("Found Devices Activity", "Discovery is started !!");
} else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
MyDevice dvc = new MyDevice();
if (device.getName().equals(null)) {
dvc.name = "UNDEFINED NAME";
} else {
dvc.name = device.getName();
}
if(device.getAddress().equals(null)) {
dvc.address = "UNDEFINED ADDRESS";
} else {
dvc.address = device.getAddress();
}
foundedDevicesList.add(dvc);
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
bluetoothAdapter.cancelDiscovery();
Toast.makeText(FoundDevicesActivity.this, "Discovery is finished !!", Toast.LENGTH_SHORT).show();
Log.d("Found Devices Activity", "Discovery is finished !!");
}
}
};
}
Any idea ?

android bluetooth discovery not finding devices

I have a very simple activity for discovering other android devices via bluetooth:
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// Get the local Bluetooth adapter
FrameLayout f = new FrameLayout(this);
setContentView(f);
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
this.registerReceiver(mReceiver, filter);
// Register for broadcasts when discovery has finished
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(mReceiver, filter);
mBtAdapter = BluetoothAdapter.getDefaultAdapter();
// Get a set of currently paired devices
Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();
// Request discover from BluetoothAdapter
Log.i("bluetooth", "about to start device discovery");
mBtAdapter.startDiscovery();
//start receiving stuff
mReceiver = new BluetoothReceiver();
}
The problem is that the BluetoothRecieiver class called at the end of the activity's onCreate() doesn't seem to find and devices, although I have one turned on in the vicinity when I am debugging this:
public class BluetoothReceiver extends BroadcastReceiver {
public ArrayAdapter<String> mNewDevicesArrayAdapter;
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// If it's already paired, skip it, because it's been listed already
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
Log.i("face", device.getName() + "\n" + device.getAddress());
mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
// When discovery is finished, change the Activity title
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
if (mNewDevicesArrayAdapter.getCount() == 0) {
Log.i("face", "found NOTHING!");
mNewDevicesArrayAdapter.add("no devices found");
}
}
}
}
Is there anything I am missing here?
I think it's because when you call registerReceiver() mReceiver is null, move mReceiver = new BluetoothReceiver(); above the first this.registerReceiver(mReceiver, filter);, also you could do something like
filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
and then call this.registerReceiver(mReceiver, filter); only one time

Scanning available wifi, detect specific strongest Wifi SSID to launch an XML activity layout

I need to locate my current location in a building by scanning the strongest available Wifi to launch an activity. I want to locate only 3 places in that building. So if I am currently near any of those locations, I will click a button to scan the strongest available Wifi to launch an activity.
I need to scan available Wifi in a building.
Get the 3 strongest signal.
Then detect whether any of those 3 strongest signal's SSID is the same with the specific SSID that I want to locate.
If my SSID is one of the strongest 3 signals, then the application will launch a xml layout activity,
So far I already have the coding to scan strongest available Wifi. But I don't know how to launch an activity when the strongest specific Wifi SSID detected. I do not need the information about the Wifi, just to launch my activity layout that has my information.
At the moment I'm using the following bit of code to scan the strongest Wifi signal that I got from here:
WiFiDemo.java
public class WiFiDemo extends Activity implements OnClickListener {
private static final String TAG = "WiFiDemo";
WifiManager wifi;
BroadcastReceiver receiver;
TextView textStatus;
Button buttonScan;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Setup UI
textStatus = (TextView) findViewById(R.id.textStatus);
buttonScan = (Button) findViewById(R.id.buttonScan);
buttonScan.setOnClickListener(this);
// Setup WiFi
wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
// Get WiFi status
WifiInfo info = wifi.getConnectionInfo();
textStatus.append("\n\nWiFi Status: " + info.toString());
// List available networks
List<WifiConfiguration> configs = wifi.getConfiguredNetworks();
for (WifiConfiguration config : configs) {
textStatus.append("\n\n" + config.toString());
}
// Register Broadcast Receiver
if (receiver == null)
receiver = new WiFiScanReceiver(this);
registerReceiver(receiver, new IntentFilter(
WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
Log.d(TAG, "onCreate()");
}
#Override
public void onStop() {
unregisterReceiver(receiver);
}
public void onClick(View view) {
Toast.makeText(this, "On Click Clicked. Toast to that!!!",
Toast.LENGTH_LONG).show();
if (view.getId() == R.id.buttonScan) {
Log.d(TAG, "onClick() wifi.startScan()");
wifi.startScan();
}
} }
WiFiScanReceiver.java
public class WiFiScanReceiver extends BroadcastReceiver {
private static final String TAG = "WiFiScanReceiver";
WiFiDemo wifiDemo;
public WiFiScanReceiver(WiFiDemo wifiDemo) {
super();
this.wifiDemo = wifiDemo;
}
#Override
public void onReceive(Context c, Intent intent) {
List<ScanResult> results = wifiDemo.wifi.getScanResults();
ScanResult bestSignal = null;
for (ScanResult result : results) {
if (bestSignal == null
|| WifiManager.compareSignalLevel(bestSignal.level, result.level) < 0)
bestSignal = result;
}
String message = String.format("%s networks found. %s is the strongest.",
results.size(), bestSignal.SSID);
Toast.makeText(wifiDemo, message, Toast.LENGTH_LONG).show();
Log.d(TAG, "onReceive() message: " + message);
}
}
You just need to start your activity from onReceive. Unless I'm not understanding your question, you just need to fire off your activity.
Since you have the context on your receiver's onReceive you just need to startActivity()
Start Activity inside onReceive BroadcastReceiver
#Override
public void onReceive(Context context, Intent intent) {
//start activity
Intent i = new Intent();
i.setClassName("com.test", "com.test.MainActivity");
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
Don't forget to define a proper filter for it in your manifest.
http://developer.android.com/reference/android/content/BroadcastReceiver.html

Categories

Resources