Well I am debugging my android application on phone. There is a File Explorer in Eclipse, where I can navigate and delete some files if I want to. My application's database file is under "/data" (by default) but using the Eclipse's File Explorer I don't have access to this folder.
So my question is 'Why I don't have access'?
and
Is there a way for accessing this folder?
Thank you!
...
The way I am deleting my database file is:
context.deleteDatabase(DATABASE_NAME);
Try this:
private void writeToSD() throws IOException {
File f=new File("/data/data/yourPackageName/databases/DatabaseName");
FileInputStream fis=null;
FileOutputStream fos=null;
try{
fis=new FileInputStream(f);
fos=new FileOutputStream("/mnt/sdcard/dump.db");
while(true){
int i=fis.read();
if(i!=-1){
fos.write(i);
}
else{
break;
}
}
fos.flush();
}
catch(Exception e){
e.printStackTrace();
}
finally{
try{
fos.close();
fis.close();
}
catch(IOException ioe){
System.out.println(ioe);
}
}
}
Check for the exception when you call this file from within a try catch block, that will get you started. Cheers!!
So my question is 'Why I don't have access'?
You probably do not have read and write permissions to the folder
Is there a way for accessing this folder?
Yes. You need to have root access and remount the folder with read write permissions.
You need root access. Typically your device has to be rooted before you can do that.
Find out more about rooting:
http://www.androidcentral.com/root
Because your phone isn't rooted so Eclipse/DDMS doesn't have permission to view that folder. Which is quite correct from a security standpoint, otherwise you could edit/delete/compromise any app's data, not just your own.
Related
I have written a method which creates a file and writes data to the file and stores in the internal storage. When I get the absolute path or path of the file [I have added log messages to experiment with the operations on the File], it shows me that the file is getting created under the root directory and its under the /data/data/mypackagename/files/filename.txt. Nevertheless, I could find these folders on the DDMS where I could find the file which has been created by the method which I have written. But I am unable to open that file too as I don't have permissions.
When I look at my Android device, I can't find these directories. I looked up on stack overflow and some have answered that the /data/data folders in the internal storage are hidden and to access them I have to root the device which I don't want to do.
Next approach: There is a folder called as MyFiles on the android device [I am using Galaxy Tab 4 running Android 4.4 for testing]. Under this folder there is Device Storage directory which has various folders like Documents, Pictures, Music, Ringtones, Android, etc, etc.. So, the apps like camera, spread sheet apps, are able to write or save pictures into the pictures folder or txt files in the documents folder. Similarly, how could I write the file which I am creating in the function to the Documents folder or any other folder which could be accessible over the device. Please help me how could I do it, any help is appreciated.
The following is the code which I have written:
public void addLog(String power_level){
// creates a logFile in the root directory of the internal storage of the application.
// If the file does not exists, then it is created.
Log.d("AppendPower", "In addLog method");
//File logFile = new File(((Context)this).getFilesDir(), "logFile.txt");
File logFile = new File(getFilesDir(), "logFile.txt");
Log.d("FilesDir Path", getFilesDir().getAbsolutePath());
Log.d("FilesDir Name", getFilesDir().getName());
Log.d("Path on Android", logFile.getPath());
Log.d("Absolute Path on Android", logFile.getAbsolutePath());
Log.d("Parent", logFile.getParent());
if(!logFile.exists()){
try{
logFile.createNewFile();
}catch(IOException io){
io.printStackTrace();
}
}
try{
BufferedWriter writer = new BufferedWriter(new FileWriter(logFile, true));
writer.write("Battery level reading");
writer.append(power_level);
Log.d("Power_Level in try", power_level);
writer.newLine();
writer.close();
}catch(IOException e){
e.printStackTrace();
}
}
As you have figured out writing to root directories in Android is impossible unless you root the device. Thats why even some apps in Play-store asking for root permissions before installing the app. Rooting will void your warranty so i don't recommend it if you don't have serious requirement.
Other than root directories you can access any folder which are visible in your Android file manager.
Below is how you can write into sd with some data - Taken from : https://stackoverflow.com/a/8152217/830719
Use these code you can write a text file in SDCard along with you need to set permission in android manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
this is the code :
public void generateNoteOnSD(String sFileName, String sBody){
try
{
File root = new File(Environment.getExternalStorageDirectory(), "Notes");
if (!root.exists()) {
root.mkdirs();
}
File gpxfile = new File(root, sFileName);
FileWriter writer = new FileWriter(gpxfile);
writer.append(sBody);
writer.flush();
writer.close();
Toast.makeText(this, "Saved", Toast.LENGTH_SHORT).show();
}
catch(IOException e)
{
e.printStackTrace();
importError = e.getMessage();
iError();
}
}
.
1) If your purpose is debugging, you may just write to the /sdcard/. It always works.
2) Again, if your purpose is debugging, you may try to set read permissions on your app's directories. A while ago it worked for me on some Android devices (but did not work on at least one device).
Add this permission in your AndroidManifest.xml file:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Then use this shortest recipe:
try
{
FileOutputStream fos =
openFileOutput("myfile.txt", getApplicationContext().MODE_PRIVATE);
fos.write("my text".getBytes());
fos.close();
}
catch (Exception exception)
{
// Do something, not just logging
}
It will be saved in "/data/data/my.package.name/files/" path.
I have been trying for the last couple of days to find the right way of writing a file to a subdirectory of the android data folder.
Most answers i found were not clear or didn't address the problem in a right and working way so i finally decided to ask.
I am giving a user the possibility of backing up his data on my server by basically uploading the database to the server through a php script.
The database is located in
'/data/data/com.package/databases/data.db'
The problem here is when a user wants to reload a backed up database.
The application Downloads the file and should then write it (Overwriting the old one) to the /databases/data.db' file, and then reload.
I have managed to get everything to work up until where i have to write the downloaded file because FileOutputStream throws an illegal argument exception saying that i can't use path separators in the path.
I understand that FileOutputStream can only write to the first level of the data folder and not to subdirectories.
How can this be done?
If it can't be done, is there any way to set the default database path to the first level of the 'data' directory to solve this problem?
If this is a completely wrong approach to what i want to obtain i am open to critique but it would still be nice to get an answer, just for future knowing.
public void aSyncDatabaseDownloadFileFinish(PhpWrapper feed) {
if (validateServerResponse(feed.Result)) {
// Copy Database to Directory
try {
FileOutputStream fos = ctx.openFileOutput(ctx.getDatabasePath(DataDatabaseHelper.DBNAME).getAbsolutePath(),
Context.MODE_PRIVATE);
fos.write(feed.DownloadedBytes, 0, feed.DownloadedBytes.length);
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
else
Toast.makeText(ctx, ctx.getResources().getString(R.string.nofilesonserver), Toast.LENGTH_SHORT).show();
}
Thanks in advance.
How can this be done?
In your case, use getDatabasePath() to write a file into the standard location for databases for your app.
Regardless of your path separator issue, openFileOutput() will work with files/ directory in your internal storage, not the databases/ directory.
Ok,
I got the answer thanks to Squonk, Still can't believe that it was that simple.
For anybody having the same problem here is an example:
if (validateServerResponse(feed.Result)) {
// Copy Database to Directory
try {
// This Solved the Exception
FileOutputStream fos = new FileOutputStream(ctx.getDatabasePath(DataDatabaseHelper.DBNAME), true);
fos.write(feed.DownloadedBytes, 0, feed.DownloadedBytes.length);
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
else
Toast.makeText(ctx, ctx.getResources().getString(R.string.nofilesonserver), Toast.LENGTH_SHORT).show();
Thank you Squonk!
I'm trying to create a .csv file in an android app. The app is supposed to create the file if there is none, or replace the file if it already exist. I tried to use the FileWriter, but it doesn't create the file and throws the 'FileNotFoundException: open failed: EROFS' exception.
I've already done some research, but I really can't find it. I have the permission in the manifest file (<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />) and the app folder is not open in any other app.
(I know there is opencsv, but since this is the only thing I need to do, I don't think I really need it.)
Here's my code:
FileWriter writer;
try {
writer = new FileWriter("data.csv");
for(Answer answer: answerList) {
writer.append(answer.getName());
writer.append(',');
writer.append(answer.getTime());
writer.append('\n');
}
writer.flush();
writer.close();
}
catch (Exception e) {
e.printStackTrace();
}
Thank you!
Change
writer = new FileWriter("data.csv");
to
writer = new FileWriter(getFilesDir()+File.separatorChar+"data.csv");
This will create the file in the internal storage.
You need to give the full path to where you want to create the file or where it exists already.
First: see my question Reading XML online and Storing It (Using Java). Read the approved answers and the comments underneath that answer.
So, what my question here is: even though I've run through the process described in the linked question, and the .xml file saves to the /res/values folder in my Android App, its not showing up at all - not when I'm running the app, nor after I close the app.
Does anyone have any ideas on how to fix this so that when I generate the file, it will be available right away, even while the app is running, to read and use?
just use this code,
FileOutputStream fOut = null;
try {
fOut = this.openFileOutput("your xml file name.xml", MODE_PRIVATE);
try {
InputStream is = new FileInputStream("your source file");
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
fOut.write(buffer);
} catch(Exception e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
fOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
and you can see your xml file at the data/data/packagename/file folder Thnx. Hope this will help you.
I'm not 100% sure if you're running the XML parsing in Java or actually in your Android app.
If you're running in Java, be aware that your project structure isn't live in the emulator - the .apk was packaged up and installed before running. You need to use adb to push files into the emulator (or your Android device) before your app can see the file.
If you're accessing the file in the app:
If you use file access methods such as openFileOutput() it will show up in the private directory on the device, which would be /data/data//files/
However, if you're using "new File(" rather than "context.openFileOutput" then the file is wherever you put it.
My app has .txt files in subdirectories in the assets folder. It reads those .txt files and puts them in a textview. It's working great and no problems.
Should I be concerned about the files in the assets folder getting deleted by the user or missing. If this ever could happen, my app would get an error because the file would not be there when it tried to read it into the stream.
Is there a need for me to check the existence of an asset file before I read it or does the asset manager take care of it all? I also was wondering if there's a chance that a user would or could delete and asset file.
Like I say, everything works fine without me inserting code to check for file existence. I just wondered if people use the .exists() statement every time they go to read in a stream from assets.
You may be concerned that the file have been removed and the apk resigned
You can check using:
Arrays.asList(getResources().getAssets().list("")).contains("myFile")
if you really want to check for the file existence:
AssetManager mg = getResources().getAssets();
InputStream is = null;
try {
is = mg.open(pathInAssets);
//File exists so do something with it
} catch (IOException ex) {
//file does not exist
} finally {
if (is != null) {
is.close();
}
}
If your file is located in assets/folder/file.ext, then pathInAssets would be
"folder/file.ext"
Ideally after apk is built, nobody can remove any assets from it, but if someone decompiled it and recompiles than it may be possible.
Though for other scenarios also when an asset is not present in apk at Runtime, we can check the existence of asset.
In our app, we have a provision to build app using gradle, ant and eclipse, and for each build mechanism some of our assets file are bundled in apk and some are not, so to identify if any asset file is present in current build apk at runtime,
we do this as follows:
private boolean isAssetExists(String pathInAssetsDir){
AssetManager assetManager = AppContext.get().getResources().getAssets();
InputStream inputStream = null;
try {
inputStream = assetManager.open(pathInAssetsDir);
if(null != inputStream ) {
return true;
}
} catch(IOException e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
Yes and No.
A normal user would not be able to delete them, but a user on a rooted phone who doesn't know what they're doing… that's a different situation.
If you ask me, the extra code is not needed. Also if you try and open a file that doesn't exist, you will get an exception thrown at some point, catch that and display a dialog if you really want to.
AssetManager am = getAssets();
try {
List<String> mapList = Arrays.asList(am.list("path/in/assets/folder"));
if (mapList.contains("file_to_check")) {
Log.e("ERROR", "exists");
} else {
Log.e("ERROR", "not exists");
}
} catch ( IOException ex){
ex.printStackTrace();
}
Convert to function or method can be easy ;)
I think you should be OK. From having a root around in my phone I can't see any way of deleting the assests without deleting the app as it all seems to be wrapped up in the .apk file. You can do it but I think you need to be rooted or use adb.
I would personally surround any reading/writing with a try/catch block anyway, just to be safe.