Android permissions in react native app can be integrated very easily if you need something quick for a component, a list of permissions and a nice example for react-native can be found here.
But why
1. Login using redux-saga and store token from server to local storage (There are many debates related to storing JWT to local storage, but if anyone wants another alternative a nice article can be found here.
2. Request the necessary permissions
3. Store response of prompted permission to redux for later use
To have our permissions into redux I’ve added several functions to saga which I will explain below:
const watchLogin = function*() {
while (true) {
const { username, password, navigation } = yield take(types.LOGIN_REQUESTED);
const task = yield fork(login, username, password, navigation);
const action = yield take([types.CLIENT_UNSET, types.LOGIN_ERROR]);
if (action.type === types.CLIENT_UNSET) yield cancel(task);
yield call(logout);
}
};
export default watchLogin;
const login = function*(username, password, navigation) {
let token;
try {
token = yield call(loginApi, username, password);
yield put(setClient(token));
yield put({ type: types.LOGIN_SUCCESS });
AsyncStorage.setItem('token', JSON.stringify(token));
yield put({ type: types.PERMISSIONS_REQUESTED });
yield call(setPermissions);
navigation.navigate('SignedIn');
} catch (error) {
yield put({ type: types.LOGIN_ERROR, error });
} finally {
// if canceled redirect to login
if (yield cancelled()) {
navigation.navigate('SignedOut');
}
}
return token;
};
So the first generator function watchLogin is the root for my saga file and when my action LOGIN_REQUESTED has triggered I get the username, password, and navigation. The last parameter is used for connecting my navigation to log out functionality. The next important step for this generator is the call of login
I start by taking token
from the API loginApi
As we can see login
setPermissions
is again a generator function and is looking like this:
export const setPermissions = function*() {
try {
const custom = yield call(requestPermission, [
PermissionsAndroid.PERMISSIONS.READ_CALL_LOG,
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
PermissionsAndroid.PERMISSIONS.CAMERA,
]);
yield all(
custom.map(item => {
if (Object.values(item)[0] === PermissionsAndroid.RESULTS.GRANTED) {
return put({ type: types.PERMISSIONS_SUCCESS, payload: item });
}
return put({ type: types.PERMISSIONS_REJECTED, payload: item });
})
);
} catch (err) {
return err;
}
return true;
};
I’m calling a new requestPermission
custom
const. The requestPermission
the function is looking like this:
const requestPermission = async requestedType => {
try {
const granted = await PermissionsAndroid.requestMultiple(requestedType);
const access = Object.keys(granted).map(item => {
const name = item.split('.').slice(-1)[0];
const revObj = {};
revObj[name] = granted[item];
AsyncStorage.mergeItem('permissions', JSON.stringify(revObj));
return revObj;
});
return access;
} catch (e) {
return e;
}
};
I’m requestMultiple()
custom
map
and if the value is granted
or denied
I’m updating my redux store.

Because I have stored permissions into redux, I can use them easily in any react-native component. If you don’t know how to use redux check this article.