ibeaconaltbeaconandroid-ibeaconandroid-10.0kontakt.io

Altbeacon stopped working on Android10 and didEnterRegion does not get called at all


altbeacon on Android 10 has simply stopped working. Are there any changes required especially to go to Android 10?

I have added the following permissions to my AndroidManifest.xml

<uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\"/>
<uses-permission android:name=\"android.permission.BLUETOOTH\"/>
<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>
<uses-permission android:name=\"android.permission.ACCESS_BACKGROUND_LOCATION\"/>
<uses-permission android:name=\"android.permission.RECEIVE_BOOT_COMPLETED\" />
<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>

Looking at the app permissions, my app has the location and BT permissions granted while running. I start looking for beacons on onBeaconServiceConnect as prescribed at https://altbeacon.github.io/android-beacon-library/samples.html. What am I missing?


Solution

  • Android 10 adds new permissions requirements to do BLE scans and detect BLE beacons -- any app setting targetSdkVersion 29 or higher needs to obtain permissions as described below or no beacons will be detected. (If you set targetSdkVersion 28 or earlier, these new requirements do not apply when running on Android 10, as Android grants the permissions automatically. This allows old apps to continue running unaffected after upgrading to Android 10.)

    The changes below are what you need to to if you set your project to targetSdkVersion 29 or higher:

    In addition to adding these permissions to the manifest:

    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
    

    You must also dynamically obtain the location permissions from the user as described here:

    private static final int PERMISSION_REQUEST_FINE_LOCATION = 1;
        private static final int PERMISSION_REQUEST_BACKGROUND_LOCATION = 2;
    ...
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            ...
    
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (this.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
                        == PackageManager.PERMISSION_GRANTED) {
                    if (this.checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
                            != PackageManager.PERMISSION_GRANTED) {
                        if (this.shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) {
                            final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                            builder.setTitle("This app needs background location access");
                            builder.setMessage("Please grant location access so this app can detect beacons in the background.");
                            builder.setPositiveButton(android.R.string.ok, null);
                            builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
    
                                @TargetApi(23)
                                @Override
                                public void onDismiss(DialogInterface dialog) {
                                    requestPermissions(new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION},
                                            PERMISSION_REQUEST_BACKGROUND_LOCATION);
                                }
    
                            });
                            builder.show();
                        }
                        else {
                            final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                            builder.setTitle("Functionality limited");
                            builder.setMessage("Since background location access has not been granted, this app will not be able to discover beacons in the background.  Please go to Settings -> Applications -> Permissions and grant background location access to this app.");
                            builder.setPositiveButton(android.R.string.ok, null);
                            builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
    
                                @Override
                                public void onDismiss(DialogInterface dialog) {
                                }
    
                            });
                            builder.show();
                        }
    
                    }
                } else {
                    if (this.shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
                        requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
                                        Manifest.permission.ACCESS_BACKGROUND_LOCATION},
                                PERMISSION_REQUEST_FINE_LOCATION);
                    }
                    else {
                        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                        builder.setTitle("Functionality limited");
                        builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons.  Please go to Settings -> Applications -> Permissions and grant location access to this app.");
                        builder.setPositiveButton(android.R.string.ok, null);
                        builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
    
                            @Override
                            public void onDismiss(DialogInterface dialog) {
                            }
    
                        });
                        builder.show();
                    }
    
                }
            }
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode,
                                               String permissions[], int[] grantResults) {
            switch (requestCode) {
                case PERMISSION_REQUEST_FINE_LOCATION: {
                    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                        Log.d(TAG, "fine location permission granted");
                    } else {
                        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                        builder.setTitle("Functionality limited");
                        builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons.");
                        builder.setPositiveButton(android.R.string.ok, null);
                        builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
    
                            @Override
                            public void onDismiss(DialogInterface dialog) {
                            }
    
                        });
                        builder.show();
                    }
                    return;
                }
                case PERMISSION_REQUEST_BACKGROUND_LOCATION: {
                    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                        Log.d(TAG, "background location permission granted");
                    } else {
                        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                        builder.setTitle("Functionality limited");
                        builder.setMessage("Since background location access has not been granted, this app will not be able to discover beacons when in the background.");
                        builder.setPositiveButton(android.R.string.ok, null);
                        builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
    
                            @Override
                            public void onDismiss(DialogInterface dialog) {
                            }
    
                        });
                        builder.show();
                    }
                    return;
                }
            }
        }
    

    If you do not see this working, go to Settings -> Apps -> Your App -> Permissions and verify location had been granted.