Reputation: 1005
I am trying to read a CSV file, load its content to a spinner. I have given relevant permissions MANAGE_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE to read a file from external storage. I have placed the CSV file in a directory requested permission on runtime. Also the file.exists() function return true but still unable to read csv file. Where am I going wrong?
Here is the error log:
022-02-27 18:03:32.457 13080-13080/com.example.locationfetcher_v2 W/System.err: java.io.FileNotFoundException: /storage/emulated/0/Khidmah/input.csv: open failed: EACCES (Permission denied)
2022-02-27 18:03:32.461 13080-13080/com.example.locationfetcher_v2 W/System.err: at libcore.io.IoBridge.open(IoBridge.java:492)
2022-02-27 18:03:32.461 13080-13080/com.example.locationfetcher_v2 W/System.err: at java.io.FileInputStream.<init>(FileInputStream.java:160)
2022-02-27 18:03:32.461 13080-13080/com.example.locationfetcher_v2 W/System.err: at java.io.FileInputStream.<init>(FileInputStream.java:115)
2022-02-27 18:03:32.461 13080-13080/com.example.locationfetcher_v2 W/System.err: at java.io.FileReader.<init>(FileReader.java:58)
2022-02-27 18:03:32.461 13080-13080/com.example.locationfetcher_v2 W/System.err: at com.example.locationfetcher_v2.MainActivity.onCreate(MainActivity.java:157)
2022-02-27 18:03:32.461 13080-13080/com.example.locationfetcher_v2 W/System.err: at android.app.Activity.performCreate(Activity.java:8157)
2022-02-27 18:03:32.461 13080-13080/com.example.locationfetcher_v2 W/System.err: at android.app.Activity.performCreate(Activity.java:8129)
2022-02-27 18:03:32.461 13080-13080/com.example.locationfetcher_v2 W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1310)
2022-02-27 18:03:32.461 13080-13080/com.example.locationfetcher_v2 W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3494)
2022-02-27 18:03:32.461 13080-13080/com.example.locationfetcher_v2 W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3693)
2022-02-27 18:03:32.461 13080-13080/com.example.locationfetcher_v2 W/System.err: at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
2022-02-27 18:03:32.461 13080-13080/com.example.locationfetcher_v2 W/System.err: at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
2022-02-27 18:03:32.461 13080-13080/com.example.locationfetcher_v2 W/System.err: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
2022-02-27 18:03:32.461 13080-13080/com.example.locationfetcher_v2 W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2135)
2022-02-27 18:03:32.461 13080-13080/com.example.locationfetcher_v2 W/System.err: at android.os.Handler.dispatchMessage(Handler.java:106)
2022-02-27 18:03:32.462 13080-13080/com.example.locationfetcher_v2 W/System.err: at android.os.Looper.loop(Looper.java:236)
2022-02-27 18:03:32.462 13080-13080/com.example.locationfetcher_v2 W/System.err: at android.app.ActivityThread.main(ActivityThread.java:8059)
2022-02-27 18:03:32.462 13080-13080/com.example.locationfetcher_v2 W/System.err: at java.lang.reflect.Method.invoke(Native Method)
2022-02-27 18:03:32.462 13080-13080/com.example.locationfetcher_v2 W/System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:656)
2022-02-27 18:03:32.462 13080-13080/com.example.locationfetcher_v2 W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:967)
2022-02-27 18:03:32.462 13080-13080/com.example.locationfetcher_v2 W/System.err: Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
2022-02-27 18:03:32.462 13080-13080/com.example.locationfetcher_v2 W/System.err: at libcore.io.Linux.open(Native Method)
2022-02-27 18:03:32.462 13080-13080/com.example.locationfetcher_v2 W/System.err: at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
2022-02-27 18:03:32.462 13080-13080/com.example.locationfetcher_v2 W/System.err: at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
2022-02-27 18:03:32.462 13080-13080/com.example.locationfetcher_v2 W/System.err: at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
2022-02-27 18:03:32.462 13080-13080/com.example.locationfetcher_v2 W/System.err: at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7932)
2022-02-27 18:03:32.462 13080-13080/com.example.locationfetcher_v2 W/System.err: at libcore.io.IoBridge.open(IoBridge.java:478)
2022-02-27 18:03:32.462 13080-13080/com.example.locationfetcher_v2 W/System.err: ... 19 more
Below is my code:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Using Dexter Library
Dexter.withContext(this)
.withPermissions(
Manifest.permission.MANAGE_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CAMERA
).withListener(new MultiplePermissionsListener() {
@Override public void onPermissionsChecked(MultiplePermissionsReport report) {/* ... */}
@Override public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {/* ... */}
}).check();
MultiplePermissionsListener dialogMultiplePermissionsListener =
DialogOnAnyDeniedMultiplePermissionsListener.Builder
.withContext(this)
.withTitle("Camera, Storage and Location permission")
.withMessage("All Camera, Storage and Location permission are required for this application")
.withButtonText(android.R.string.ok)
.build();
//// Read data from CSV file
List<String> addresses = new ArrayList<String>();
Spinner address_spinner = findViewById(R.id.spinnerAddress);
// File file = new File(Environment.getExternalStorageDirectory() + "/Khidmah/", "input.csv");
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "input.csv");
show_notification(file.getPath());
show_notification(new Boolean(file.exists()).toString());
FileInputStream fis = null;
try {
if (file.exists()){
show_notification("can read - " + new Boolean(file.canRead()).toString());
CSVReader reader = new CSVReader(new FileReader(file.toURI().toString()));
show_notification("successfully read file...");
String[] nextLine;
while ((nextLine = reader.readNext()) != null) {
// nextLine[] is an array of values from the line
// System.out.println(nextLine[0] + nextLine[1] + nextLine[2]);
addresses.add(nextLine[0] + nextLine[1] + nextLine[2]);
show_notification(nextLine[0] + nextLine[1] + nextLine[2]);
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.support_simple_spinner_dropdown_item,addresses);
address_spinner.setAdapter(adapter);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (CsvValidationException e) {
e.printStackTrace();
}
}
Here is AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.locationfetcher_v2">
<!-- Always include this permission -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Include only if your app benefits from precise location access. -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.LocationFetcher_v2"
android:foregroundServiceType="location">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="preloaded_fonts"
android:resource="@array/preloaded_fonts" />
</application>
</manifest>
UPDATE
I am now using Dexter Library to grant permissions. I have added additional permission MANAGE_EXTERNAL_STORAGE and place the input.csv file in Public Directory i.e. Downloads folder. However now it's giving following error:
open failed: ENOENT (No such file or directory)
Upvotes: 2
Views: 3961
Reputation: 9282
After File.exists() use File.canRead() before you act on the file.
This csv file is not created by your app.
Hence on Android 11 you are not the owner and although your app can check if the file exists it discovers with File.canRead() that the file is not accessable.
With MANAGE_EXTERNAL_STORAGE and the right runtime code your app can obtain access.
The right code would start an intent for Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION
.
Upvotes: 0