I want to get rssi value with BroadcastReceiver. When I implemented the code below on Android 4 worked well(also the code just had the BroadcastReceiver and was registered the broadcastReceiver and didn't have that requests for permissions) but didn't answer in Android 6 and upper. I read that BroadcastReceiver has changed for Android 6+ and it needs ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permission.I added this in android manifest and requested permissions in MainActivity but when I run the code on phone which has Android 7 and click the button when a bluetooth device is near that, is throws exception and when nothing is near when I click the button it shows nothing.
Here is my code:
public class MainActivity extends AppCompatActivity {
private BluetoothAdapter BTAdapter = BluetoothAdapter.getDefaultAdapter();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
checkLocationPermission();
proceedDiscovery();
}
});
}
private final BroadcastReceiver receiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Toast.makeText(MainActivity.this,action, Toast.LENGTH_LONG).show();
if(BluetoothDevice.ACTION_FOUND.equals(action)) {
int rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,Short.MIN_VALUE);
String name = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
TextView rssi_msg = (TextView) findViewById(R.id.textView);
rssi_msg.setText(rssi_msg.getText() + name + " => " + rssi + "dBm"+"\n");
}
}
};
protected void checkLocationPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
{
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 0);
int MY_PERMISSIONS_REQUEST = 200;
int permissions=ContextCompat.checkSelfPermission (this,Manifest.permission.ACCESS_FINE_LOCATION);
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST);
}}
}
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 0: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
proceedDiscovery();
}
else{}
break;
}
}}
protected void proceedDiscovery() {
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothDevice.ACTION_NAME_CHANGED);
registerReceiver(receiver, filter);
BTAdapter.startDiscovery();
}}
and my android manifest has these permissions:
<uses-feature android:name="android.hardware.bluetooth" />
<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" />
I got help for permissions from this link: correct procedure for BT device discovery on Marshmallow
Exceptions in logcat:
08-16 14:33:16.341 6630-6630/com.example.hanane.rssi E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.hanane.rssi, PID: 6630
java.lang.RuntimeException: Error receiving broadcast Intent { act=android.bluetooth.device.action.FOUND flg=0x10 launchParam=MultiScreenLaunchParams { mDisplayId=0 mBaseDisplayId=0 mFlags=0 } bqHint=1 (has extras) } in com.example.hanane.rssi.MainActivity$2@a1e9394
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:1195)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6816)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1565)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1453)
Caused by: android.content.res.Resources$NotFoundException: String resource ID #0xffffffd4
at android.content.res.Resources.getText(Resources.java:1184)
at android.widget.Toast.makeText(Toast.java:460)
at com.example.hanane.rssi.MainActivity$2.onReceive(MainActivity.java:75)
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:1185)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6816)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1565)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1453)
As your exception says, the problem is in calling
Toast.makeText(MainActivity.this,action, Toast.LENGTH_LONG).show();
As documentation says, Toast.makeText
requires string resource identifier (R.string.<something>
) as 2nd parameter in one overload, or a String
in another, while you are passing action
, which is causing Toast to look for the resource with the identifier of the action
value, which it can't find.
If you want to Toast
the action
value, you have to convert it to string first. Easiest way is to use it as action + ""
:
Toast.makeText(MainActivity.this,action + "", Toast.LENGTH_LONG).show();