Search code examples
androidbluetoothbroadcastreceiverrssi

Get rssi value with BroadcastReceiver


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) 

Solution

  • 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();