Flutter - Android Native

Team
SDK Team
Last Updated
June 10, 2026

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;
2
3...
4
5public class App extends Application {
6 @Override
7 public void onCreate() {
8 super.onCreate();
9
10 GroupLink.register{
11 getApplicationContext(),
12 "YOUR_GROUP_LINK_TOKEN",
13 true
14 );
15
16 ...
17 }
18
19 ...
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-permission
2 android:name="android.permission.INTERNET" />
3<uses-permission
4 android:name="android.permission.ACCESS_FINE_LOCATION " />
5<uses-permission
6 android:name="android.permission.ACCESS_COARSE_LOCATION" />
7<uses-permission
8 android:name="android.permission.BLUETOOTH_ADMIN" />
9<uses-permission
10 android:name="android.permission.ACCESS_WIFI_STATE" />
11<uses-permission
12 android:name="android.permission.FOREGROUND_SERVICE"/>
13
14 <!-- Mandatory permissions for Android 12 and above.-->
15 <!-- Also, they should be asked in runtime. -->
16 <uses-permission
17 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" />
22
23 <!-- 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_scanbluetooth_advertisebluetooth_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 Lvl
2
3import android.Manifest;
4import android.annotation.SuppressLint;
5import android.content.Intent;
6import android.content.pm.PackageManager;
7import android.os.Build;
8import android.os.Bundle;
9
10import androidx.annotation.RequiresApi;
11import androidx.appcompat.app.AppCompatActivity;
12import androidx.core.app.ActivityCompat;
13import androidx.fragment.app.Fragment;
14
15public class MainActivity extends AppCompatActivity {
16
17 private static final int REQUEST_PERMISSION_CODE = 420;
18 private static final int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE = 0;
19
20 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_LOCATION
25 };
26
27 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_LOCATION
32 };
33
34 @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_NOTIFICATIONS
46 } :
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_CONNECT
55 };
56
57 private int count = 0;
58 private int countAutoStart = 0;
59
60 @SuppressLint("NewApi")
61 @Override
62 protected void onCreate(Bundle savedInstanceState) {
63 super.onCreate(savedInstanceState);
64 setContentView(R.layout.activity_main);
65 requestGlPermissions();
66 }
67
68
69 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 }
92
93 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 }
101
102 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 }
110
111 @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 }
120
121 @RequiresApi(Build.VERSION_CODES.M)
122 private void requestPermissions() {
123 requestPermissions(REQUIRED_PERMISSIONS, REQUEST_PERMISSION_CODE);
124 }
125
126 @RequiresApi(Build.VERSION_CODES.Q)
127 private void requestPermissionsQ() {
128 requestPermissions(REQUIRED_PERMISSIONS_Q, REQUEST_PERMISSION_CODE);
129 }
130
131 @RequiresApi(Build.VERSION_CODES.S)
132 private void requestPermissionsS() {
133 requestPermissions(REQUIRED_PERMISSIONS_S, REQUEST_PERMISSION_CODE);
134 }
135
136 @SuppressWarnings("deprecation")
137 @Override
138 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 }
144
145 @Override
146 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.