Skip to main content

Must Have Permissions

Before you start

Warning: It is strongly advised to request any necessary runtime permissions after the user launches your application for the first time. In scenarios where your application features a login page, failure to request these permissions may result in incomplete user registration.

1. Adding permissions to Android Manifest

Add permissions

Add the follow permissions inside your project.

Access fine location permission must be asked for in app.

Some of the permissions below must be requested on runtime.

For location specifically, your app must display a prominent disclosure through a pop-up alert before your app’s location runtime permission.


<uses-permission
android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION " />
<uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission
android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission
android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission
android:name="android.permission.FOREGROUND_SERVICE"/>

<!-- Mandatory permissions for Android 12 and above.-->
<!-- Also, they should be asked in runtime. -->
<uses-permission
android:name="android.permission.BLUETOOTH_SCAN"
android:minSdkVersion="31"
android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

<!-- Mandatory permissions for Android 13 and above. -->
<!-- Also, should be asked in runtime. -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

2. Asking Runtime Permissions

Disclaimer: It is recommended to ask the permissions at launch. If one or more of the permissions are missing for the target api of the device, the SDK will not start. Avoid requesting permissions after login.

(Optional) For newer Android versions (API 34 and above) it is also recommended to request the FullScreenIntent permission by launching the following intent ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT. You may also request Manifest.permission.SCHEDULE_EXACT_ALARM by starting android.provider.Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM. The SDK will work normally on most devices even without these two permissions, but they are known to help on more esoteric Android roms.

Since api lvl 23 (Android 6.0) location permission must be requested at runtime. In Flutter and React-Native, access_fine_location and access_coarse_location are known as while_in_use type location.

Since api lvl 31 (Android 12) there are new permissions to access, connect and identify nearby devices. To use this bluetooth features, bluetooth_scan, bluetooth_advertise, bluetooth_connect permissions must be asked at runtime.

Follow the link Asking Runtime Permissions (ANDROID-Flutter) for further instructions on how to ask runtime permissions on Flutter.

Follow the link Asking Runtime Permissions (ANDROID-React-Native) for further instructions on how to ask runtime permissions on React-Native.

//Example of permissions request by Android Api Lvl

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;

public class MainActivity extends AppCompatActivity {

private static final int REQUEST_PERMISSION_CODE = 420;
private static final int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE = 0;

private static final String[] REQUIRED_PERMISSIONS = {
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
};

private static final String[] REQUIRED_PERMISSIONS_Q = {
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
};

@RequiresApi(api = Build.VERSION_CODES.S)
private static final String[] REQUIRED_PERMISSIONS_S =
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) ?
new String[]{
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_ADVERTISE,
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.POST_NOTIFICATIONS
} :
new String[]{
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_ADVERTISE,
Manifest.permission.BLUETOOTH_CONNECT
};

private int count = 0;
private int countAutoStart = 0;

@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
requestGlPermissions();
}


private void requestGlPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
if (!hasNeededPermissionsS()) {
requestPermissionsS();
return;
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
if (!hasNeededPermissionsQ()) {
requestPermissionsQ();
return;
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
if (!hasNeededPermissions()) {
requestPermissions();
return;
}
}
if (countAutoStart < 1) {
countAutoStart++;
}
}

private boolean hasNeededPermissions() {
for (String permission : REQUIRED_PERMISSIONS) {
if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}

private boolean hasNeededPermissionsQ() {
for (String permission : REQUIRED_PERMISSIONS_Q) {
if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}

@RequiresApi(Build.VERSION_CODES.S)
private boolean hasNeededPermissionsS() {
for (String permission : REQUIRED_PERMISSIONS_S) {
if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}

@RequiresApi(Build.VERSION_CODES.M)
private void requestPermissions() {
requestPermissions(REQUIRED_PERMISSIONS, REQUEST_PERMISSION_CODE);
}

@RequiresApi(Build.VERSION_CODES.Q)
private void requestPermissionsQ() {
requestPermissions(REQUIRED_PERMISSIONS_Q, REQUEST_PERMISSION_CODE);
}

@RequiresApi(Build.VERSION_CODES.S)
private void requestPermissionsS() {
requestPermissions(REQUIRED_PERMISSIONS_S, REQUEST_PERMISSION_CODE);
}

@SuppressWarnings("deprecation")
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE) {
requestGlPermissions();
}
super.onActivityResult(requestCode, resultCode, data);
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == REQUEST_PERMISSION_CODE) {
if (count < REQUIRED_PERMISSIONS_Q.length) {
count++;
requestGlPermissions();
return;
}
if (countAutoStart < 1) {
countAutoStart++;
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}

3. (Optional) Asking Runtime Background Location

Remember, your prominent disclosure must:

  • Appear before your app’s location runtime permission.

  • Include at least the following sentence, adapted to include all the relevant features requesting access to location in the background in the app that are readily visible to the user: “This app collects location data to enable ["feature"], ["feature"], & ["feature"] even when the app is closed or not in use.” If you extend permitted usage to ads, please also include: “This data is also used to provide ads/support advertising/support ads.”

  • Include any other details necessary to make it clear to the user how and why you are using location in the background. While additional content is permitted, it should not cause the required content to not be immediately visible.

4. Bluetooth Permissions and Location Permissions Rationale

BLUETOOTH_ADVERTISE (API level > 31)

Description: Allows the application to use Bluetooth to advertise the presence of the device, enabling interaction with nearby devices compatible with the GroupLink SDK. This permission is essential to facilitate campaigns and events among nearby devices.

BLUETOOTH_CONNECT (API level > 31)

Description: Enables the application to connect to Bluetooth devices compatible with the GroupLink SDK. This permission is necessary to establish secure connections and carry out interactions between devices during specific campaigns and events.

BLUETOOTH_SCAN (API level > 31)

Description: Allows the application to scan for Bluetooth devices in the vicinity that also have the GroupLink SDK. This functionality is essential to identify and interact with relevant devices during campaigns and events.

BLUETOOTH_ADMIN

Description: Grants the application control over the Bluetooth settings of the device. This permission is necessary to ensure that the GroupLink SDK can operate effectively, coordinating interactions between devices during specific events.

Regarding location-related permissions:

ACCESS_COARSE_LOCATION

Description: This permission is required for Bluetooth communication on Android devices with API versions prior to 31. Additionally, it allows access to approximate location information to enable interactions between devices compatible with the GroupLink SDK during campaigns and events.

ACCESS_FINE_LOCATION

Description: Similar to the previous permission but also grants access to more precise location information for Android devices with API versions prior to 31. This precision is necessary for the effectiveness of interactions between devices in proximity.