Hello i have followed the example in https://developer.android.com/guide/topics/connectivity/bluetooth and my broadcast receiver maybe is not working. I am running android 8.1 in my Android Xiaomi mi A1 device.
#Override
protected void onCreate(Bundle savedInstanceState) {
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
bluetoothAdapter.startDiscovery();
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Discovery has found a device. Get the BluetoothDevice
// object and its info from the Intent.
BluetoothDevice device = (BluetoothDevice) intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String deviceName = device.getName();
String deviceHardwareAddress = device.getAddress(); // MAC address
Toast.makeText(MainActivity.this, deviceName, Toast.LENGTH_SHORT).show();
Toast.makeText(MainActivity.this, deviceHardwareAddress, Toast.LENGTH_SHORT).show();
mDeviceList.add(deviceHardwareAddress);
ArrayAdapter arrayAdapter = new ArrayAdapter(MainActivity.this,android.R.layout.simple_list_item_1,mDeviceList);
listV.setAdapter(arrayAdapter);
}
}
};
Thank you!
NOTE
For android Api 21 Broadcast receiver works fine is there a change i have to make to make it work for Android 8.1?
In manifest I have put the permissions and other services like start stop bluetooth and find paired devices are working fine...
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
You Need to Add Permission in code above Version M
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 1000);
Related
I'm trying to start the bluetooth sco to be able to record a call through bluetooth headset but every tim i execute the code , it returns disconencted even though bluetooth is on and headsets are connected , any reason why Thank you .
Manifest File
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
<uses-permission android:name="android.permission.BLUETOOTH" android:required="false" />
Registering receiver
// register new receiver for bluetooth headset
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED); // API 14
registerReceiver(broadcastReceiver,intentFilter);
audioManager.setMode(AudioManager.MODE_IN_CALL);
audioManager.startBluetoothSco();
if(audioManager.isBluetoothScoOn()){
Log.d("TAG","True");
} else {
Log.d("TAG","False");
}
Receiver code
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,-1);
if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
// Start recording audio
isConnected = true;
Log.d("TAG","audio connected");
} else if(state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED){
Log.d("TAG","audio Disconnected");
} else if (state == AudioManager.SCO_AUDIO_STATE_CONNECTING){
Log.d("TAG","audio Connecting");
}
}
};
LOGS
I am able to list unpaired devices on scan discovery only if other devices are on their 'bluetooth setting screen'.If other devices are on their homepage then my application cannot find those devices.
I have android 7 on my mobile phone and other devices have android 9 on them.
Any help is appreciated.Thanks:)
public void startDiscovery()
{
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
BA.startDiscovery();
registerReceiver(mReceiver, filter);
Toast.makeText(getApplicationContext(), "Discovery started", Toast.LENGTH_SHORT).show();
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d("main","action found"+action);
if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
Toast.makeText(getApplicationContext(), "Discovery started", Toast.LENGTH_SHORT).show();
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
Toast.makeText(getApplicationContext(), "Discovery finished", Toast.LENGTH_SHORT).show();
} else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
//Discovery has found a device. Get the BluetoothDevice
// object and its info from the Intent.
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String deviceName = device.getName();
String deviceHardwareAddress = device.getAddress(); // MAC address
Log.d("main","devicename"+deviceName);
Log.d("main","deviceHardwareAddress"+deviceHardwareAddress);
}
};
#Override
protected void onDestroy() {
Log.d("main","destroyed");
super.onDestroy();
BA.cancelDiscovery();
// Don't forget to unregister the ACTION_FOUND receiver.
unregisterReceiver(mReceiver);
}
Its not being discovered because its hidden according to the bt protocol however see https://stackoverflow.com/a/36984988/8461344
It's my first time working with Bluetooth module in Android, I'm trying to scan devices not paired yet and show them in a message but it doesn't work. I have tried a lot of things but nothing. I have all the permissions needed. This is part of my code
mScanBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
//registerReceiver(mBroadcastReceiver, filter);
if(mBlueAdapter!=null && mBlueAdapter.isEnabled()) {
listAdapter.clear();
mBlueAdapter.startDiscovery();
showToast("Discovery");
IntentFilter filtera = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mBroadcastReceiver, filter);
}
And this is my BroadcastReceiver
private final BroadcastReceiver mBroadcastReceiver = 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);
listAdapter.add(device.getName() + device.getAddress());
listAdapter.notifyDataSetChanged();
showToast("Action Scan Mode " );
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
mpossibleBtn.setText("Scanning Bluetooth Devices");
showToast("Scannning Bluetooth Devices... " );
} else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){
mpossibleBtn.setText("Scanning in progress...");
showToast("Scanning in progress... " );
}
if (action.equals(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED)) {
showToast("Action Scan Mode " );
int modeValue=intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, BluetoothAdapter.ERROR);
if(modeValue==BluetoothAdapter.SCAN_MODE_CONNECTABLE){
mPairedTv.setText("The device is not in discoverable mode but still can receive connections");
} else if(modeValue==BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE){
mPairedTv.setText("The device is in discoverable mode");
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String deviceName = device.getName();
String deviceHardwareAddress = device.getAddress(); // MAC address
showToast("onReceive: " + device.getName() + ": " + device.getAddress());
} else if (modeValue==BluetoothAdapter.SCAN_MODE_NONE){
mPairedTv.setText("The device is not in discoverable mode and can't receive connection");
} else{
mPairedTv.setText("Error");
}
}
}
};
I'm testing the app on my Xiaomi cellphone.
you need to ADD after registering receiver
mBtAdapter.startDiscovery();
Start discovery after registering your receiver.
IntentFilter intent = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
registerReceiver(mBroadcastReceiver, intent);
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mBroadcastReceiver, filter);
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mBroadcastReceiver, filter);
mBtAdapter.startDiscovery();
Or in your case
IntentFilter filtera = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mBroadcastReceiver, filter);
mBtAdapter.startDiscovery();
Also ensure you have bt permissions on your manifest
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
On some phones you will need to restart the adapter first.
mBluetoothAdapter.disable();
mBluetoothAdapter.enable();
for some time on the broadcast receiver if you don't receive BluetoothAdapter.ACTION_DISCOVERY_STARTED after starting discovery, you have to prompt device restart as the bt may not be working properly.you can use a timer to check this.
Ok so I just found my error. In this case BLUETOOTH and BLUETOOTH_ADMIN permissions have a protection Level of normal, and so all you need to do is request them in the manifest. The location permissions are dangerous, though, and so on Android 6.0+ devices, with a targetSdkVersion of 23 or higher, you need to request those at runtime.
I alredy have the permissions however, we do need to request ACCESS_COARSE_LOCATION at runtime.
This time the code works
mScanBtn.setOnClickListener(new View.OnClickListener() {
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
public void onClick(View v) {
if(mBlueAdapter!=null && mBlueAdapter.isEnabled()) {
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mBroadcastReceiver, filter);
if (context.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
if (mMap != null) {
mMap.setMyLocationEnabled(true);
mBlueAdapter.startDiscovery();
}
}
else {
// Permission to access the location is missing. Show rationale and request permission
PermissionUtils.requestPermission(MainActivity.this, MY_PERMISSIONS_REQUEST_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION, true);
mBlueAdapter.startDiscovery();
}
}
});
I'm working on application which shows list of certain connected bluetooth low energy devices, so user can choose which one of them he wants to configure.
The problem is that you can't just list all connected devices. As far as I know there are three possible ways:
Use BluetoothProfiles
bluetoothManager.getConnectedDevices(BluetoothProfile.GATT_SERVER);
This fails because android won't connect to GATT server, when device connects, so device is neither under GATT_SERVER nor GATT profile. However once I call connectGatt method,
bluetoothDevice.connectGatt(getApplicationContext(), false, gattCallback);
device can be found under both GATT_SERVER and GATT profile. Other profiles are not supported by low energy devices.
List paired devices and try connectGatt on each of them
List<BluetoothDevice> connectedDevices = new ArrayList<BluetoothDevice>();
for(BluetoothDevice device : bluetoothAdapter.getBondedDevices()) {
BluetoothGatt gatt = device.connectGatt(getApplicationContext(), false, gattCallback);
if(gatt != null) {
connectedDevices.add(device);
}
gatt.disconnect();
}
This method cannot be used as it cannot determine if device is already connected or only in range but not connected
On system boot start service listening to ACL_CONNECTED and ACL_DISCONNECTED intents and maintaining list of connected devices
Manifest
<service android:name=".ManagerService" android:enabled="true" />
<receiver
android:name=".BootFinishedReceiver"
android:directBootAware="true"
android:enabled="true"
android:exported="false"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
Receiver
public class BootFinishedReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context, ManagerService.class);
context.startService(serviceIntent);
}
}
Service
public class ManagerService extends Service {
private static List<BluetoothDevice> connectedDevices;
#Override
public void onCreate() {
connectedDevices = new ArrayList<BluetoothDevice>();
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
registerReceiver(connectionReceiver, filter);
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
unregisterReceiver(connectionReceiver);
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private final BroadcastReceiver connectionReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if(BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
connectedDevices.add(device);
}else{
connectedDevices.remove(device);
}
}
};
public static List<BluetoothDevice> getConnectedDevices() {
return connectedDevices;
}
}
Since 3.1 apps can no longer receive system intents before activity is started, so this cannot be used either.
Is there any other way or how can I achieve it now in later android versions?
Thanks for any suggestions
Well, I found out that you can still use ON_BOOT_COMPLETED, but you have to allow it in setting on your device. So my problem is solved
First i prompts the user to open the wifi or not.
I want to open the wifi if closed, scan all the wifi networks available and connect to certain one based on it's ssid.
I want to register a broad cast receiver to wait till the WifiManager to finish scanning results.
public class Project1 extends Activity {
/**
* Called when the activity is first created.
*/
EditText userName;
EditText passWord;
Button button;
TextView thankYou;
WifiManager wifiManager;
List<ScanResult> results1;
BroadcastReceiver receiver;
public Boolean connectToNetworK() {
Log.e("Start of connect","Debug");
Log.e("before wifi manager of connect","Debug");
if(!wifiManager.isWifiEnabled()){
Log.e("wifi is not enabled","Debug");
wifiManager.setWifiEnabled(true);
}
Log.e("after wifi manager of connect","Debug");
List<ScanResult>results =null;
Log.e("after scan result = null","Debug");
while(!wifiManager.isWifiEnabled())
{
Log.e("wifi still off","Debug");
}
Log.e("wifi is on","Debug");
Log.e("starting scan","Debug");
wifiManager.startScan();
Log.e("waiting","Debug");
if(results1!=null && !results1.isEmpty())
{
Log.e("Results1 is not emplty","Debug");
}
}
#Override
public void onStop()
{
unregisterReceiver(receiver);
}
public void onCreate(Bundle savedInstanceState) {
final Context contex = this;
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if(receiver == null){
Log.e("Registering reciver","mark");
receiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent){
Log.e("In broad cast reciver","mark");
results1 =wifiManager.getScanResults();
}
};
registerReceiver(receiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
}
}
if (!mWifi.isConnected()) {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Please Open the Wifi");
alert.setMessage("Your Wifi is Currently Turned off, Would You like to turn it on?");
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if(connectToMobinilNetworK())
{
AfterWifiIsOn();
}
else{
Intent intent = new Intent(contex, ErrorPage.class);
startActivity(intent);}
}
});
alert.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(contex, ErrorPage.class);
startActivity(intent);
}
});
alert.show();
} }
}
}
The list of scan resutls are always empty and the logs inside the broadcast receiver is not written.
Thanks in advance.
Do you have the correct permissions set up in your AndroidManifest? According to this guide, your permissions should look something like this:
<uses-sdk android:minSdkVersion="14" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />