react-native 0.59 migrated to API 29 how to request permission on location - react-native

I'm using rn 0.59.
Currently on Android API 28, when you request a permission,
It has an option for 'Allow all the time'
But when I shifted to API 29.
It is gone on the permission box.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
export async function requestLocationPermission() {
try {
const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
return PermissionsAndroid.RESULTS.GRANTED;
} else if (granted === PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN) {
return PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN;
} else {
return PermissionsAndroid.RESULTS.DENIED;
}
} catch (err) {
return false;
}
};
how can you access the background location here, since it has only ACCESS_FINE_LOCATION?
Thanks!

https://developer.android.com/training/location/permissions#request-background-location
On Android 11 (API level 30) and higher, however, the system dialog doesn't include the Allow all the time option. Instead, users must enable background location on a settings page.
You can help users navigate to this settings page by following best practices when requesting the background location permission. The process for granting the permission depends on your app's target SDK version.
Open settings using the same permissions library that you're using :
https://github.com/zoontek/react-native-permissions#opensettings
import {openSettings} from 'react-native-permissions';
openSettings().catch(() => console.warn('cannot open settings'));

I created a bridge on android
int permissionCheck = ContextCompat.checkSelfPermission(this.getReactApplicationContext(),
Manifest.permission.ACCESS_BACKGROUND_LOCATION);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
promise.resolve(true);
} else {
final Activity activity = getCurrentActivity();
ActivityCompat.requestPermissions(
activity,
new String[]{
Manifest.permission.ACCESS_BACKGROUND_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
},
MY_PERMISSIONS_REQUEST_LOCATION
);
promise.resolve(false);
}

Related

Photo still not seen after PermissionsAndroid.PERMISSIONS.CAMERA is granted

My React Native 0.66 app needs to have CAMERA permission to access the photos in gallery in Android. Following is the permission function added to splash screen when the app is being launched.
//require Camera permission when open gallery
const requestCameraPermission = async () => {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.CAMERA,
{
title: "添加权限",
message:
"app正常运行需要用到相册。请点OK ",
buttonNegative: "Cancel",
buttonPositive: "OK"
}
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
return true; //console.log("You can use the camera");
} else {
console.log
}
} catch (err) {
console.log(err);
}
};
if (Platform.OS === 'android') requestCameraPermission();
When the gallery is accessed first time, the function above pops up a window asking for the permission. After click OK, however, the image picked is still not seen in the app. Also in device under Setting -> App -> the app permission, permission for CAMERA was not there. BTW, the config (which is not shown here) for image picking on iOS works fine.
You need to add permission in your Native Modules.
In AndroidManifest.xml(Android),
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
In Info.plist(iOS),
<key>NSCameraUsageDescription</key>
<string>Your own description of the purpose</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Your message to user when the photo library is accessed for the first time</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Your message to user when the photo library is accessed for the first time</string>
Also in you app/build.gradle file,
defaultConfig {
...
missingDimensionStrategy 'react-native-camera', 'general' // <--- insert this line
}

expo-camera: Error: Permissions module is null

I have an error in console after to install expo-camera.
expo install expo-camera
add permission in android manifest
add module expo camera in maven
allprojects {
repositories {
// * Your other repositories here *
// * Add a new maven block after other repositories / blocks *
maven {
// expo-camera bundles a custom com.google.android:cameraview
url "$rootDir/../node_modules/expo-camera/android/maven"
}
}
}
start the protect
click on the button to show camera ... error in log
Error: Permissions module is null.
Permission:
<uses-permission android:name="android.permission.CAMERA" />
update 1 :
I test with this code example to check my permission
https://reactnative.dev/docs/permissionsandroid
my example function
// state local
const [hasPermission, setHasPermission] = useState(null);
// function
const requestCameraPermission = async () => {
console.log('requestCameraPermission')
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.CAMERA,
{
title: "Cool Photo App Camera Permission",
message:
"Cool Photo App needs access to your camera " +
"so you can take awesome pictures.",
buttonNeutral: "Ask Me Later",
buttonNegative: "Cancel",
buttonPositive: "OK"
}
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
setHasPermission(true)
console.log("You can use the camera");
} else {
console.log("Camera permission denied");
setHasPermission(false)
}
} catch (err) {
console.warn(err);
}
};
// result of requestCameraPermission : You can use the camera
// Error : Attempt to invoke interface method 'boolan expo.modules.interfaces.permission.Permission.hasGrantedPermissions(java.lang.string[]) on a null object reference
I make something wrong ?
thanks for help
If you did just these steps, you have to do more things to make it works on Android device.
Github page says:
Adjust the android/build.gradle to add a new maven block after all other repositories as described below:
allprojects {
repositories {
// * Your other repositories here *
// * Add a new maven block after other repositories / blocks *
maven {
// expo-camera bundles a custom com.google.android:cameraview
url "$rootDir/../node_modules/expo-camera/android/maven"
}
}
}
But before do that, you should:
For bare React Native projects, you must ensure that you have installed and configured the react-native-unimodules package before continuing.

react-native-fs cannot access storage

i'm using react-native-fs package to save files to android storage.
when i perform these two lines of code, it works
await RNFS.readDir(RNFS.DocumentDirectoryPath);
=====>/data/user/0/com.youtubedljs/files
await RNFS.readDir(RNFS.CachesDirectoryPath);
=====>/data/user/0/com.youtubedljs/cache
but when i try to access external storage, like Download or documents files
await RNFS.readDir(RNFS.DownloadDirectoryPath);
i get this error
Error: Attempt to get length of null array
i already granted storage permissions to the application, it didn't work.
Update: Works fine on android 8.1, i think that the package doesn't support android 10 yet
Need to give read-write permissions.
that's okay.. but you also need to get incode permissions, before accessing file
import {PermissionsAndroid} from 'react-native';
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
//alert('You can use the location');
console.log('write granted');
return true;
} else {
return false;
}
} catch (err) {
console.warn(err);
return false;
}
First you have to ask for permission
then you can save the into download folder of mobile
import {request, PERMISSIONS} from 'react-native-permissions';
request(
Platform.OS === 'ios'
? PERMISSIONS.IOS.MEDIA_LIBRARY
: PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE,
).then(result => {
console.log(result);
);
});
var path = RNFS.DownloadDirectoryPath + '/filename.txt';

ReactNative - PermissionDialog after launching app - 'remove' won't work

In ReactNative app, we are using Storage permission to view/save pictures. So we're getting runtime permission where its required. But the strange thing is, it was asking permission in Splash screen itself, where we didn't ask permission. Then I came across the following fix:
https://facebook.github.io/react-native/docs/removing-default-permissions
Removing Permission using 'remove':
<uses-permission tools:node="remove" android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
But the problem is, If I do like this, I can't get those permissions where its needed.
So ideally, I would like to remove permission dialog in SplashScreen and add only where its required. Please advise.
This answer might seems bit odd to you, but I was in same situation, where I need to use Storage Permission of zip extraction in my current application.
The way I manage things are as follows:
I asked permission in Android Code using React Native Bridging
concept.
I add delay to show permission dialog on next screen (i.e
after splash screen)
When user grant me permission I started extraction and overlay loader to full screen.
When user denied the storage permission I closed the application.
Check the code below
NextScreen After Splash
this.onZipExtracted = this.onZipExtracted.bind(this)
componentDidMount() {
setTimeout(() => {
Splash.hide()
}, Platform.OS == 'ios' ? 1000 : 500);
if (Platform.OS === 'android') {
AsyncStorage.getItem("Extraction",(error,result)=>{
if(result != 'done'){
this.setState({
animating:true
})
setTimeout(() => {
expandPath.callReactMethod(this.onZipExtracted, (error) => {
console.log("Activation Inside Callback"+JSON.stringify(error))
//Do your stuff
})
}, 500)
}
})
}
}
onZipExtracted(success){
console.log("Activation Callback Extract Success -> "+JSON.stringify(success))
this.setState({
set loader flag
})
AsyncStorage.setItem("Extraction","done")
Actions.replace('Screen to replace')
}
Java Code for Permission
I used Dexter Android Permission Library
#ReactMethod
public void callReactMethod(Callback successCallback, Callback errorCallback){
callUserPermission(getCurrentActivity(), successCallback,errorCallback);
}
private void callUserPermission(Activity currentActivity, Callback successCallback, Callback errorCallback) {
Dexter.withActivity(getCurrentActivity())
.withPermissions(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
.withListener(new MultiplePermissionsListener() {
#Override
public void onPermissionsChecked(MultiplePermissionsReport report) {
// check if all permissions are granted
if (report.areAllPermissionsGranted()) {
Log.i(TAG, "onPermissionsChecked: -> Granted");
// Do your stuff here
}
} else {
currentActivity.finishAffinity();
System.exit(0);
}
// check for permanent denial of any permission
if (report.isAnyPermissionPermanentlyDenied()) {
// permission is denied permenantly, navigate user to app setting
}
}
#Override
public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions,
PermissionToken token) {
token.continuePermissionRequest();
}
})
.onSameThread()
.check();
}

Requesting Run time permission in android in react native

I am trying to add runtime permission feature in my react native app but unable to add. Please help me. Here is my code. I have tried all the methods but it is not working.
samplefunction=()=>{
async function requestCameraPermission() {
try {
const granted = PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.CAMERA,
{
'title': 'Cool Photo App Camera Permission',
'message': 'Cool Photo App needs access to your camera ' +
'so you can take awesome pictures.'
}
)
if (granted === true || granted === PermissionsAndroid.RESULTS.GRANTED){
console.log("You can use the camera")
Alert.alert("You can use the camera")
} else {
console.log("Camera permission denied")
Alert.alert("Camera permission denied")
}
} catch (err) {
console.warn(err)
}
}
requestCameraPermission(false);
}
Make sure you have added this line in AndroidManifest.xml before you use thePermissionAndroid feature:
<uses-permission android:name="android.permission.CAMERA" />
The permission mechanism is asynchronous, and returns a promise. You should await the result:
const granted = await PermissionsAndroid.request( ...