jungleMan
jungleMan

Reputation: 888

How do I request permission for Android Device Location in React Native at run-time?

I have been trying to use React Native 's GeoLocalisation for an Android App. The poorly documentated module is found here https://facebook.github.io/react-native/docs/geolocation.html. According to the documentation, you handle location permissions on Android using the following code in the AndroidManifest.xml file

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

However, my online research suggests that the above line of code is useless for versions of ANDROID >= 6.0

As my implementation of GeoLocation is not currently working, I have no other reason but to believe that location permissions are not correctly handled.

How do I successfully request location permission at run-time for React Native Android App?

Upvotes: 41

Views: 134438

Answers (7)

vibhu
vibhu

Reputation: 377

this is for react-native after debugging and follow GitHub and stack overflow i'm able to find the region how to solve this in my build.gradel file i have target sdk version is 33

   buildToolsVersion = "33.0.0"
    minSdkVersion = 21
    compileSdkVersion = 33
    targetSdkVersion = 33

   androidmainifest.xml
   
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.awesomeproject">          

       <uses-permission 
      android:name="android.permission.ACCESS_FINE_LOCATION" />
  <uses-feature android:name="android.hardware.bluetooth_le" 
  android:required="true" />
 <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
 <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>

  </manifest>

in js file

 import { Platform, PermissionsAndroid } from 'react-native';

 // Function to request Bluetooth permissions
  const requestBluetoothPermissions = async () => {
 if (Platform.OS === 'android') {
 if (Platform.Version >= 31) {
  // Handle target API 31 and above
  try {
    const granted = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
      {
        title: 'Bluetooth Permission',
        message: 'This app requires Bluetooth Connect permission.',
        buttonPositive: 'OK',
      },
    );
    if (granted === PermissionsAndroid.RESULTS.GRANTED) {
      // Permission granted, continue with Bluetooth functionality
    } else {
      // Permission denied, handle accordingly
    }
    } catch (error) {
    // Handle error
   }
   } else {
    // Handle target API below 31
    try {
    const granted = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
      {
        title: 'Bluetooth Permission',
         message: 'This app requires access to your location to scan for 
       Bluetooth devices.',
        buttonPositive: 'OK',
      },
    );
    if (granted === PermissionsAndroid.RESULTS.GRANTED) {
      // Permission granted, continue with Bluetooth functionality
    } else {
      // Permission denied, handle accordingly
    }
      } catch (error) {
    // Handle error
   }
  }
 }
};

 // Call the function to request Bluetooth permissions
requestBluetoothPermissions();

  note  if (Platform.OS === 'android') //important condition. 
  if (Platform.Version >= 31) //important condition.

my js code i have settime 5 sec to scan the device and show them in ui with help of flatlist i have different requirement so i call BLUETOOTH_CONNECT and ACCESS_FINE_LOCATION at same time

 import React, { useState, useEffect } from 'react';
 import { View, Text, Button, PermissionsAndroid, FlatList } from 
'react-native';
 import { BleManager } from 'react-native-ble-plx';

  const bleManager = new BleManager();

  const BluetoothScreen = () => {
  const [scanning, setScanning] = useState(false);
 const [devices, setDevices] = useState([]);


    const requestBluetoothPermissions = async () => {
    try {
  const granted = await PermissionsAndroid.request(
    PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
    {
      title: 'Bluetooth Permission',
      message: 'This app requires access to your Fine location to 
   scan for Bluetooth devices.',
      buttonNeutral: 'Ask Me Later',
      buttonNegative: 'Cancel',
      buttonPositive: 'OK',
    },
  );
  const granted1 = await PermissionsAndroid.request(
    PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
    {
      title: 'Bluetooth Permission',
      message: 'This app requires access to your Fine location to 
   scan for Bluetooth devices.',
      buttonNeutral: 'Ask Me Later',
      buttonNegative: 'Cancel',
      buttonPositive: 'OK',
    },
  );
  const bluetoothPermission = await PermissionsAndroid.request(
    PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
  );
  console.log('bluetoothPermission',bluetoothPermission)
 

  if (bluetoothPermission === PermissionsAndroid.RESULTS.GRANTED) 
    {
    console.log('Bluetooth permission granted');
    startDeviceScan();
  } else {
    console.log('Bluetooth permission denied');
  }
  } catch (error) {
  console.error('Error requesting Bluetooth permissions:', 
 error);
 }
 };

  const startDeviceScan = async() => {
  // setScanning(true);

    bleManager.startDeviceScan( 
  [],
  {allowDuplicates: false},
  // null,null,
   (error, scannedDevice) => {
  if (error) {
    console.log('Error scanning devices:', error);
    // console.log('PermissionsAndroid', PermissionsAndroid)
    return;
  }

  if (scannedDevice) {
    const device=scannedDevice
    console.log('Found device:', device);
    setDevices(prevDevices => [...prevDevices, scannedDevice]);
    setTimeout(()=>{
      bleManager.stopDeviceScan();
    },5000)
    }
  });
  };

  const renderItem = ({ item }) => (
  <View>
  <Text>{item.name}</Text>
  
  </View>
 );
    useEffect(() => {
     requestBluetoothPermissions();

// Cleanup function
return () => {
  bleManager.stopDeviceScan();
};
 }, []);

    return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 
 'center' }}>
  <Button title={scanning ? 'Scanning...' : 'Scan Devices'} 
 onPress={startDeviceScan} disabled={scanning} />

  <FlatList
    data={devices}
    renderItem={renderItem}
    keyExtractor={(item,index) => index.toString()}
  />
  </View>
 );
};

 export default BluetoothScreen;

Upvotes: 0

Jagadeesh
Jagadeesh

Reputation: 539

I solved it by changing the targetSdkVersion ( same to compileSdkVersion, in my case 23) in android/app/build.gradle.

Edit AndroidManifest.xml located in android/src/main and add the

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

next :

import { PermissionsAndroid } from 'react-native';

and then add this method:

export async function requestLocationPermission() 
{
  try {
    const granted = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
      {
        'title': 'Example App',
        'message': 'Example App access to your location '
      }
    )
    if (granted === PermissionsAndroid.RESULTS.GRANTED) {
      console.log("You can use the location")
      alert("You can use the location");
    } else {
      console.log("location permission denied")
      alert("Location permission denied");
    }
  } catch (err) {
    console.warn(err)
  }
}

and access the method when you request the location at run-time

async componentWillMount() {
    await requestLocationPermission()
}

Upvotes: 49

Keshav Gera
Keshav Gera

Reputation: 11244

in Manifest

 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.CAMERA"/>

more details

import {PermissionsAndroid} from 'react-native';

async function 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) {
      console.log('You can use the camera');
    } else {
      console.log('Camera permission denied');
    }
  } catch (err) {
    console.warn(err);
  }
}

export default class AlertDetails extends Component{

    async componentDidMount() {
        await request_storage_runtime_permission()
    }
}

Upvotes: 4

Rajneesh Shukla
Rajneesh Shukla

Reputation: 1382

You can ask location permission using following code

try {
     const granted = await PermissionsAndroid.request(
       PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
     )
     if (granted === PermissionsAndroid.RESULTS.GRANTED) {
       alert("You can use the location")
     } else {
       alert("Location permission denied")
     }
   } catch (err) {
     console.warn(err)
   }
   alert('hi');

Upvotes: 4

Jan
Jan

Reputation: 945

This did not work for me

if (granted === PermissionsAndroid.RESULTS.GRANTED) {
}

I referred to https://facebook.github.io/react-native/docs/permissionsandroid.html#request and check() return a boolean

const granted = await PermissionsAndroid.check( PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION );

if (granted) {
  console.log( "You can use the ACCESS_FINE_LOCATION" )
} 
else {
  console.log( "ACCESS_FINE_LOCATION permission denied" )
}

Upvotes: 35

Hiren Patel
Hiren Patel

Reputation: 52790

I've noticed two things:

  1. You have to change compileSdkVersion 23 in build.gradle file
  2. You have to add your View's click listener to display to Permission dialog.

Sample code:

import React, { Component } from 'react';
import { Text, PermissionsAndroid, Alert } from 'react-native';

export default class RuntimePermissionSample extends React.Component {

    constructor(props) {
        super(props);
    }

    async requestLocationPermission() {
        const chckLocationPermission = PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION);
        if (chckLocationPermission === PermissionsAndroid.RESULTS.GRANTED) {
            alert("You've access for the location");
        } else {
            try {
                const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
                    {
                        'title': 'Cool Location App required Location permission',
                        'message': 'We required Location permission in order to get device location ' +
                            'Please grant us.'
                    }
                )
                if (granted === PermissionsAndroid.RESULTS.GRANTED) {
                    alert("You've access for the location");
                } else {
                    alert("You don't have access for the location");
                }
            } catch (err) {
                alert(err)
            }
        }
    };

    render() {
        return (
            <Text
                onPress={() => this.requestLocationPermission()}>
                Request Location Permission
            </Text>
        )
    }
}

Hope this would help you.

Upvotes: 2

egisp
egisp

Reputation: 61

You could use the react native PermissionsAndroid to request the permission: https://facebook.github.io/react-native/docs/permissionsandroid.html#request

Or, an easier option will be using a library that does it for you, such as https://github.com/yonahforst/react-native-permissions

Upvotes: 5

Related Questions