Permissions
Demander les permissions d'app pour la caméra, les notifications et la localisation avec des patterns de dégradation gracieuse.
Permissions
Les applications mobiles doivent demander la permission avant d'accéder aux capacités de l'appareil comme la caméra, la localisation ou les notifications. ScaleRocket Mobile utilise l'API de permissions d'Expo pour une expérience multi-plateforme cohérente.
Comment fonctionnent les permissions
| Plateforme | Comportement |
|---|---|
| iOS | Affiche un dialogue système une seule fois. Si refusé, l'utilisateur doit aller dans Réglages |
| Android | Affiche un dialogue système. Peut être "refusé définitivement" après deux refus |
Les deux plateformes suivent le même pattern : vérifier, demander, gérer le refus.
Vérifier avant de demander
Vérifiez toujours l'état actuel avant d'afficher un prompt :
import * as ImagePicker from "expo-image-picker";
async function pickImage() {
const { status } = await ImagePicker.getMediaLibraryPermissionsAsync();
if (status !== "granted") {
const { status: newStatus } = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (newStatus !== "granted") {
Alert.alert(
"Permission Required",
"Please enable photo access in Settings to upload images.",
[
{ text: "Cancel", style: "cancel" },
{ text: "Open Settings", onPress: () => Linking.openSettings() },
]
);
return;
}
}
// Permission accordée — continuer
const result = await ImagePicker.launchImageLibraryAsync();
}Permissions courantes
Caméra
import { Camera } from "expo-camera";
const [permission, requestPermission] = Camera.useCameraPermissions();
if (!permission?.granted) {
return (
<View>
<Text>Camera access is required to take photos</Text>
<Button title="Grant Permission" onPress={requestPermission} />
</View>
);
}Notifications push
import * as Notifications from "expo-notifications";
async function requestNotificationPermission() {
const { status: existing } = await Notifications.getPermissionsAsync();
let finalStatus = existing;
if (existing !== "granted") {
const { status } = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== "granted") {
console.log("Notification permission denied");
return false;
}
return true;
}Localisation
import * as Location from "expo-location";
async function requestLocation() {
const { status } = await Location.requestForegroundPermissionsAsync();
if (status !== "granted") {
Alert.alert("Permission Denied", "Location access is needed for this feature.");
return null;
}
const location = await Location.getCurrentPositionAsync({});
return location;
}Quand demander
Le timing compte pour le taux d'acceptation :
| Timing | Taux d'acceptation | Quand l'utiliser |
|---|---|---|
| Au lancement de l'app | Faible | Jamais — les utilisateurs ne savent pas encore pourquoi |
| Avant la première utilisation | Élevé | Quand l'utilisateur déclenche une fonctionnalité |
| Après explication | Le plus élevé | Montrer pourquoi vous en avez besoin, puis demander |
Pattern d'écran de pré-permission
Montrez une explication avant le dialogue système :
function CameraPermissionScreen({ onGranted }: { onGranted: () => void }) {
const [permission, requestPermission] = Camera.useCameraPermissions();
if (permission?.granted) {
onGranted();
return null;
}
return (
<View style={{ flex: 1, justifyContent: "center", padding: 24 }}>
<Ionicons name="camera" size={64} color="#3B82F6" />
<Text style={{ fontSize: 20, fontWeight: "600", marginTop: 16 }}>
Camera Access
</Text>
<Text style={{ color: "#6B7280", marginTop: 8 }}>
We need camera access to scan QR codes and take profile photos.
</Text>
<Button title="Enable Camera" onPress={requestPermission} />
</View>
);
}Dégradation gracieuse
Fournissez toujours une alternative quand la permission est refusée :
function AvatarUpload() {
const [permission] = ImagePicker.useMediaLibraryPermissions();
if (!permission?.granted) {
return (
<View>
<Avatar name={user.name} size="lg" />
<Text style={{ color: "#9CA3AF", marginTop: 8 }}>
Enable photo access in Settings to upload a profile picture
</Text>
</View>
);
}
return <AvatarWithUpload user={user} />;
}Descriptions Info.plist iOS
iOS nécessite des descriptions lisibles pour chaque permission. Ajoutez-les dans app.json :
{
"expo": {
"ios": {
"infoPlist": {
"NSCameraUsageDescription": "We use the camera to take profile photos and scan QR codes",
"NSPhotoLibraryUsageDescription": "We access your photos to let you upload a profile picture",
"NSLocationWhenInUseUsageDescription": "We use your location to show nearby services",
"NSFaceIDUsageDescription": "We use Face ID to secure your account"
}
}
}
}Important : Les apps avec des descriptions de permission vagues ou manquantes seront rejetées par Apple.