Flutter Error: Unhandled Exception: FileSystemException: Cannot open file (OS Error: Permission denied, errno = 13) - flutter-dependencies

I'm trying to read and write a json file in device emulator Download folder but i get the error above (Flutter version 3.3.6).
After many attempts and many changes to my android/app/build.gradle I succeded in reading the file (basically i found that it works only if i manually put targetSdkVersion 29) but I still get the permission denied error when i try to write it.
I'm using the permission handler package and I when I run the app in the emulator I'm asked for the storage permission and I grant it.
Here's what my AndroidManifest.xml first lines looks like:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.flutter_application_1">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:label="flutter_application_1"
android:name="${applicationName}"
android:icon="#mipmap/ic_launcher"
android:requestLegacyExternalStorage="true">
Here's a bit of my android/app/build.gradle :
`android {
//compileSdkVersion flutter.compileSdkVersion
compileSdkVersion 33
ndkVersion flutter.ndkVersion
defaultConfig {
applicationId "com.example.flutter_application_1"
//minSdkVersion flutter.minSdkVersion
//targetSdkVersion flutter.targetSdkVersion
minSdkVersion 21
targetSdkVersion 29
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}`
I added the following dependency in pubspec.yaml: permission_handler: ^10.2.0
Here's the part of the code that handles the permissions and the reading/writing methods:
import 'dart:convert';
import 'dart:io';
import 'package:permission_handler/permission_hndler.dart';
Future<bool> requestPermission(Permission permission) async {
if (await permission.isGranted) {
return true;
} else {
var result = await permission.request();
if (result == PermissionStatus.granted) {
return true;
}
}
return false;
}
class FileManager {
Future<String> get directoryPath async {
Directory directory = Directory('/storage/emulated/0/Download');
return directory.path;
}
Future<File> get jsonFile async {
final path = await directoryPath;
return File('$path/big_book.json');
}
void writeJsonFile(List itemsRubrica) async {
if (await requestPermission(Permission.storage)) {
File file = await jsonFile;
await file.writeAsString(jsonEncode(itemsRubrica));
}
}
Future<String> readJsonFile() async {
if (await requestPermission(Permission.storage)) {
File file = await jsonFile;
String fileContent = await file.readAsString();
return fileContent;
} else {
return 'no data';
}
}
}
I prefer not to put here the rest of my code because it's very long and I think it's not related to this error.
What can I do?
Thanks

Related

Experiencing error <asynchronous suspension> in project

Future<void> shareFile() async {
await getImage();
Directory? directory = await getExternalStorageDirectory();
print('${directory!.path} / ${_image!.path}');
await WhatsappShare.shareFile(
phone: _phone,
filePath: ["${_image!.path}"],
);
}
Future getImage() async {
try {
final ImagePicker _picker = ImagePicker();
XFile? _pickedFile =
(await _picker.pickImage(source: ImageSource.gallery));
if (_pickedFile != null) {
// getting a directory path for saving
final directory = await getExternalStorageDirectory();
// copy the file to a new path
await _pickedFile.saveTo('${directory!.path}/image1.png');
_image = File('${directory.path}/image1.png');
}
} catch (er) {
print(er);
}
}
When using the Whatsapp_share2 dependencies experiencing the error of . I'm beginner of flutter. Please help to solve the error in above code.
Can anyone help me to resolve this issue

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

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);
}

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 Firebase Storage - getting error when trying to save image with .putFile()

I am trying to save a local image from the phone to firebase storage but am getting the following error.
Permission Denial: reading com.google.android.apps.photos.contentprovider/........uid=XXXXX requires the provider be exported, or grantUriPermission()
See below code.
await imageRef.putFile(localUri, {contentType: 'image/jpg'}); is where the issue is occuring
const uploadImageAndGetUrl = async (localUri, firebasePath) => {
try {
const imageRef = storage().ref(firebasePath);
await imageRef.putFile(localUri, {contentType: 'image/jpg'});
const url = await imageRef.getDownloadURL();
return url;
} catch (err) {
Alert.alert('Profile.js.....Error getting image url from FB', err);
}
};
Manifest is as follows:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name = "android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Solution 1:
import RNFetchBlob from 'rn-fetch-blob'
async function getPathForFirebaseStorage (uri) {
if (Platform.OS==="ios") return uri
const stat = await RNFetchBlob.fs.stat(uri)
return stat.path
}
const fileUri = await getPathForFirebaseStorage(file.uri)
const uploadTask = ref.putFile(fileUri)
Solution 2:
import RNFS from 'react-native-fs'
const data = await RNFS.readFile(uri, 'base64')
await ref.putString(data, 'base64')
Note: if above solution do not work then make sure READ_EXTERNAL_STORAGE permissions from the user using the react-native-permissions library
i am not sure if its the source path issue or its something about the permission. Have you added the required permissions to the Manifest.xml file.

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();
}