Android: How to check if a file exists on my sdcard - java

I'm trying to check if a file exists on my sdcard with this code but I have some problems. The API version on my Android phone is 19 and the API version of the application is 19 but there are a lot of exceptions from other application which I do not want to work with like zedge for example. Please give me some hints on how to check if that file exists.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
File extStore = Environment.getExternalStorageDirectory();
File myFile = new File(extStore.getAbsolutePath() + "/test.txt");
if(myFile.exists()){
Log.d("File", "exists");
}
}
public boolean isExternalStorage() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
}
My Manifest file is like this:
<?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:theme="#style/AppTheme" >
<activity
android:name=".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>

your code just checks if file exists at sdcard/fileName.ext :
File extStore = Environment.getExternalStorageDirectory();
File myFile = new File(extStore.getAbsolutePath() + "/test.txt");
if(myFile.exists()){
Log.d("File", "exists");
}
To search entire file system (dir tree), we need a recursive function which enters a directory or compares a file with search file name:
public static boolean searchForFile(File root, File mySearchFile)
{
if(root == null || mySearchFile == null) return; //just for safety
if(root.isDirectory())
{
Boolean flag = false;
for(File file : root.listFiles()){
flag = searchForDatFiles(file, mySearchFile);
if(flag) return true;
}
}
else if(root.isFile() && root.getName().equals(mySearchFile.getName())
{
return true;
}
return false;
}
UPDATE
Just saw that you are looking for the file in root folder only. Check this link for four ways to check if file exists. Also, above code will work for sdcard only too, but not recommended because it will parse any folders it first encounter. Good for whole directory tree search.

Related

Writing to external storage?

I have written codes from the tutorials of SLIDENERD to save info in different areas as internal cache,External cache,Private information and public information with the following codes.
EditText uname,pwd;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
uname=(EditText)findViewById(R.id.editText);
pwd=(EditText)findViewById(R.id.editText3);
}
public void intCache(View view){
File fileDir=getCacheDir();
File myFile=new File(fileDir,"User_info_intCache.txt");
write(myFile);
}
public void extCache(View view){
File fileDir=getExternalCacheDir();
File myFile=new File(fileDir,"User_info_extCache.txt");
write(myFile);
}
public void pvtDir(View view){
File fileDir=getExternalFilesDir("User_Info");
File myFile=new File(fileDir,"User_info_pvtExt.txt");
write(myFile);
}
public void pubDir(View view){
File fileDir= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File myFile=new File(fileDir,"User_info_pubExt.txt");
write(myFile);
}
private void write(File myFile){
String unameS=uname.getText().toString();
String pwdS=pwd.getText().toString();
FileOutputStream fileOutputStream=null;
try {
fileOutputStream=new FileOutputStream(myFile);
try {
fileOutputStream.write(unameS.getBytes());
fileOutputStream.write(pwdS.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
finally {
try {
if (fileOutputStream != null) {
fileOutputStream.close();
}
Toast.makeText(this,"data is written to "+myFile.getAbsolutePath(),Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I can see the files user_info_extCache.txt , User_info_pvtExt.txt. I know that internal cache location ( User_info_intCache.txt ) cant be seen.But i can't find the User_info_pubExt.txt file which must be stored in public directory Downloads.I cant see the file created by following code.
File fileDir= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File myFile=new File(fileDir,"User_info_pubExt.txt");
The toast shows that the file is created by above piece of code under /storage/emulated/0/Download/User_info_pubExt.txt .
I find somewhere that if phone is connected to pc,external storage cant be accessed.So i tried both by removing the mobile from pc.The toast says that file is created.But i cant find it under that folder.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.iamka.storage">
<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:roundIcon="#mipmap/ic_launcher_round"
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=".Main2Activity"></activity>
</application>
Your toast claiming that data is written is on the wrong place. As the toast also displays when there is an exception.
Place the toast in the try block instead. Or yet better after the close() but only if you close().
And place other toasts in the catch blocks to inform the user with e.getMessage().
As for the exception: all the paths exept the last one do not need any read/write permission at all. For the latter you need read/write permission.
But requesting them in manifest is not enough for Android 6+ as then you have to add some code to ask the user to confirm the requested permissions.
Google for runtime permissions.

Requesting Runtime Permissions Causes Crash

The main reason I'm posting here is that I'm currently stuck without a computer that can run an emulator, I've been having to send the APK to my phone to test it. Even if my phone's connected to my computer, or I have a third party emulator running, it wont work. Due to this...I have no error logs.
The app is a simple password manager, and all the other functions thus far work. I was trying to add an export function, I can't get either to actually write anything. I've checked other questions and various sources online, but I cannot seem to figure out what could be causing it. When the method is called, it simply doesn't do anything as far as I can tell. I apologize if I'm missing something, or if there was indeed another question with the same issue. I couldn't find anything missing.
Here is the method I'm using;
EDIT: The code has been updated to reflect a better method of requesting runtime permissions, which was suggested here. This ultimately is what fixed the application.
//Method017: Exports the account info to a .txt file.
public void exportData() throws IOException {
//Opens dialog to request permission.
ActivityCompat.requestPermissions(Main.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}
//Method to handle result of permission request.
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//Attempt to write a file to the Download folder.
String content = "hello world";
File file;
FileOutputStream outputStream;
try {
file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "MyCache");
outputStream = new FileOutputStream(file);
outputStream.write(content.getBytes());
outputStream.close();
//According to an online source, this is necessary to make the file viewable on the device.
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(file));
sendBroadcast(intent);
} catch (IOException e) {
e.printStackTrace();
}
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(Main.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
And my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.brand.psync">
<application
android:allowBackup="true"
android:icon="#drawable/psynclogo"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme"
android:screenOrientation="portrait">
<activity android:name=".Main">
<intent-filter>
<action
android:name="android.intent.action.MAIN"
android:screenOrientation="portrait" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<category
android:name="android.intent.category.LAUNCHER"
android:screenOrientation="portrait" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>
Sorry about the lack of error log...but if I had that, I likely wouldn't need to post here.
I have try your code and it working.
public class SaveFileSampleActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView lblBackground = new TextView(this);
lblBackground.setBackgroundColor(Color.WHITE);
setContentView(lblBackground);
ActivityCompat.requestPermissions(SaveFileSampleActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 1: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//Attempt to write a file to the Download folder.
String content = "hello world";
File file;
FileOutputStream outputStream;
try {
file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "MyCache");
outputStream = new FileOutputStream(file);
outputStream.write(content.getBytes());
outputStream.close();
//According to an online source, this is necessary to make the file viewable on the device.
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(file));
sendBroadcast(intent);
} catch (IOException e) {
e.printStackTrace();
}
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(SaveFileSampleActivity.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
}
And mainifest
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".SaveFileSampleActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
It's work and result:
You can review your code. I hope it can help you!

Need help writing file to external storage

I've been searching the internet for several hours now in an attempt to find a file writing function that actually works for me. So far I have this in my MainActivity.java:
public void writeToFile(String data, Context ctx) {
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
File tempFile = new File(path, "houseDataFile.txt");
if(!tempFile.exists()){
tempFile.mkdirs();
}
try
{
FileOutputStream fOut = new FileOutputStream(tempFile);
fOut.write(data.getBytes());
fOut.close();
Toast.makeText(ctx, "Saved", Toast.LENGTH_SHORT).show();
}catch (Exception e)
{
Log.w(TAG, "FileOutputStream exception: - " + e.toString());
}
}
My android manifest contains both permissions:
<?xml version="1.0" encoding="utf-8"?>
<manifest package="my.package.application"xmlns:android="http://schemas.android.com/apk/res/android">
<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">
</activity>
<activity android:name=".Menu_activity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
Though rather frustratingly when I run the app and call writeToFile() it gives me an error saying:
W/MainActivity: FileOutputStream exception: - java.io.FileNotFoundException: /storage/emulated/0/Documents/houseDataFile.txt: open failed: ENOENT (No such file or directory)
Any help would be greatly appreciated, thank you in advance.
I'm assuming that you are failing to get the file path because you don't asking runtime-permission while executing method. Here you can take a look at the below code.
First, check if your device's OS version is above Lollipop or not. If above then show permission pop-up dialog.
final int MyVersion = Build.VERSION.SDK_INT;
if (MyVersion > Build.VERSION_CODES.LOLLIPOP_MR1)
{
if (!checkIfAlreadyhavePermission())
{
ActivityCompat.requestPermissions(ProfileActivity.this, new String[] {android.Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
}
else
{
writeToFile(data, ctx);
}
}
else
{
writeToFile(data, ctx)
}
private boolean checkIfAlreadyhavePermission() {
int result = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
return result == PackageManager.PERMISSION_GRANTED;
}
Then define "Allow" and "Deny" button functionalities in OnRequestPerMissionResult().
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
writeToFile( data, ctx);
} else {
Toast.makeText(YourActivity.this, "Please provide permission", Toast.LENGTH_LONG).show();
}
break;
}
}
Please let me know if this solves the issue.

Why listOfFiles is null?

Android says, that listOfFiles if null, so what have i done wrong?
I've tried to change getPath to getAboletePath, but it is just the same.
And, i've tried to access /storage/ (whereas SD_PATH is /storage/emulated/0) and i've got a list of 2 folders: emulated and self, both of wich are unaccessible.
public class MainActivity extends AppCompatActivity {
private static final String SD_PATH = Environment.getExternalStorageDirectory().getPath();
...
File home = new File(SD_PATH);
File[] listOfFiles = home.listFiles();
if(listOfFiles != null && listOfFiles.length > 0){
for (File file : home.listFiles()){
songs.add(file.getName());
}
}
Here is my AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.unimusic">
<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>
</application>
</manifest>
This same thing has burned me in the past.
To quote the docs
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app.
(see here)
Reading from the file system is one of the permissions that must now be requested at run time in order to use. This is only an issue if you target SDK 23 or later. So how to fix:
The docs show an example (see here for the original) that I have modified for your use case (I have not run this code, but it should be a good starting point). You probably want to request permissions in the onCreate() for the Activity that is going to need the permission (in your case the MainActivity).
// Ask for the read external storage permission
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
{
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_EXTERNAL_STORAGE))
{
// Provide an additional rationale to the user if the permission was not granted
// and the user would benefit from additional context for the use of the permission.
// Display a SnackBar with a button to request the missing permission.
Snackbar.make(layout,
"External storage is needed in order to {YOUR EXPLANATION HERE}",
Snackbar.LENGTH_INDEFINITE).setAction("OK", new View.OnClickListener()
{
#Override
public void onClick(View view)
{
// Request the permission
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
}
}).show();
}
else
{
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
}
}

How to open a PDF file from in-app browser?

I have a basic File Browser inside my app and I want it to be able to open PDF files, but for some reason, even though I can tap on the PDF files and they open for a second, they go away and my phone gives a Toast message with an error, and this Toast I haven't programmed anywhere in my code. This is weird because the same PDF file opens from my other activities without any issues. (See the OpenPDF() Method which works from my PDFManager class) I researched a lot about how to fix this but couldn't find a clear answer. Thanks for helping!
The toast error: Cannot display PDF (filename.pdf cannot be opened)
OnListItemClick function from AndroidFileBrowser:
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
String filename = (String) getListAdapter().getItem(position);
if (path.endsWith(File.separator)) {
filename = path + filename;
} else {
filename = path + File.separator + filename;
}
pdf = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath() + "/PATH/" + filename);
Uri path = Uri.fromFile(pdf);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(path, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
}
}
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.faraz.pdfreader"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
>
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".SimpleScannerActivity"
android:label="#string/simple_scanner_activity"
android:theme="#style/AppOverlayTheme">
</activity>
<activity android:name=".PDFManager"/>
<activity android:name=".AndroidFileBrowser"/>
<!--android:screenOrientation="portrait"-->
</application>
</manifest>
OpenPDF() method from my PDFManager class
public void openPDF() {
File pdf = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath() + "/PATH/" + pdfname + ".pdf");
if (pdf.exists()) {
Uri path = Uri.fromFile(pdf);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(path, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
Toast.makeText(PDFManager.this,
"No application available to view PDF!",
Toast.LENGTH_SHORT).show();
/* Intent intent = new Intent(Intent.ACTION_VIEW)
.setData(Uri.parse("http://docs.google.com/gview?embedded=true&url=" + url));
startActivity(intent);
}
*/
}
}
}
}
In your OnItemClick():
if (path.endsWith(File.separator))
{
filename = path + filename;
}
else
{
filename = path + File.separator + filename;
}
pdf = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath() + "/PATH/" + filename);
Uri path = Uri.fromFile(pdf);
You use "path" before you initialize it, so depending on your intentions either change the name of one or the other, or declare it before your if-statement not after.

Categories

Resources