Reading Folder Structures on Android SD Card - android

I am new to Xamarin Android, but have some experience with C# and WinForms. I have a modern Android device using Android 9. I can use the built-in File Manager to see my SD card. I can also use that app to create a folder on my SD card (for example "Test Folder"). What I have not been able to do is access that folder using my C# Xamarin Android code. Should I be able to, or is this frowned upon? Is there a generic solution that will work on other devices that also have an SD card?
The Android.OS.Environment.GetExternalStoragePublicDirectory method does not seem to recognize the presence of the removable, external storage. I have also tried
new Intent(Intent.ActionOpenDocumentTree);
This allows me to "see" the new folder, but I can't seem to do anything with the URI that I get back.

To create Folder in External Storage (if External Storage is available otherwise it creates in internal storage)
public void createMainFolder (){
String myfolderLoc=Environment.getExternalStorageDirectory()+"/"+yourFolderName;
File f=new File(myfolderLoc);
if(!f.exists()) {
if (!f.mkdir()) {
//folder can't be created
} else {
//folder has been created
}
}
}
And to get the path of the folder :
public String getAppmainFolderName(){
return Environment.getExternalStorageDirectory()+"/"+yourFolderName;
}
Don't forget to add Storage Permission in your manifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
and check Storage Permission is granted or not before accessing your External Storage (required for android 6.0 and above).
Request App Permission Android Doc.
Hope this will help you. 🙂

Related

Kotlin File(path).walkTopDown() does not find files

I'm trying to read a given directory recursively and find all folders and files. The directory and subdirectory is found, but no files.
The storage structure on my virtual device:
The code used to "walk through the given directory"
import android.util.Log
import java.io.File
// path = "/storage/1B10-1D17/ReadTest/"
class FileHelper {
fun walkTest(path: String){
File(path).walkTopDown().forEach {
// println(it)
Log.e("walkTest extension", it.extension)
if(it.isDirectory){
Log.e("walkTest", "Directory: ${it.name}")
}else{
Log.e("walkTest", "File: ${it.name}")
}
}
}
}
This will output the following:
E/walkTest extension:
E/walkTest: Directory: ReadTest
E/walkTest extension:
E/walkTest: Directory: SubFolder
In my android manifest file I have the following line and the permission is granted:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
What is the flaw in my code, how can I find the three pdf files stored in these directories?
Update 1/2
As can be seen in the screenshot below, the media access is granted:
If I run the following command (as suggested by dan1st), I get the following output, which shows that pdf file in place:
> adb shell ls /storage/1B10-1D17/ReadTest/
File_1.pdf
SubFolder
You generally have no access to arbitrary files on removable storage. This is not changed by READ_EXTERNAL_STORAGE.
Your proposed solution is to use MANAGE_EXTERNAL_STORAGE. Technically, this works, and it is a fine solution for personal-use apps. If your intention is to distribute this app, you will need to file paperwork with Google (and perhaps other app stores) justifying your use of this permission. Stores that disagree with your justification may elect to not distribute your app.
Alternatively, you can use the Storage Access Framework. Use ACTION_OPEN_DOCUMENT_TREE / ActivityResultContracts.OpenDocumentTree and let the user decide where on the user's device (or in the user's cloud storage) the user wants your app to access the user's content. You can then use DocumentFile to walk the document tree to find sub-trees and documents.

Write logs on SD card

I want to write logs to the SD card like this
String filePath = "/storage/FC30-3DA9" + "/logs" + "/logcat.txt";
in Manifest
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
and i request them from the user.
I can read the file from the card, but I can't write it. When I try to write a file, I get permission denied.
The path Environment.getExternalStorageDirectory() leads to the internal memory of the phone. I have root.
Yes. Since Android Kitkat removable micro sd cards are read only.
Only at Android 11 devices they are writable again.
But there is one exception: your app specific directory on the card.
Look at the second item returned by getExternalFilesDirs().
If you use Storage Access Framework instead your app can write everywhere.

Accessing external storage in Android API 29

I'm trying to achieve some clean up tools. More and more manufacturers have forbidden rooting devices due to some "security reason", it's forbidden NOT to request for unlock.
After API 28, This code will make error:
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
}, 1); // Request permission or not, Will got same result
File rootFolder = Environment.getExternalStorageDirectory(); // That is working fine
rootFolder.listFiles(); // That will return null
Sure, I can use this:
android:requestLegacyExternalStorage="true"
But I belive that will be killed in future.
So, Any elegant way to manage SDCard?
On Android 10 Environment.getExternalStorageDirectory() and Environment.getExternalStoragePublicDirectory() will return storage paths but paths are not readable or writable.
For Android 10 you can continue to use paths provided by Environment.getExternalStorageDirectory() and Environment.getExternalStoragePublicDirectory() if you add android:requestLegacyExternalStorage="true" to application tag in manifest file. At runtime your app can call Environment.isExternalStorageLegacy() to check if the request has been done.
Another (not known) possibility (only for Android 10) is to add <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> to manifest file.
The user has to go to the advanced settings of the app and enable from Advanced settings Install unknown apps | Allow from this source.
The nice thing with this is that the user can switch the access rights. You can make it easier for the user if you implement an intent for
Settings.ACTION_APPLICATION_DETAILS_SETTINGS where he can change the settings.
A funny thing is that Environment.isExternalStorageLegacy() returns true then too.
Compiling for Android 11 both options do not work on an Android 11 device. (But they continue to work for Android 10 devices). The paths of Environment.getExternalStorageDirectory() and Environment.getExternalStoragePublicDirectory() are usable again in read mode and very often in write mode too. And this is great as one can simply list the contents of directories like Download or Pictures or DCIM/Camera again using the File class.
But adding <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> to manifest file and implementing an intent for
Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION will give your app read/write access for all files even on removable micro sd card.
(Finally you can remove the google ban not being able to read/write your own micro sd card on your own Android device using your own app).
Environment.isExternalStorageManager() can be used to check if the permission is on/off.
As long as you do not try to upload your app to the play store you are fine.
use android:requestLegacyExternalStorage="true" in your Manifest below <application

Xamarin.Forms Android cannot access USB OTG folder

I'm on an Android 5.0 device where a usb mass storage is mounted at "/storage/usbotg" via USB OTG cable.
Unfortunately from my app I only have read access to that folder. Please note that I set the write external storage permission as I'm able to write to device storage.
I post the following code as reference:
string Root = "/storage/usbotg";
string[] Dirs = Directory.GetDirectories(Root);
string NewFolder = Path.Combine(Root, "NewFolder");
Directory.CreateDirectory(NewFolder);
This gives me an exception on the last line (but I'm able to list subdirectories in Dirs)
Exception:
System.UnauthorizedAccessException
Exception Message:
Access to the path "/storage/usbotg/NewFolder" is denied.
If I use:
string Root = "/storage/emulated/0";
everything is working fine and the "NewFolder" is created.
What I'm missing? How can I write to that folder?
I'm using Xamarin.Forms 2.5.0
Thanks for your help
Accessing data outside your application's private storage using the file system is more restricted with each Android version.
The recommended options are :
Use getExternalFilesDirs(), getExternalCacheDirs, ... : this gives you one or more directories specific to you application (usually directories named after the package name). This does not work for removable media, unless they're adopted.
Use the Storage Access Framework : ask the user (using ACTION_OPEN_DOCUMENT_TREE) to choose the storage root. You can then manage the content of the picked directory through the SAF API. You can persist the permission, so you only need to ask the user once. It seems that it is what ES File explore does to get write permission.
A (much) more detailed explanation by Mark Murphy.

how to get secondary storage uri or root directory of secondary storage of all devices in android

the secondary storage access is the main problem in android for all device but why?if anyone can solve this then it will be very helpful to me.who can know about access of secondary storage means external sd card of any device in marshmallow.please check below code link and help me.Its big problem still don't get solution.
https://www.dropbox.com/s/sojccopr46gbqgg/CheckExternalSDCardDemo.tar.gz?dl=1
before you access the external storage or root storage you need to define user permission in manifest and as well as in java file of your code where you want to access it before this ask the run time permission for external storage
for adding run time permission go threw https://developer.android.com/training/permissions/requesting.html
or any run time tutorial
First, check whether External Storage is Available or Not using below code:
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
If it returns true use below code to get access to External Storage:
getExternalStoragePublicDirectory()
For more information visit: Official Documentation

Categories

Resources