Android Studio Java Bluetooth LE doesn't work - java

So I have my Arduino advertising BLE, I can download, "BLE Scanner" app to connect to it and it works that way. Now I'm writing app on Android to connect to that Arduino. I've got following code but it doesn't work:
ScanCallback scanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, final ScanResult result) {
super.onScanResult(callbackType, result);
System.out.println("Callback: " + callbackType);
}
#Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
System.out.println("callback error");
}
};
BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();
BluetoothLeScanner mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
ScanSettings scanSettings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
mLEScanner.startScan(null,scanSettings,scanCallback);
and I'm getting this error:
I/BNRClientProivder, VERSION : 1.7.5: register - xml6 quick_backup : ACCESSIBILITYSETTINGS, X6qErjsfs2, com.android.settings.accessibility.sharedaccessibility.scloud.BNRTask
I/QBNRClientHelper: init SyncClientHelper : ACCESSIBILITYSETTINGS
I/BNRClientProivder, VERSION : 1.7.5: register - xml6 quick_backup : CONNECTIONS, C0phMaUuZZ, com.android.settings.wifi.mobileap.WifiApBackupRestore
I/QBNRClientHelper: init SyncClientHelper : CONNECTIONS
I/BNRClientProivder, VERSION : 1.7.5: register - xml6 quick_backup : WiFi, C0phMaUuZZ, com.android.settings.wifi.WifiBackupRestore

Accessibility settings seems like permissions. You need to allow for ble features within the application.
Go to your manifest file add bluetooth permissions and location permissions
Then you will need to grant the app permissions when you run it. Go to your open apps and press the 3 dots, app info, permissions location enable.
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
Also I cant see what the scan result it. On a ble scan callback you get the device address, scan record(advert data) and the rssi(power received).

Related

startBluetoothSco keeps jumping between SCO_AUDIO_STATE_CONNECTED and SCO_AUDIO_STATE_DISCONNECTED

I'm trying to connect to a bluetooth headset to record audio from device , the issue is that it shows that it is connected but right after it goes to disconnected for some reason , i'm debugging the code but could not figure out the problem , i would appreciate anyone giving some help , Thank you
Manifest File
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<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
public void onCreate() {
super.onCreate();
recorder = new Recorder(getApplicationContext());
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
nm = (NotificationManager) getApplicationContext()
.getSystemService(Context.NOTIFICATION_SERVICE);
settings = Core.getInstance().getCache().getPrefs();
self = this;
// register new receiver for bluetooth headset
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if(bluetoothAdapter.isEnabled()){
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); // API 11
intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); // API 8
intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED); // API 14
registerReceiver(broadcastReceiver,intentFilter);
audioManager.startBluetoothSco();
}
}
Receiver code
// when the call starts it executed CONNECTED then right after it goes to DISCONNECTED
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(AudioManager.SCO_AUDIO_STATE_CONNECTED == state){
Log.d("TAG","Connected");
audioManager.setSpeakerphoneOn(false);
audioManager.setBluetoothScoOn(true);
} else if (AudioManager.SCO_AUDIO_STATE_DISCONNECTED == state){
Log.d("TAG","Disconnected");
}
}
};

Huawei Honor 10 blocked Bluetooth when app is running

I`m development network radio app for Android API 21-29 and all worked fine but one cases confuses me. On Huawei Honor 10 when my app started playing and trying to switch on the Bluetooth nothing works. Device turn-off Bluetooth and all. I add this permission in my AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
If Bluetooth turn on before playing, he turn off right after start play.
I used this method when app send mediasession.OnPlay
#Override
public void onPlay() {
if (!exoPlayer.getPlayWhenReady()) {
startService(new Intent(getApplicationContext(), PlayerService.class));
if (stationsRepository == null)
return;
station = stationsRepository.getCurrent();
bitrate = Connectivity.currentBitrate;
String stream = station.getStreamByBitrate(bitrate);
prepareToPlay(Uri.parse(stream));
mediaSession.setQueueTitle(station.getTitle());
if (!audioFocusRequested) {
audioFocusRequested = true;
int audioFocusResult;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
audioFocusResult = audioManager.requestAudioFocus(audioFocusRequest);
} else {
audioFocusResult = audioManager.requestAudioFocus(audioFocusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
}
if (audioFocusResult != AudioManager.AUDIOFOCUS_REQUEST_GRANTED)
return;
}
mediaSession.setActive(true);
registerReceiver(becomingNoisyReceiver, new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
exoPlayer.setPlayWhenReady(true);
}
mediaSession.setPlaybackState(stateBuilder.setState(PlaybackStateCompat.STATE_PLAYING, PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN, 1).build());
currentState = PlaybackStateCompat.STATE_PLAYING;
refreshNotificationAndForegroundStatus(currentState);
}
On same devices uses Android 10, Android 8, Android 7 all work is fine.
Can anyone help me fix with this.
P.S. Sorry for my English. This is the first time when I ask a question in this language.
Update: Tested on Huawei P30 lite and catch this bug too.

UsbDevice requestPermission is denied without showing the request dialog prompt

I'm trying to use usb camera devices connected to my android device. So initially i have got the details of the usb devices connected through UsbManager.getDeviceList() method. Then i iterated through every device and requested for permission if permission was already not granted.
Prior to requesting the permission i have registered a global BroadCastReceiver to listen to the response of the requested permission.
Here is the MainActivity.java:
public class MainActivity extends AppCompatActivity {
private UsbManager usbManager_;
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
public PendingIntent permissionIntent;
private static String TAG = "testing";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// SurroundView surroundView = new SurroundView(this);
// setContentView(surroundView);
usbManager_ = (UsbManager) getSystemService(USB_SERVICE);
permissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
requestUsbPermissions();
}
private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.i(TAG, "received intent by broadcast " + intent.getAction());
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if (device != null) {
Log.i(TAG, "got the permission");
}
} else {
Log.d(TAG, "permission denied for device " + device);
}
}
}
}
};
public void requestUsbPermissions(){
HashMap<String, UsbDevice> deviceList = usbManager_.getDeviceList();
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
this.registerReceiver(usbReceiver, filter);
Log.i(TAG, "registered broadcast receiver!");
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while (deviceIterator.hasNext()) {
UsbDevice device = deviceIterator.next();
Log.i(TAG,
"Camera: device Id " + device.getDeviceId() + " device mName : " + device.getDeviceName());
if (!usbManager_.hasPermission(device)) {
Log.i(TAG, "requesting permission");
usbManager_.requestPermission(device, permissionIntent);
}
}
}
}
So when i run the app it detects one usb device connected and requests permission for the same. But the dialog box which asks for user input never comes. Instead when the intent is received by the BroadCastReceiver the value of intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false) will always be false which means the permission is already denied. Can anyone explain to me why the dialog box is not coming in the first place and why the permission is denied automatically.
Here is my AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.vision_sdk_testing">
<uses-feature android:name="android.hardware.usb.host" android:required="true"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
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>
</manifest>
And below is the output log:
2020-05-01 17:56:05.282 30769-30769/com.example.vision_sdk_testing I/testing: registered broadcast receiver!
2020-05-01 17:56:05.283 30769-30769/com.example.vision_sdk_testing I/testing: Camera: device Id 1003 device mName : /dev/bus/usb/001/003
2020-05-01 17:56:05.283 30769-30769/com.example.vision_sdk_testing I/testing: requesting permission
2020-05-01 17:56:05.301 30769-30769/com.example.vision_sdk_testing I/testing: received intent by broadcast com.android.example.USB_PERMISSION
2020-05-01 17:56:05.302 30769-30769/com.example.vision_sdk_testing D/testing: permission denied for device UsbDevice[mName=/dev/bus/usb/001/003,mVendorId=1443,mProductId=38192,mClass=239,mSubclass=2,mProtocol=1,mManufacturerName=Sonix Technology Co., Ltd.,mProductName=USB 2.0 Camera,mVersion=1.00,mSerialNumberReader=android.hardware.usb.IUsbSerialReader$Stub$Proxy#d41ebfa,mConfigurations=[
UsbConfiguration[mId=1,mName=null,mAttributes=128,mMaxPower=128,mInterfaces=[
UsbInterface[mId=0,mAlternateSetting=0,mName=HD USB Camera,mClass=14,mSubclass=1,mProtocol=0,mEndpoints=[]]
UsbConfiguration[mId=3,mName=null,mAttributes=3,mMaxPower=88,mInterfaces=[]]
Any help is appreciated. Thanks!
For me, I had to go into the app's permissions in the settings menu and give my app the Camera permission. I'm guessing it's because my USB device is a camera? Once I granted this permission, the app worked just as described in the docs https://developer.android.com/guide/topics/connectivity/usb/host

How to turn on location in order to display found bluetooth device

I am trying to do a indoor location services using bluetooth LE scan to search for beacons. However, in order to display found bluetooth devices, location need to be turned on.
I tried searching online for solutions but to no avail. I have only enable the permission for the app not to turn on the location.
this is the code for the permission
if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("This app needs location access");
builder.setMessage("Please grant location access so this app can detect peripherals.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
}
});
builder.show();
}
i have also added the permission in android manifest.xml
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

BluetoothAdapter.getBondedDevices returns zero Devices although paired, why?

I'm currently trying to write an Android App which connects to a Device using Bluetooth and opens a serial connection. To connect to the device I need to pass the device to some Code which establishes and maintains the connection. My Problem is that I don't seem to get to this point because my code always returns a NullPointer as device.
I've already tried debugging the code and now found out that the function to get bonded devices returns zero devices. To mitigate this I've made sure that the bluetooth adapter is existent and is turned on. I've also made sure in the android menu that there are devices connected and that the android device I want to establish a connection to has been paired with.
Below is the code which should identify and return the device:
public class BluetoothDeviceRecognition {
BluetoothDevice blDevice(BluetoothAdapter myBluetoothAdapter) {
Set<BluetoothDevice> pairedDevices = myBluetoothAdapter.getBondedDevices();
BluetoothDevice myDevice = null;
if(pairedDevices.size() > 0){
for (BluetoothDevice device : pairedDevices){
if (device.getName().equals("ESP32_LED_Control")) {
myDevice = device;
}
}
}
return myDevice;
}
This is the Code which should make sure that there is a bluetooth adapter and which should enable it if this is not the case:
public void startBluetooth(){
if(mBluetoothAdapter == null)
{
Log.d(TAG, "connectBluetooth: Does not have Bluetooth Capabilities");
return;
}
if(!mBluetoothAdapter.isEnabled())
{
Log.d(TAG, "connectBluetooth: Enabling Bluetooth");
Intent enableBTIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivity(enableBTIntent);
}
}
And this is the code which starts the code above:
connect.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try{
startBluetooth();
BluetoothDevice myDevice = mBluetoothDevice.blDevice(mBluetoothAdapter);
connectBluetooth(myDevice, MY_UUID_INSECURE);
}
catch(NullPointerException e){
Log.d(TAG, "connectBluetooth: Bluetooth Device cannot be Null");
sent.setText("Error, Bluetooth Device cannot be Null");
}
}
});
When setting a break point at the beginning of the if loop in the first code snippet, I expect to have the size of the pairedDevices be greater than 0 but the actual size of the pairedDevices is zero.
EDIT:
My Manifest File:
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
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>
My Target SDK should be 21.
EDIT:
So I didn't really solve this but instead used a different approach. Instead of looking for devices which were paired with my device I am instead looking for devices which are currently discoverable near me. Used this code: https://github.com/mitchtabian/Sending-and-Receiving-Data-with-Bluetooth
Before calling mBluetoothDevice.blDevice(mBluetoothAdapter), you must make sure that bluetooth has been turned on. So you just need to use startActivityForResult(enableBTIntent) to enable bluetooth and receive the result from onActivityResult(), once you receive the reslut that user turns on bluetooth, you can call mBluetoothDevice.blDevice(mBluetoothAdapter).
You are Missing The Location Permission,
As Stated in the Documentation :
https://developer.android.com/guide/topics/connectivity/bluetooth#Permissions
If your target Sdk is 23 and higher, you should ask for this Permission at runtime

Categories

Resources