or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdnotification-permissions.mdpermission-checking.mdpermission-constants.mdpermission-requesting.mdplatform-specific-features.md

permission-requesting.mddocs/

0

# Permission Requesting

1

2

Request permissions from the user with optional rationale dialogs. Handles the native permission request flow and user interaction.

3

4

## Capabilities

5

6

### Request Single Permission

7

8

Request a single permission from the user, with optional rationale dialog for explanation.

9

10

```typescript { .api }

11

/**

12

* Request a single permission from the user

13

* @param permission - The permission to request

14

* @param rationale - Optional rationale dialog or function for explanation

15

* @returns Promise resolving to the permission status after user interaction

16

*/

17

function request(permission: Permission, rationale?: Rationale): Promise<PermissionStatus>;

18

19

type Rationale = RationaleObject | (() => Promise<boolean>);

20

21

interface RationaleObject {

22

title: string;

23

message: string;

24

buttonPositive: string;

25

buttonNegative?: string;

26

}

27

```

28

29

**Usage Examples:**

30

31

```typescript

32

import { request, PERMISSIONS, RESULTS } from "react-native-permissions";

33

34

// Basic permission request

35

const cameraStatus = await request(PERMISSIONS.IOS.CAMERA);

36

if (cameraStatus === RESULTS.GRANTED) {

37

console.log("Camera permission granted");

38

}

39

40

// Request with rationale dialog (Android)

41

const micStatus = await request(PERMISSIONS.ANDROID.RECORD_AUDIO, {

42

title: "Microphone Permission",

43

message: "This app needs microphone access to record audio for voice messages.",

44

buttonPositive: "Grant Access",

45

buttonNegative: "Not Now"

46

});

47

48

// Request with custom rationale function

49

const locationStatus = await request(

50

PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,

51

async () => {

52

// Custom logic to show rationale

53

const userWantsToGrant = await showCustomRationaleDialog();

54

return userWantsToGrant;

55

}

56

);

57

```

58

59

### Request Multiple Permissions

60

61

Request multiple permissions in a single call, with optional rationale for Android.

62

63

```typescript { .api }

64

/**

65

* Request multiple permissions simultaneously

66

* @param permissions - Array of permissions to request

67

* @returns Promise resolving to object mapping each permission to its status

68

*/

69

function requestMultiple<P extends Permission[]>(

70

permissions: P

71

): Promise<Record<P[number], PermissionStatus>>;

72

```

73

74

**Usage Examples:**

75

76

```typescript

77

import { requestMultiple, PERMISSIONS, RESULTS } from "react-native-permissions";

78

79

// Request multiple iOS permissions

80

const statuses = await requestMultiple([

81

PERMISSIONS.IOS.CAMERA,

82

PERMISSIONS.IOS.MICROPHONE,

83

PERMISSIONS.IOS.PHOTO_LIBRARY,

84

]);

85

86

// Check individual results

87

Object.entries(statuses).forEach(([permission, status]) => {

88

console.log(`${permission}: ${status}`);

89

});

90

91

// Check if all permissions were granted

92

const allGranted = Object.values(statuses).every(status => status === RESULTS.GRANTED);

93

if (allGranted) {

94

console.log("All permissions granted - ready to proceed");

95

} else {

96

console.log("Some permissions were denied");

97

}

98

99

// Request specific Android permissions for media access

100

const mediaStatuses = await requestMultiple([

101

PERMISSIONS.ANDROID.CAMERA,

102

PERMISSIONS.ANDROID.RECORD_AUDIO,

103

PERMISSIONS.ANDROID.READ_MEDIA_IMAGES,

104

]);

105

```

106

107

### Request Location Accuracy (iOS)

108

109

Request full location accuracy from the user when the app has reduced accuracy.

110

111

```typescript { .api }

112

/**

113

* Request location accuracy upgrade from reduced to full (iOS only)

114

* @param options - Configuration with purpose key from Info.plist

115

* @returns Promise resolving to the granted accuracy level

116

*/

117

function requestLocationAccuracy(options: LocationAccuracyOptions): Promise<LocationAccuracy>;

118

119

interface LocationAccuracyOptions {

120

purposeKey: string;

121

}

122

123

type LocationAccuracy = 'full' | 'reduced';

124

```

125

126

**Usage Examples:**

127

128

```typescript

129

import {

130

requestLocationAccuracy,

131

checkLocationAccuracy,

132

PERMISSIONS,

133

request

134

} from "react-native-permissions";

135

136

// First ensure location permission is granted

137

const locationStatus = await request(PERMISSIONS.IOS.LOCATION_WHEN_IN_USE);

138

if (locationStatus === RESULTS.GRANTED) {

139

const currentAccuracy = await checkLocationAccuracy();

140

141

if (currentAccuracy === 'reduced') {

142

// Request full accuracy using purpose key from Info.plist

143

const newAccuracy = await requestLocationAccuracy({

144

purposeKey: 'NSLocationDefaultAccuracyReduced'

145

});

146

147

if (newAccuracy === 'full') {

148

console.log("Full location accuracy granted");

149

} else {

150

console.log("User chose to keep reduced accuracy");

151

}

152

}

153

}

154

```

155

156

### Request Notification Permissions

157

158

Request notification permissions with specific notification types and optional rationale.

159

160

```typescript { .api }

161

/**

162

* Request notification permissions with specific options

163

* @param options - Array of notification types to request

164

* @param rationale - Optional rationale for Android

165

* @returns Promise resolving to notification status and detailed settings

166

*/

167

function requestNotifications(

168

options?: NotificationOption[],

169

rationale?: Rationale

170

): Promise<NotificationsResponse>;

171

172

type NotificationOption =

173

| 'alert'

174

| 'badge'

175

| 'sound'

176

| 'carPlay'

177

| 'criticalAlert'

178

| 'provisional'

179

| 'providesAppSettings';

180

181

interface NotificationsResponse {

182

status: PermissionStatus;

183

settings: NotificationSettings;

184

}

185

```

186

187

**Usage Examples:**

188

189

```typescript

190

import { requestNotifications, RESULTS } from "react-native-permissions";

191

192

// Request basic notification permissions

193

const basicNotifications = await requestNotifications(['alert', 'badge', 'sound']);

194

if (basicNotifications.status === RESULTS.GRANTED) {

195

console.log("Basic notifications granted");

196

}

197

198

// Request advanced notification permissions (iOS)

199

const advancedNotifications = await requestNotifications([

200

'alert',

201

'badge',

202

'sound',

203

'criticalAlert',

204

'provisional'

205

]);

206

207

console.log("Notification settings:", advancedNotifications.settings);

208

209

// Request with rationale (Android)

210

const androidNotifications = await requestNotifications(

211

['alert', 'badge'],

212

{

213

title: "Enable Notifications",

214

message: "Get notified about important updates and messages.",

215

buttonPositive: "Enable",

216

buttonNegative: "Skip"

217

}

218

);

219

220

// Check specific notification capabilities

221

if (advancedNotifications.settings.criticalAlert) {

222

console.log("Critical alerts are enabled");

223

}

224

if (advancedNotifications.settings.provisional) {

225

console.log("Provisional notifications are enabled");

226

}

227

```

228

229

## Permission Request Flow

230

231

The request flow varies by platform:

232

233

### iOS Request Flow

234

1. First request shows system dialog

235

2. If denied, subsequent requests return 'denied' immediately

236

3. User must manually enable in Settings if 'blocked'

237

4. Some permissions (like notifications) can be requested multiple times

238

239

### Android Request Flow

240

1. Shows rationale dialog if provided and needed

241

2. Shows system permission dialog

242

3. If denied twice, permission becomes 'blocked'

243

4. Some permissions require specific Android versions

244

245

```typescript

246

import { request, check, openSettings, PERMISSIONS, RESULTS } from "react-native-permissions";

247

248

async function requestCameraWithFallback() {

249

// Check current status first

250

let status = await check(PERMISSIONS.IOS.CAMERA);

251

252

if (status === RESULTS.DENIED) {

253

// Request permission

254

status = await request(PERMISSIONS.IOS.CAMERA);

255

}

256

257

if (status === RESULTS.BLOCKED) {

258

// Permission is blocked, direct user to settings

259

console.log("Camera permission is blocked. Please enable in Settings.");

260

await openSettings();

261

}

262

263

return status === RESULTS.GRANTED;

264

}

265

```

266

267

## Rationale Best Practices

268

269

### Effective Rationale Messages

270

- Explain **why** the permission is needed

271

- Be specific about the feature it enables

272

- Keep messages concise and user-friendly

273

- Use positive language

274

275

```typescript

276

// Good rationale example

277

const goodRationale = {

278

title: "Camera Access Required",

279

message: "Camera access is needed to take photos for your profile and share them with friends.",

280

buttonPositive: "Grant Access",

281

buttonNegative: "Not Now"

282

};

283

284

// Poor rationale example - too vague

285

const poorRationale = {

286

title: "Permission Required",

287

message: "This app needs camera permission to work properly.",

288

buttonPositive: "OK",

289

buttonNegative: "Cancel"

290

};

291

```

292

293

### Custom Rationale Function

294

Use custom rationale functions for complex logic or custom UI:

295

296

```typescript

297

import { request, PERMISSIONS } from "react-native-permissions";

298

299

const customRationaleFunction = async (): Promise<boolean> => {

300

// Show custom modal or alert

301

const result = await showCustomPermissionDialog({

302

title: "Location Access",

303

message: "Enable location to find nearby restaurants and get personalized recommendations.",

304

primaryButton: "Enable Location",

305

secondaryButton: "Maybe Later"

306

});

307

308

return result.action === 'primary';

309

};

310

311

const locationStatus = await request(

312

PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,

313

customRationaleFunction

314

);

315

```

316

317

## Error Handling

318

319

Request functions may throw errors in these cases:

320

321

- **Invalid Permission**: Requesting unsupported permissions

322

- **Native Module Error**: Native module initialization failures

323

- **Platform Incompatibility**: Platform-specific method calls on wrong platform

324

325

```typescript

326

import { request, PERMISSIONS } from "react-native-permissions";

327

328

async function safeRequestPermission(permission: Permission) {

329

try {

330

const status = await request(permission);

331

return { success: true, status };

332

} catch (error) {

333

console.error("Permission request failed:", error);

334

return { success: false, error };

335

}

336

}

337

338

// Usage

339

const result = await safeRequestPermission(PERMISSIONS.IOS.CAMERA);

340

if (result.success) {

341

console.log("Permission status:", result.status);

342

} else {

343

console.log("Request failed:", result.error);

344

}

345

```