Camera permission keeps being denied on iOS - ios

This code is requesting camera permission to initialize camera to use it later, it works fine on Android, but on iOS the permission keeps being denied on its own without showing permission request dialogue box
void _initCamera() async {
if (await PermissionsService().hasCameraPermission()) {
setState(() {
isCameraPermissionGranted = true;
});
print('camera permission granted');
} else {
bool isGranted = await PermissionsService().requestCameraPermission(
onPermissionDenied: () {
AppUtil.showAlertDialog(
context: context,
heading: 'info',
message:
'You must grant this camera access to be able to use this feature.',
firstBtnText: 'Give Permission',
firstFunc: () async {
Navigator.of(context).pop(false);
await _initCamera();
},
secondBtnText: 'Leave',
secondFunc: () async {
print('camera permission denied');
Navigator.of(context).pop();
Navigator.of(context).pop();
},
);
});
setState(() {
isCameraPermissionGranted = isGranted;
});
return;
}
if (isCameraPermissionGranted) {
//initialization code
}
any idea why this behavior happens?

Add this line in info.plist file in Runner folder of iOS this will give camera access permission to iOS app
<key>NSCameraUsageDescription</key>
<string>This app requires access to the camera.</string>

Related

Ionic - How to request permission again after user rejected once?

Currently, I can request permission for microphone with the following code if the user has not rejected granting permissions:
permission = await this.diagnostic.isMicrophoneAuthorized();
if (!permission) {
permission = await this.diagnostic.requestMicrophoneAuthorization()
.then(async () => {
console.log('this.diagnostic.requestMicrophoneAuthorization succeed.');
return await this.diagnostic.isMicrophoneAuthorized();
})
.catch((err) => {
console.error('this.diagnostic.requestMicrophoneAuthorization failed, error: ', err);
return false;
})
}
But once they reject the request, the requestMicrophoneAuthorization is still triggered, but no dialog pop up and the result always returns false.
Is there a way to request the authorization again with Ionic 3?
To do this, you will need to use the cordova-diagnostic-plugin to check the current microphone authorization status and request authorization again if it has been denied.
import { Diagnostic } from '#ionic-native/diagnostic/ngx';
constructor(private diagnostic: Diagnostic) {}
async requestMicrophoneAuthorization() {
// Check the current microphone authorization status
let authorizationStatus = await this.diagnostic.getMicrophoneAuthorizationStatus();
if (authorizationStatus === this.diagnostic.permissionStatus.DENIED_ALWAYS) {
// If the authorization has been denied always, we need to ask the user to grant
// microphone permission again.
try {
// Request microphone authorization
authorizationStatus = await this.diagnostic.requestMicrophoneAuthorization();
console.log('Microphone authorization status: ', authorizationStatus);
} catch (error) {
console.error('Error requesting microphone authorization: ', error);
}
}
}

IOS Simulator Location Access Problem - Flutter

Future<String> getCurrentLocation() async {
late Placemark place;
try {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.low);
latitude = position.latitude;
longitude = position.longitude;
print("Geolocator worked");
List<Placemark> placemarks =
await placemarkFromCoordinates(latitude, longitude);
place = placemarks[0];
print("Location to city worked");
print("Place: ${place.locality}");
} catch (e) {
print(e);
}
return place.locality.toString();
}
Here is my code to get current location and the city name of the current lat-log. However, when I started the code, I can't see any permission screen on my simulator. Simulator version is iOS 15.2.
And here is the error code from try-catch block:
flutter: User denied permissions to access the device's location.
However, like I said no permission access screen shows up on my simulator.
Also:
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to location when open.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs access to location when in the background.</string>
I already added these to Info.plist.
Add permission_handler package to your pubspec.yaml, and ask for permission before trying to use Geolocator. There are different possibilities, check the following code:
import 'package:permission_handler/permission_handler.dart';
Future<bool> isLocationAvailable() async {
// get current permission status of location
var permissionStatus = await Permission.locationWhenInUse.status;
// if restricted, it can't be used
if (permissionStatus == PermissionStatus.restricted) {
return Future.value(false);
}
// it can be switched off, so it can't be used
if (!await Permission.locationWhenInUse.serviceStatus.isEnabled) {
return Future.value(false);
}
// if user permanently denied access, it can't be used
if (permissionStatus == PermissionStatus.permanentlyDenied) {
return Future.value(false);
}
// get permission and return result
return await Permission.locationWhenInUse.request().isGranted;
}
And call this before you try to get location:
if (await isLocationAvailable()) {
// get location here
}

Turn on Wifi and connect to a protected SSID on ios with react native

I am working on IOT project with react native in which Phone must connect to a protected WiFi(no internet connection). I should programmatically turn on WiFi and connect to the protected ssid. So, I used the following library: https://github.com/JuanSeBestia/react-native-wifi-reborn.
On android, I have full control on device and everything works like a charm. On the other hand, on ios, I can't turn wifi on and even after that user turns the wifi on, it seems defined functions in library like connectToProtectedSSID just doesn't work.
Any advice would be appreciated.
P.s. I exactely followed the document in the library including location access in both platforms.
Finally, the solution for both platforms:
iOS:
with the following approach app will turn on WIFI and connect to the specific SSID (at least for iOS 13):
You should add these capabilities to your app :
Access WiFi Information
Hotspot Configuration ( this is missed in the README ! )
(iOS 13) "Privacy - Location When In Use Usage
Description" or "Privacy - Location Always and When In Use Usage
Description" in Settings -> info
import WifiManager from "react-native-wifi-reborn";
ConnectToNetwork = async () => {
WifiManager.connectToProtectedSSID("YourSSIDName", "YourPassword", false)
.then(
() => {
//console.log("connectToProtectedSSID successfully!");
},
(reason) => {
//console.log("connectToProtectedSSID failed!");
//console.log(reason);
}
);
}
Android:
Don't forget to turn on location!
disconnecting from the current SSID and connecting to the desired one:
import RNAndroidLocationEnabler from 'react-native-android-location-enabler';
import WifiManager from "react-native-wifi-reborn";
ConnectToNetwork() {
WifiManager.setEnabled(true);
WifiManager.disconnect();
//WifiManager.forceWifiUsage(true);
PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
title: '',
message:'',
buttonNegative: '',
buttonPositive: '',
},
).then((granted) => {
//console.log(granted);
if (granted === PermissionsAndroid.RESULTS.GRANTED)
{
//console.log("granted");
RNAndroidLocationEnabler.promptForEnableLocationIfNeeded({interval: 10000, fastInterval: 5000})
.then(data => {
WifiManager.connectToProtectedSSID("YourSSIDName", "YourPassword", false)
.then(
() => {
//console.log("connectToProtectedSSID successfully!");
},
(reason) => {
//console.log("connectToProtectedSSID failed!");
//console.log(reason);
}
);
//console.log("location enabled");
//WifiManager.connectToProtectedSSID("", "", false)
WifiManager.getCurrentWifiSSID().then(
ssid => {
if(ssid =="YourSSIDName"){
}
else {
}
//console.log("Your current connected wifi SSID is " + ssid);
},
() => {
//console.log("Cannot get current SSID!");
}
);
}).catch(err => {
//console.log("not permitted to enable location");
});
}
else
{
//console.log("not granted");
// Permission denied
}
// expected output: "Success!"
});
}
There is no public API to control the Wifi on iOS.
Method setEnabled is only for android.

React Native Ios Push Notification Not Working

I use '#react-native-firebase/messaging' module to send notifications. On Android everything works fine, Following is the error log I get when I try const fcmToken = await firebase.messaging().getToken(); on ios device.
NativeFirebaseError: [messaging/unknown] The operation couldn’t be completed. (com.firebase.iid error 1001.)
I have already implemented "react-native-permissions" to grant notification permission.
My AppDelegate.m contains :
if ([FIRApp defaultApp] == nil) {
[FIRApp configure];
}
Should I add anything else to it?
Any help or suggestion will be very helpful.
Thanks in advance
You need to check and ask messaging permission before get the fcm token in iOS
/**
* Check is notification showing permission enabled if not ask the permission.
*/
async checkFcmPermission() {
firebase
.messaging()
.hasPermission()
.then(enabled => {
if (enabled) {
// User has permissions
this.getFcmToken(); // const fcmToken = await firebase.messaging().getToken();
} else {
// User doesn't have permission
firebase
.messaging()
.requestPermission()
.then(() => {
// User has authorized
this.getFcmToken(); // const fcmToken = await firebase.messaging().getToken();
})
.catch(error => {
// User has rejected permissions
console.log(
'PERMISSION REQUEST :: notification permission rejected',
);
});
}
});
}
There are a lot of solutions to this issue. I post my answer since some StackOverflow users requested.
Here is my code
const sleep = ms => {
return new Promise(resolve => setTimeout(resolve, ms));
};
async function requestPermissionForNotification() {
try {
const permission = await requestNotifications(["alert", "badge", "sound"]);
if (permission.status === "granted") {
setupNotification();
}
} catch (e) {
console.log(e)
}
};
async function setupNotification() {
try {
await sleep(5000)
// TODO no need token for now, Will be used for future releases
const enabled = await firebase.messaging().hasPermission();
await requestNotifications(['alert', 'badge', 'sound']);
await firebase.messaging().registerForRemoteNotifications();
const token = await firebase.messaging().getToken();
firebase.messaging().onMessage(async (remoteMessage) => {
});
} catch (e) {
console.log(e)
}
}
And Also I have added following to Info.plist
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
To sum up, I use react permissions to grant permission and the sleep method is to wait for firebase to be ready. Finally uninstalled app couple time to get a result.
When It started working, I couldn't dare to touch the code since I spent days on this.

Determining if geolocation enabled with react native

Building an app with RN I use the following to receive user's location :
navigator.geolocation.getCurrentPosition(
(position) => {
//do stuff with location
},
(error) => {
//error or locaiton not allowed
},
{enableHighAccuracy: true, timeout: 20000, maximumAge: 1000}
);
Which immediately invokes the inquiry for user to accept geolocation permissions. What I'm trying to achieve now is to have an explicit screen before prompting user to click on a button to accept those permissions. In order to get there, I need some way to check if he has accepted those permissions before or not. Caching it in storage would be a bad solution - it might go out of sync if user changes permissions in settings.
How can I check if user has accepted geolocation permissions without triggering the permission alert?
You can use this library https://github.com/yonahforst/react-native-permissions to check if user has accepted location permission.
Like this:
Permissions.getPermissionStatus('location')
.then(response => {
this.setState({ locationPermission: response })
})
In v2.x.x of react-native-permissions (https://github.com/react-native-community/react-native-permissions)
import { Platform } from "react-native";
import { PERMISSIONS, request } from "react-native-permissions";
import * as Geolocation from "#react-native-community/geolocation";
try {
request(
Platform.select({
android: PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
ios: PERMISSIONS.IOS.LOCATION_WHEN_IN_USE
})
).then(res => {
if (res == "granted") {
Geolocation.getCurrentPosition( // do location staffs);
Geolocation.watchPosition( // do watch location staffs );
} else {
// console.log("Location is not enabled");
}
});
} catch (error) {
console.log("location set error:", error);
}
Check this library, this would help you to check location is enabled or not.
https://www.npmjs.com/package/react-native-device-info#isLocationEnabled
Note : Above will not check permission enabled on not. It will just check location truned on or not

Resources