Reading files from SD card issue: no file is visible - android

I have a problem with my app. I'm trying to read files from my SD card, but I cannot find any file. Files are added to main folder in my sdcard. I tried also create a new folder and read files from folder, but I have the same problem. Other files from SD card (not added by me for app purposes) are also not visible. I'm testing my app on real device Samsung Galaxy A3. Do you have any idea, where is a problem, or what I do wrong? Below is my code:
Manifest file:
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".RecipeActivity"></activity>
</application>
Activity class:
File dir = Environment.getExternalStorageDirectory();
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "receip.txt");
if(file.exists()) // check if file exist
{
//Read text from file
StringBuilder text = new StringBuilder();
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null) {
text.append(line);
text.append("\n");
}
}
catch (IOException e) {
//You'll need to add proper error handling here
}
//Set the text
Log.d("File text:", text.toString() );
Toast.makeText(getApplicationContext(),"File Found", Toast.LENGTH_SHORT);
}
else
{
Log.d("Romek file:", "File not found" );
Toast.makeText(getApplicationContext(),"File not Found", Toast.LENGTH_SHORT);
}
I added also below methods to checked whether my SD card is writable and readable. All methods return true.
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
Log.d("Romek", "External Storage is writable");
return true;
}
Log.d("Romek", "External Storage is not writable");
return false;
}
/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
Log.d("Romek", "External Storage is readable");
return true;
}
Log.d("Romek", "External Storage is not readable");
return false;
}
I used runtime permission and I can read files, but I have another problem. How can I get a correct path to my files in external SDCARD. When I using a Environment.getExternalStorageDirectory().getAbsolutePath(), then I recived a path to external card in my phone, not SDCARD.

If your phone has android 6.0 or newer version, you have to ask run time permissions. More info you can get from https://developer.android.com/training/permissions/requesting.html

Related

Access to the path ... is denied - Xamarin Android

I am trying to write an image to my android file system, however when trying to write the bytes, I get the above error.
I am running Visual Studio 2019 (as administrator) and targeting API Level 29
AndroidManifest.xml
My external storage permissions are present in my manifest file:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
And as per another suggestion I have added android:requestLegacyExternalStorage="true" in my application tag:
<application android:label="App Name" android:icon="#mipmap/launcher_foreground" android:extractNativeLibs="true" android:requestLegacyExternalStorage="true">
MainActivity.cs
Here I am requesting the permissions when the app starts and pressing allow on both prompts:
int requestPermissions = 0;
string cameraPermission = Android.Manifest.Permission.Camera;
string filePermission = Android.Manifest.Permission.WriteExternalStorage;
if (!(ContextCompat.CheckSelfPermission(this, cameraPermission) == (int)Permission.Granted) || !(ContextCompat.CheckSelfPermission(this, filePermission) == (int)Permission.Granted))
{
ActivityCompat.RequestPermissions(this, new String[] { cameraPermission, filePermission
}, requestPermissions);
}
SaveMedia.cs
I get the error on File.WriteAllBytes:
public string SavePickedPhoto(Stream file, string fileName)
{
var bytes = GetBytesFromStream(file);
string path = Path.Combine(Android.App.Application.Context.GetExternalFilesDir("").AbsolutePath + "PhotoDirectoryForApp";
if (!Directory.Exists(path))
{
try
{
Directory.CreateDirectory(path);
}
catch (Exception e)
{
}
}
Path.Combine(path, fileName);
try
{
File.WriteAllBytes(path, bytes);
}
catch (Exception ex)
{
}
return path;
}
I am at a bit of a loss on what to try next as to me it seems that I should have the necessary permissions to write a file to a folder on the device. I have also tried various locations to save to and methods of saving with the same result.
Thanks in advance
You are trying to write to a directory as you are throwing away the return value from Path.Combine :
Path.Combine(path, fileName);
Try:
~~~
path = Path.Combine(path, fileName);
~~~

No such file or directory in Android 10 (api 29)

I am working on a photo editor app in which after editing my picture I save it into my local storage. It is working fine till android 9 but not on android 10. It shows exception of "No such file or directory found" in Android 10. After some research I found that getExternalFilesDir() is deprecated in android Q+. But I cannot find any proper way to do it in android 10. So please if anyone can provide a tutorial it would be really helpful.
I've added and granted uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> in case of it was the issue, and it didn't solve anything.
This is my try (Used ParcelFileDescriptor):
private void fileAccessForAndroidQ(Uri fileUri){
try {
ParcelFileDescriptor parcelFileDescriptor = this.getContentResolver().openFileDescriptor(fileUri, "r", null);
InputStream inputStream = new FileInputStream(parcelFileDescriptor.getFileDescriptor());
Cursor returnCursor =
getContentResolver().query(fileUri, null, null, null, null);
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
returnCursor.moveToFirst();
fileName = returnCursor.getString(nameIndex);
file = new File(this.getFilesDir(), fileName);
OutputStream outputStream = new FileOutputStream(file);
IOUtils.copyStream(inputStream, outputStream);
}catch (Exception e){
Toast.makeText(this, ""+e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
Any kind of help would be appreciated.
If you target Android 10 (API level 29) or higher, set the value of requestLegacyExternalStorage to true in your app's manifest file:
Documentation
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.appname"
android:installLocation="auto">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:requestLegacyExternalStorage="true"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme.NoActionBar">
<activity android:name=".activities.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Here is the best I could find:
https://developer.android.com/training/data-storage/app-specific#external
Basically, you now use app-specific directories for your files. For example:
#Nullable
File getAppSpecificAlbumStorageDir(Context context, String albumName) {
// Get the pictures directory that's inside the app-specific directory on
// external storage.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (file == null || !file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
I found this working for me. i am trying to list all file on ListView
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
} else {
File s = Environment.getExternalStorageDirectory();
Log.d("Path ",Arrays.toString(s.listFiles()));
File[] s1 = new File[s.listFiles().length];
for(int i=0;i<s.listFiles().length;i++){
s1[i]= new File(s.listFiles()[i].toString().replace("/storage/emulated/0/", ""));
}
ArrayAdapter<File> adapter = new ArrayAdapter<File>(this,R.layout.support_simple_spinner_dropdown_item,s1);
l1.setAdapter(adapter);
}

Directory does and doesn't exist

I am trying to write a file to the SD card on my android phone, but it seems to be having issues with the directory. It exists but doesnt exist. By this I mean when I go to the file browser on the android phone, and look for the GPStracker folder I cannot find it. Yet in the program it seems to acknowledge that this directory exists when it checks the dir.exists() if condition below. Then when it gets to the canWrite() function it always returns false. I have no idea what is wrong at this point, anyone have any debugging ideas? Thanks.
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// We can read and write the media
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// We can only read the media
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
} else {
// Something else is wrong. It may be one of many other states, but all we need
// to know is we can neither read nor write
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
^ These both return true now, got that issue fixed.
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tinywebteam.gpstracker"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.tinywebteam.gpstracker.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Code:
try {
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File(sdCard + "/GPStracker/data");
if (!dir.exists()) {
if (!dir.mkdirs())
throw new FileNotFoundException("Couldn't make directory.");
if (!dir.isDirectory())
throw new FileNotFoundException("Couldn't verify directory.");
}
File fileOut = new File(dir, "GPSTracker_" + ts + ".csv");
if (fileOut.canWrite()) {
FileOutputStream out = new FileOutputStream(fileOut);
out.write(fileStr.getBytes());
out.close();
System.out.println("File written successfully");
} else {
System.out.println("Could not write to file");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

Cannot write to SD Card on Android phone

EDIT2: For people stumbling across this question from Google. The canWrite() function is kinda buggy and doesn't seem to work properly. I would recommend not using it. Just catch and exceptions instead. Also make sure your phone is not in USB Storage mode so that you can write to the SD card. Lastly make sure the settings in Android device don't have write protection or anything of the sort on.
I seem to be having issues trying to write to my SD card on my Android phone. It doesn't matter if I am in debug mode with Eclipse, or running the phone on it's own. I cannot write to the SD Card. Yes the permissions are configured, as shown below. When using the code snippet provided on the Android site I am being given false for both of the booleans after it finishes the segment. I have absolutely no idea why the storage is not available or writable. I eject the SD card and the phone from my Mac to make sure they are not using it and that the phone can mount, but like I said I get the same issue when not using Eclipse at all.
EDIT: Using a real Android phone running 4.04 according to the about information.
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// We can read and write the media
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// We can only read the media
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
} else {
// Something else is wrong. It may be one of many other states, but all we need
// to know is we can neither read nor write
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tinywebteam.gpstracker"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.tinywebteam.gpstracker.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
It fails when trying to execute mkdirs() below and throws the assigned exception:
try {
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File(sdCard.getAbsolutePath() + "/GPStracker/data/");
if (!dir.exists()) {
if (!dir.mkdirs())
throw new FileNotFoundException("Couldn't make directory.");
}
File fileOut = new File(dir, "GPSTracker_" + ts + ".csv");
if (fileOut.canWrite()) {
FileOutputStream out = new FileOutputStream(fileOut);
out.write(fileStr.getBytes());
out.close();
System.out.println("File written successfully");
} else {
System.out.println("Could not write to file");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
According to the documentation, the state you're describing means that the external media storage isn't accessible to you:
public static final String MEDIA_SHARED
Added in API level 1 getExternalStorageState() returns MEDIA_SHARED if
the media is present not mounted, and shared via USB mass storage.
Constant Value: "shared"
You need to go to your USB Mass Storage options and turn off USB storage.
here is the deal, you are using
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File(sdCard.getAbsolutePath() + "/GPStracker/data/");
instead use -
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File(sdcard + "/GPStracker/data");
here we didn't use second '/' because mkdirs() misinterpret it as creating recursive directories.
you will not get this exception. And check if you pass your filename with a '/' appended before or it works this way as well.
I have a samsung galaxy s3 (running android 4.1.2) and my internal memory is named sdCard0 and My external sd card named as extSdCard.
So Environment.getExternalStorageDirectory() returned the path of sdCard0 which my internal phone memory
In such cases you can use the following to get the actual path.
String externalpath = new String();
String internalpath = new String();
public void getExternalMounts() {
Runtime runtime = Runtime.getRuntime();
try
{
Process proc = runtime.exec("mount");
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
String line;
BufferedReader br = new BufferedReader(isr);
while ((line = br.readLine()) != null) {
if (line.contains("secure")) continue;
if (line.contains("asec")) continue;
if (line.contains("fat")) {//external card
String columns[] = line.split(" ");
if (columns != null && columns.length > 1) {
externalpath = externalpath.concat("*" + columns[1] + "\n");
}
}
else if (line.contains("fuse")) {//internal storage
String columns[] = line.split(" ");
if (columns != null && columns.length > 1) {
internalpath = internalpath.concat(columns[1] + "\n");
}
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
System.out.println("Path of sd card external............"+externalpath);
System.out.println("Path of internal memory............"+internalpath);
}
Once you get the actual path you can write files to sdcard.

Trouble Creating a Directory on the SD Card

I am trying to have my app create a directory on the root of the SD Card, if that directory does not already exist. When I run the app, the "Creating Home Directory..." toast notification displays, but the directory is not created... What am i doing wrong?? (P.S. permissions are set for writing to external storage)
public class Main extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Check SD Card for Read/Write
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// We can read and write the media
mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// We can only read the media
mExternalStorageWriteable = false;
} else {
// Something else is wrong. It may be one of many other states, but all we need
// to know is we can neither read nor write
mExternalStorageWriteable = false;
}
if (mExternalStorageWriteable == false) {
//Toast Notification that SD Card is not Accessible
Context context = getApplicationContext();
CharSequence text = "SD Card is NOT Accessable, Please Remount and Try Again";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
} else {
//Check If Home Dir Exists
boolean exists = (new File("/AndGuard/")).exists();
if (exists) {
Context context = getApplicationContext();
CharSequence text = "Accessing Data Files...";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
} else {
Context context = getApplicationContext();
CharSequence text = "Creating Home Directory...";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
// Create a directory; all non-existent ancestor directories are
// automatically created
// Create a directory; all non-existent ancestor directories are
// automatically created
File root = Environment.getExternalStorageDirectory();
boolean success = (new File(root,"directoryName")).mkdirs();
if (!success) {
// Directory creation failed
}
}
}
Here is my Manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="soapbox.sym3try.andguard"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".Main"
android:label="#string/app_name">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="4" />
</manifest>
I tried this as well, it didn't work, but it might be a step in the right direction as it creates the directory and populates it with a file from res/raw all in one step:
public boolean saveas(int ressound){
byte[] buffer=null;
InputStream fIn = getBaseContext().getResources().openRawResource(ressound);
int size=0;
try {
size = fIn.available();
buffer = new byte[size];
fIn.read(buffer);
fIn.close();
} catch (IOException e) {
// TODO Auto-generated catch block
return false;
}
String path="/sdcard/AndGuard/List1";
String filename="hosts";
boolean exists = (new File(path)).exists();
if (!exists){new File(path).mkdirs();}
FileOutputStream save;
try {
save = new FileOutputStream(path+filename);
save.write(buffer);
save.flush();
save.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
return false;
}
return exists;
}
The uses-permission should be in the manifest xml tag I think, check out http://developer.android.com/guide/topics/manifest/uses-permission-element.html
This may not do anything, but right after WRITE_EXTERNAL_STORAGE" in your manifest add this permission
android:name="android.permission.READ_PHONE_STATE"
The uses-permission should be in manifest tag, not in activity.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="soapbox.sym3try.andguard"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-sdk android:minSdkVersion="4" />
<application
android:icon="#drawable/icon"
android:label="#string/app_name">
<activity
android:name=".Main"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
You can't create any files in the root directory, so I assume it must me
File root = Environment.getExternalStorageDirectory();
boolean exists = (new File(root, "AndGuard")).exists();
Hardcoding /sdcard/ is wrong.
String path="/sdcard/AndGuard/List1"
right
File path = new File(root, "AndGuard/List1");
And
save = new FileOutputStream(path+filename);
will give you
"/sdcard/AndGuard/List1hosts"
So it must be
save = new FileOutputStream(new File(path, filename));
//create file dir
File wallpaperDirectory = new File("/sdcard/example");
// have the object build the directory structure, if needed.
wallpaperDirectory.mkdirs();
This works for me. You will need to set
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">

Categories

Resources