2

I am new to Android App developing and BLE, and I am learning these using the sample code BluetoothLeGatt [The one I imported from Android Studio]. The code works fine on my tablet (Android 5.0), but the scan activity does not return any BLE devices on Android 6.0. The error message I got is shown below.

07-19 12:41:39.615 7617-7642/? W/Binder: Caught a RuntimeException from the binder stub implementation.
                                     java.lang.SecurityException: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to get scan results
                                         at android.os.Parcel.readException(Parcel.java:1599)
                                         at android.os.Parcel.readException(Parcel.java:1552)
                                         at android.bluetooth.IBluetoothGatt$Stub$Proxy.startScan(IBluetoothGatt.java:772)
                                         at android.bluetooth.le.BluetoothLeScanner$BleScanCallbackWrapper.onClientRegistered(BluetoothLeScanner.java:331)
                                         at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:56)
                                         at android.os.Binder.execTransact(Binder.java:458)

I looked at the post Bluetooth Low Energy startScan on Android 6.0 does not find devices and the official page Requesting Permissions at Run Time, but I still don't really know how to modify my code.

I did add the permissions of GPS, ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION, and I turned on the Location Service on my tablet.

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-feature android:name="android.hardware.location.gps" />

But the App still cannot return any BLE devices. Then, when I try to add the following block of code to my App (from Requesting Permissions at Run Time ), there is always an error on checkSelfPermission [Cannot resolve symbol 'checkSelfPermission']. But I did import import android.support.v4.content.ContextCompat;

Can someone help me with this? Also, is there a simpler answer to the question how to make DeviceScanActivity work? I don't really know where to put the blocks of the code from Requesting Permissions at Run Time to my code :( I know this is a really stupid question, but I am really new to this field. Please help me!

// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
            Manifest.permission.READ_CONTACTS)
    != PackageManager.PERMISSION_GRANTED) {

// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
        Manifest.permission.READ_CONTACTS)) {

    // Show an explanation to the user *asynchronously* -- don't block
    // this thread waiting for the user's response! After the user
    // sees the explanation, try again to request the permission.

} else {

    // No explanation needed, we can request the permission.

    ActivityCompat.requestPermissions(thisActivity,
            new String[]{Manifest.permission.READ_CONTACTS},
            MY_PERMISSIONS_REQUEST_READ_CONTACTS);

    // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
    // app-defined int constant. The callback method gets the
    // result of the request.
}
}

EDIT The following is my dependencies block.

dependencies {
compile "com.android.support:support-v4:25.3.1"
compile "com.android.support:support-v13:25.3.1"
compile "com.android.support:cardview-v7:25.3.1"
compile "com.android.support:appcompat-v7:25.3.1"
}
Natalie
  • 63
  • 6

2 Answers2

1

Thank you everyone for your responses and help! I've just solved my case!

What I did is that besides adding the permissions in AndroidManifest.xml, I added the following code to my onCreate method in DeviceScanActivity, and the reference I used is Requesting Permissions at Run Time. Also, I just randomly assigned a number to MY_PERMISSIONS_REQUEST_LOCATION.

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getActionBar().setTitle(R.string.title_devices);
        mHandler = new Handler();
    //Check for permissions
        int permissionCheck = ContextCompat.checkSelfPermission(this,
            Manifest.permission.WRITE_CALENDAR);
        Log.e(TAG, "Permission Status: " +permissionCheck );

    //***********************************************************
    // 
        if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_COARSE_LOCATION)
            != PackageManager.PERMISSION_GRANTED)
        {

            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                Manifest.permission.ACCESS_COARSE_LOCATION))
            {

            // Show an explanation to the user *asynchronously* -- don't block
            // this thread waiting for the user's response! After the user
            // sees the explanation, try again to request the permission.

            } 
            else
            {

            // No explanation needed, we can request the permission.

            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
                    MY_PERMISSIONS_REQUEST_LOCATION);
            }
        }

    ......//The rest of code
    }

When I first added the above code, there is a pop-up window coming up on my tablet asking me for permissions, and I clicked "allow." Then, I am able to scan my ble devices.

BTW, it only asks for my permission once. When I clicked "Run Application" later (after slight modifications of my code), it didn't ask for my permission again.

Natalie
  • 63
  • 6
0

Do you add those all permissions:

<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" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

It works fine on android 6.0