Flutter - Android Native
Instructions for adding grouplink sdk natively on Flutter.
Android on Flutter
To use our native lib for Android, create a directory named libs under the app folder inside the android part of the Flutter app. Follow further instruction on the Quickstart Android section, to download the framework, and register the Grouplink lib.

Create a class extending Application on the Android project of flutter.
1package com.grouplink.flutter_grouplink_settings;23...45public class App extends Application {6 @Override7 public void onCreate() {8 super.onCreate();910 GroupLink.register{11 getApplicationContext(),12 "YOUR_GROUP_LINK_TOKEN",13 true14 );1516 ...17 }1819 ...20}
Follow further instructions on the Quickstart Android section. If you need help asking runtime permissions in Flutter, just follow the guide Asking Runtime Permissions (ANDROID-Flutter).
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.
1<uses-permission2 android:name="android.permission.INTERNET" />3<uses-permission4 android:name="android.permission.ACCESS_FINE_LOCATION " />5<uses-permission6 android:name="android.permission.ACCESS_COARSE_LOCATION" />7<uses-permission8 android:name="android.permission.BLUETOOTH_ADMIN" />9<uses-permission10 android:name="android.permission.ACCESS_WIFI_STATE" />11<uses-permission12 android:name="android.permission.FOREGROUND_SERVICE"/>1314 <!-- Mandatory permissions for Android 12 and above.-->15 <!-- Also, they should be asked in runtime. -->16 <uses-permission17 android:name="android.permission.BLUETOOTH_SCAN"18 android:minSdkVersion="31"19 android:usesPermissionFlags="neverForLocation" />20 <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />21 <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />2223 <!-- Mandatory permissions for Android 13 and above. -->24 <!-- Also, should be asked in runtime. -->25 <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.
1//Example of permissions request by Android Api Lvl23import android.Manifest;4import android.annotation.SuppressLint;5import android.content.Intent;6import android.content.pm.PackageManager;7import android.os.Build;8import android.os.Bundle;910import androidx.annotation.RequiresApi;11import androidx.appcompat.app.AppCompatActivity;12import androidx.core.app.ActivityCompat;13import androidx.fragment.app.Fragment;1415public class MainActivity extends AppCompatActivity {1617 private static final int REQUEST_PERMISSION_CODE = 420;18 private static final int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE = 0;1920 private static final String[] REQUIRED_PERMISSIONS = {21 Manifest.permission.BLUETOOTH,22 Manifest.permission.BLUETOOTH_ADMIN,23 Manifest.permission.ACCESS_FINE_LOCATION,24 Manifest.permission.ACCESS_COARSE_LOCATION25 };2627 private static final String[] REQUIRED_PERMISSIONS_Q = {28 Manifest.permission.BLUETOOTH,29 Manifest.permission.BLUETOOTH_ADMIN,30 Manifest.permission.ACCESS_FINE_LOCATION,31 Manifest.permission.ACCESS_COARSE_LOCATION32 };3334 @RequiresApi(api = Build.VERSION_CODES.S)35 private static final String[] REQUIRED_PERMISSIONS_S =36 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) ?37 new String[]{38 Manifest.permission.BLUETOOTH,39 Manifest.permission.BLUETOOTH_ADMIN,40 Manifest.permission.ACCESS_FINE_LOCATION,41 Manifest.permission.ACCESS_COARSE_LOCATION,42 Manifest.permission.BLUETOOTH_SCAN,43 Manifest.permission.BLUETOOTH_ADVERTISE,44 Manifest.permission.BLUETOOTH_CONNECT,45 Manifest.permission.POST_NOTIFICATIONS46 } :47 new String[]{48 Manifest.permission.BLUETOOTH,49 Manifest.permission.BLUETOOTH_ADMIN,50 Manifest.permission.ACCESS_FINE_LOCATION,51 Manifest.permission.ACCESS_COARSE_LOCATION,52 Manifest.permission.BLUETOOTH_SCAN,53 Manifest.permission.BLUETOOTH_ADVERTISE,54 Manifest.permission.BLUETOOTH_CONNECT55 };5657 private int count = 0;58 private int countAutoStart = 0;5960 @SuppressLint("NewApi")61 @Override62 protected void onCreate(Bundle savedInstanceState) {63 super.onCreate(savedInstanceState);64 setContentView(R.layout.activity_main);65 requestGlPermissions();66 }676869 private void requestGlPermissions() {70 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {71 if (!hasNeededPermissionsS()) {72 requestPermissionsS();73 return;74 }75 }76 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {77 if (!hasNeededPermissionsQ()) {78 requestPermissionsQ();79 return;80 }81 }82 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {83 if (!hasNeededPermissions()) {84 requestPermissions();85 return;86 }87 }88 if (countAutoStart < 1) {89 countAutoStart++;90 }91 }9293 private boolean hasNeededPermissions() {94 for (String permission : REQUIRED_PERMISSIONS) {95 if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {96 return false;97 }98 }99 return true;100 }101102 private boolean hasNeededPermissionsQ() {103 for (String permission : REQUIRED_PERMISSIONS_Q) {104 if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {105 return false;106 }107 }108 return true;109 }110111 @RequiresApi(Build.VERSION_CODES.S)112 private boolean hasNeededPermissionsS() {113 for (String permission : REQUIRED_PERMISSIONS_S) {114 if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {115 return false;116 }117 }118 return true;119 }120121 @RequiresApi(Build.VERSION_CODES.M)122 private void requestPermissions() {123 requestPermissions(REQUIRED_PERMISSIONS, REQUEST_PERMISSION_CODE);124 }125126 @RequiresApi(Build.VERSION_CODES.Q)127 private void requestPermissionsQ() {128 requestPermissions(REQUIRED_PERMISSIONS_Q, REQUEST_PERMISSION_CODE);129 }130131 @RequiresApi(Build.VERSION_CODES.S)132 private void requestPermissionsS() {133 requestPermissions(REQUIRED_PERMISSIONS_S, REQUEST_PERMISSION_CODE);134 }135136 @SuppressWarnings("deprecation")137 @Override138 protected void onActivityResult(int requestCode, int resultCode, Intent data) {139 if (requestCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE) {140 requestGlPermissions();141 }142 super.onActivityResult(requestCode, resultCode, data);143 }144145 @Override146 public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {147 if (requestCode == REQUEST_PERMISSION_CODE) {148 if (count < REQUIRED_PERMISSIONS_Q.length) {149 count++;150 requestGlPermissions();151 return;152 }153 if (countAutoStart < 1) {154 countAutoStart++;155 }156 }157 super.onRequestPermissionsResult(requestCode, permissions, grantResults);158 }159}
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.