I'm using xamarin forms to develop an Android app. I can save a file via
var fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), $"appsettiings.txt");
var data = JsonConvert.SerializeObject(this);
File.WriteAllText(fileName, data);
When I debug I can see that the file should be stored at
/data/user/0/<applicationame>/files/.local/share/appsettiings.txt
I like to see if the file is actually saved and what the content is. I opened the Android device monitor but the data folder was 'empty'. From some other SO case I took that I should but myself in root-mode by executing
C:\Program Files (x86)\Android\android-sdk\platform-tools>adb root
Now the data folder contains data and I can drill down up to the files folder, but that one seems to be empty.
When I run the app again and check in code if the file exists, it actually does.
Any further suggestions how to get access to that file from any tooling. I want to delete that file and run the app again.
You can use adb pull to copy the file to local machine and look at it content like this:
adb root
adb pull /data/user/0/<applicationame>/files/.local/share/appsettiings.txt [LOCAL_FOLDER]
then you can use adb shell then rm -f to remove it, like this:
adb shell
su
rm -f /data/user/0/<applicationame>/files/.local/share/appsettiings.txt
Since the file you are requesting is inside /data folder, you need to have the corresponding root priviliege to get it, so you need to do adb root before the adb pull command, and you need to do su before removing the file.
If I am not mistaken, if you save a file with your approach, it should exist, as you already proofed with the .Exists method.
I am not quite sure, are you just trying to read the content out of the file? Or do you want to access it from outside of the application?
If your desire is to just read the content, you could access it with
string content= File.ReadAllText(your file path);
and set a breakpoint (F9) on the next line.
New to Android, working on an app for Vuzix M300s. The app needs to access a file that contains the IP address and port of a web server.
I believe I will need to manually place a pre-configured file on the M300s using adb shell, but I cannot figure out where on the device to place it so that the app can find it.
Via Android Studio 3.1.3, I have placed a file in the assets folder which I can open & read, but using adb shell I cannot locate it. (I get permission denied for a lot of actions like ls).
How do I get a file on there? Or is there a better way?
Note that the assets folder in your project only exists on your development machine. The contents of this folder are packaged into the APK file when you build your app. In order to read any of these files, you need to use Context.getAssets() as explained in read file from assets.
Figured it out.
To move/copy a file to the M300s for an application
move the file to the device (in the sdcard folder)
.\adb push C:\temp\file.cfg /sdcard/
move the file from /sdcard/ to the desired location
a) go into the shell
'> .\adb shell
b) change to the application's permissions
$ run-as com.foobar.appname
c) copy the file into the app's 'files' folder
$ cp /sdcard/file.cfg files/
Within my app, I was able to read this with
FileInputStream fin = openFileInput("file.cfg");
InputStreamReader rdr = new InputStreamReader(fin);
char[] inputBuffer = new char[100];
int charsRead = rdr.read(inputBuffer);
String fileContents = new String(inputBuffer);
rdr.close();
Log.i(method, "charsRead: " + charsRead);
Log.i(method, "fileContents: " + fileContents);
I am trying to write a log file of my app to my external SD card. To figure out how to do this, I have been trying to follow the example HERE.
There is a section about 3/4 of the way down that page that says:
If none of the pre-defined sub-directory names suit your files, you can instead call getExternalFilesDir() and pass null. This returns the root directory for your app's private directory on the external storage.
My device does not have any of those pre-defined directories, and I would rather just as well save my data to the external SD card. Using the following command:
$ ADB shell
shell#android:/ $ cd /mnt
shell#android:/ $ ls -F
d ext_sdcard
You can see my external SD card. So, I created a directory on the external SD card:
shell#android:/ $ cd ext_sdcard
shell#android:/ $ mkdir MyAwesomeApplication
shell#android:/ $ ls -F
d MyAwesomeApplication
Now is when I [sort of] use the code from the Android developers site:
public File getDocumentStorageDir(String filename){
File file = new File("/mnt/ext_sdcard/MyAwesomeApplication", filename);
if(!file.getParentFile().mkdirs()){
Log.i(MainActivity.class.getName(), "Directory Not Created!");
}
return file;
}
When I run my application, it sort of works; I immediately get this error:
E/myPackage.MainActivity: Directory Not Created!
But then it creates the log file anyway, and successfully writes the data to the file.
My issue is that it is always overwriting the log file with new data, it doesn't append, even though I am using:
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
if(isExternalStorageWritable()){
File logfile = getDocumenetStorageDir("mylogfile.log");
PrintWriter logFileWriter = null;
try {
logFileWriter = new PrintWriter(logfile);
logFileWriter.append("stuff ...");
} catch(FileNotFoundException fnfe){
Log.i(MainActivity.class.getName(), fnfe.getMessage());
} finally {
logFileWriter.close();
}
}
Now, when I use this command:
shell#android:/ $ cd MyAwesomeApplication
shell#android:/ $ ls -F
- mylogfile.log
I see my log file where it should be. But when I use this command:
shell#android:/ $ cat mylogfile.log
// only the very latest piece of data is here
What I am I doing incorrectly here?
Thanks
there're two parts on your question and I'll try to address them separately.
Location of files
You should never hardcode file locations like you're doing (even if it's just debug logging). The location File file = new File("/mnt/ext_sdcard/MyAwesomeApplication", filename); might work for this device, but this vary on version of Android and manufacturer. You must use the appropriate getter method available to get the correct directory. On THIS LINK you can find the complete explanation, but from what I understood of your use case you want to use the following code:
public static File getLogFile(Context context) {
File folder = getExternalFilesDir("logs");
if(!folder.exists()) {
folder.mkdirs();
}
return new File(folder, "mylogfile.log");
}
Append to an existing file.
You didn't show how you're creating the PrintWriter, but I've always used the FileWriter class without any issues on appending.
Here in this question you can see about that (How to append to a text file in android?). And here some code
FileWriter f;
try {
f = new FileWriter(getLogFile(context), true); // true is for append
f.write(" ..logs...");
f.flush();
} catch(Exception e) {
.. handle exceptions
} finally {
if(f != null) {
f.close();
} catch(Exception ee){
... exceptions might happen here too
}
}
I am developing an app and I know my database *.db will appear in data/data/com.****.***
I can access this file from AVD in Eclipse with help of sqlite manager
But I can't access this file in my Android phone.
I googled it and it says I need to root my phone to do it, but I don't want to do that.
How can I access my data/data/..... directory in my Android phone "without rooting it"?
Can I change user permissions for the directory data/data..... without rooting it?
Accessing the files directly on your phone is difficult, but you may be able to copy them to your computer where you can do anything you want with it.
Without rooting you have 2 options:
If the application is debuggable you can use the run-as command in adb shell
adb shell
run-as com.your.packagename
cp /data/data/com.your.packagename/
Alternatively you can use Android's backup function.
adb backup -noapk com.your.packagename
You will now be prompted to 'unlock your device and confirm the backup operation'. It's best NOT to provide a password, otherwise it becomes more difficult to read the data. Just click on 'backup my data'. The resulting 'backup.ab' file on your computer contains all application data in android backup format. Basically it's a compressed tar file. This page explains how you can use OpenSSL's zlib command to uncompress it.
You can use the adb restore backup.db command to restore the backup.
If you are using Android Studio 3.0 or later version then follow these steps.
Click View > Tool Windows > Device File Explorer.
Expand /data/data/[package-name] nodes.
You can only expand packages which runs in debug mode on non-rooted device.
You could also try fetching the db using root explorer app. And if that does not work then you can try this:
Open cmd
Change your directory and go into 'Platform tools'
Type 'adb shell'
su
Press 'Allow' on device
chmod 777 /data /data/data /data/data/com.application.package /data/data/com.application.package/*
Open DDMS view in Eclipse and from there open 'FileExplorer' to get your desired file
After this you should be able to browse the files on the rooted device.
To do any of the above (i.e. access protected folders from within your phone itself), you still need root. (That includes changing mount-permissions on the /data folder and accessing it)
Without root, accessing the /data directly to read except from within your application via code isn't possible. So you could try copying that file to sdcard or somewhere accessible, and then, you should be able to access it normally.
Rooting won't void your warranty if you have a developer device. I'm sorry, there isn't any other way AFAIK.
The easiest way (just one simple step) to pull a file from your debuggable application folder (let's say /data/data/package.name/databases/file) on an unrooted Android 5.0+ device is by using this command:
adb exec-out run-as package.name cat databases/file > file
Open your command prompt
Change directory to E:\Android\adt-bundle-windows-x86_64-20140702\adt-bundle-windows-x86_64-20140702\sdk\platform-tools
Enter below commands
adb -d shell
run-as com.your.packagename cat databases/database.db > /sdcard/database.db
Change directory to cd /sdcard to make sure database.db is there.
adb pull /sdcard/database.db or simply you can copy database.db from device .
Use File Explorer in eclipse. Select Windows => Show View => Other ... => File Explorer.
An another way is pull the file via adb:
adb pull /system/data/data/<yourpackagename>/databases/<databasename> /sdcard
To backup from Android to Desktop
Open command line cmd and run this:
adb backup -f C:\Intel\xxx.ab -noapk your.app.package.
Do not enter password and click on Backup my data.
Make sure not to save on drive C root. You may be denied.
This is why I saved on C:\Intel.
To extract the *.ab file
Go here and download: https://sourceforge.net/projects/adbextractor/
Extract the downloaded file and navigate to folder where you extracted.
run this with your own file names: java -jar abe.jar unpack c:\Intel\xxx.ab c:\Intel\xxx.tar
I had also the same problem once. There is no way to access directly the file within android devices except adb shell or rooting device.
Beside here are 02 alternatives:
1)
public void exportDatabse(String databaseName)
{
try {
File sd = Environment.getExternalStorageDirectory();
File data = Environment.getDataDirectory();
if (sd.canWrite()) {
String currentDBPath = "//data//"+getPackageName()+"//databases//"+databaseName+"";
String backupDBPath = "backupname.db";
File currentDB = new File(data, currentDBPath);
File backupDB = new File(sd, backupDBPath);
if (currentDB.exists()) {
FileChannel src = new FileInputStream(currentDB).getChannel();
FileChannel dst = new FileOutputStream(backupDB).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
}
}
} catch (Exception e) {
}
}
2) Try this: https://github.com/sanathp/DatabaseManager_For_Android
On a rooted device, the correct solution is this:
Open cmd
Change your directory and go into 'Platform tools'
Type 'adb shell'
su
Press 'Allow' on device
chmod 777 /data /data/data /data/data/*
Open DDMS view in Eclipse/IntelliJ and from there open 'FileExplorer' to get your desired file
The original solution worked, but the chmod would return unknown directory. Changing the chmod command to /data/data/* gave access to all subfolders in the data directory from DDMS in Intellij. I assume the same solution is true for Eclipse DDMS.
UPDATE
So, what I've found is strange. I'm running a Nexus 6 using DDMS in IntelliJ (Android Device Monitor). I have built a little starter app. Said app saves data to a .csv file in data/data/com.example.myapp/files
When I first started to try to access this file on my Nexus 6, I found that I have to root the device.. I could see the data folder, but trying to open it would not work. As mentioned online in other places, the expand + would vanish then reappear shortly thereafter (note, there are solutions on the web that claim to allow access to these folders without rooting, I didn't find them till too late, and I'm not sure if I prefer not to root anyway ((I'd rather be able to do it manually than rely on an app or command prompt to give me my solutions))). I rooted my 6 and tried DDMS again.
At this point, it showed me the data folder and I could expand the folder and see the com. directories, but I could not open any of them. That is when I discovered the above solution. The initial instructions would not work on this part:
chmod 777 /data /data/data /data/data/com.application.pacakage /data/data/com.application.pacakage/*
That is when I tried the solution I posted:
chmod 777 /data /data/data /data/data/*
That solution seemed to work, but only on certain folders. I now could expand my myapp folder, but could not expand the files directory in it.
At this point, I played around for a while then figured why not just try it on the directory I need rather than trying these wildcard entries.
chmod 777 /data /data/data /data/data/com.example.myapp/*
Followed by:
chmod 777 /data /data/data /data/data/com.example.myapp/files
These commands allowed me to expand and view the files in my app's directory to confirm that the .csv was being saved correctly.
Hope this helps someone. I struggled with this for hours!
(to compound on this a tad further, oddly enough, the permissions did not pass to the .csv file that passed to the files directory. my files directory permissions read drwxrwxrwx and my log.csv file permissions read -rw-rw---- .. just fyi)
may be to access this folder you need administrative rights.
so you have two options:-
root your device and than try to access this folder
use emulator
p.s. : if you are using any of above two options you can access this folder by following these steps
open DDMS perspective -> your device ->(Select File Explorer from
right window options) select package -> data -> data -> package name
->files
and from there you can pull up your file
You can download a sigle file like that:
adb exec-out run-as debuggable.app.package.name cat files/file.mp4 > file.mp4
Before you download you might wan't to have a look at the file structure in your App-Directory. For this do the following steps THelper noticed above:
adb shell
run-as com.your.packagename
cd files
ls -als .
The Android-Studio way Shahidul mentioned (https://stackoverflow.com/a/44089388/1256697) also work. For those who don't see the DeviceFile Explorer Option in the Menu: Be sure, to open the /android-Directory in Android Studio.
E.g. react-native users have this inside of their Project-Folder right on the same Level as the /ios-Directory.
adb backup didn't work for me, so here's what I did (Xiaomi Redmi Note 4X, Android 6.0):
1. Go to Settings > Additional Settings > Backup & reset > Local backups.
2. Tap 'Back up' on the bottom of the screen.
3. Uncheck 'System' and 'Apps' checkmarks.
4. Tap detail disclosure button on the right of the 'Apps' cell to navigate to app selection screen.
5. Select the desired app and tap OK.
6. After the backup was completed, the actual file need to be located somehow. Mine could be found at /MIUI/backup/AllBackup/_FOLDER_NAMED_AFTER_BACKUP_CREATION_DATE_.
7. Then I followed the steps from this answer by RonTLV to actually convert the backup file (.bak in my case) to tar (duplicating from the original answer):
"
a) Go here and download: https://sourceforge.net/projects/adbextractor/
b) Extract the downloaded file and navigate to folder where you extracted.
c) run this with your own file names: java -jar abe.jar unpack c:\Intel\xxx.ab c:\Intel\xxx.tar
"
Simple answer is NO. On upcoming Android 13, you can't access anything in
/storage/emulated/0/Android/*
directory without Rooting your device or hooking up to a PC, certainly not in Pixel devices.
Read Android Source page for such App data access using ADB here:
https://developer.android.com/training/data-storage/manage-all-files
One of the simple way is to create your database on SD-Card. Because you cannot get access to your phone's data folder in internal memory, unless you root your phone. So why not simply create your database on SD-Card.
Moreover, if you want, you may write some file copying-code to copy your existing database file (from internal memory) to external memory without requiring any root.
you can copy this db file to somewhere in eclipse explorer (eg:sdcard or PC),and you can use sqlite to access and update this db file .
You can also try copying the file to the SD Card folder, which is a public folder, then you can copy the file to your PC where you can use sqlite to access it.
Here is some code you can use to copy the file from data/data to a public storage folder:
private void copyFile(final Context context) {
try {
File sd = Environment.getExternalStorageDirectory();
File data = Environment.getDataDirectory();
if (sd.canWrite()) {
String currentDBPath =
context.getDatabasePath(DATABASE_NAME).getAbsolutePath();
String backupDBPath = "data.db";
File currentDB = new File(currentDBPath);
File backupDB = new File(sd, backupDBPath);
if (currentDB.exists()) {
FileChannel src = new FileInputStream(currentDB).getChannel();
FileChannel dst = new FileOutputStream(backupDB).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
Manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
SQLlite database is store on user's Phone and it's hidding under path:
/Data/Data/com.companyname.AppName/File/
you have 2 options here:
you can root your phone so that you get access to view your hidding
db3 file
this is not a solution but a work around. Why not just create test
page that display your database table in it using 'select' statment.
I need to create files under myapp/files/subdir with global permission in my application. I do this because I use external applications to open some files
Using this
FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_WORLD_READABLE);
creates file only under files folder. Using
File dir=new File(Constants.TASK_DIRECTORY);
dir.mkdirs();
File file=new File(dir, FILENAME);
file.createNewFile(); FileOutputStream fos=new FileOutputStream(file);
creates files under subdirectories but with private permissions. I need to find a way to compose those both to create a file in a subdirectory to be world readable
I have been trying a lot of things but none helped me and this was the longest time unanswered question of mine
I know this is an old question, but here is the correct way
public void makeFileWorldReadable(String path)
{
File f = new File(path);
if(!f.exists()) // Create the file if it does not exist.
f.createNewFile();
f.setReadable(true, false);
}
OP asked how to give access to a file in the following hierarchy: appdir/files/subdir/myfile.
The answers provided here don't take subfolder into account, so I feel there's a room for improvement.
In order to access file in hierarchy, a consumer should have execute permission on each folder in a path in order to access (read, write, execute) files underneath it.
For API >= 24
Starting from API 24, Android restricts access to appdir (a.k.a /data/data/appdir):
In order to improve the security of private files, the private
directory of apps targeting Android 7.0 or higher has restricted
access (0700). This setting prevents leakage of metadata of private
files, such as their size or existence.
The appdir doesn't have world-execute permission, and therefore you can't cd into it:
angler:/ $ cd /data/data
angler:/data/data $ cd com.myapp
/system/bin/sh: cd: /data/data/com.myapp: Permission denied
Bottom line: you can give world-readable permission to one of the files in your app's folder, but no other app (as long as they don't share the same Linux user ID) will be able to read them.
Not only that: attempt to pass a file:// URI to external app will trigger a FileUriExposedException.
For API < 24
The appdir folder has world-execute permission by default:
shell:/ $ cd /data/data
shell:/data/data $ cd com.myapp
shell:/data/data/com.myapp $
Note that even the appdir/files folder has world-execute permission:
shell:/data/data/com.myapp $ cd files
shell:/data/data/com.myapp/files $
But if you'll try to create a sub-folder (underneath files folder), using this code:
File subdir = new File(context.getFilesDir(), "subfolder");
subdir.mkdir();
it won't have world-execute permission:
shell:/ $ cd /data/data/com.myapp/files
shell:/data/data/com.myapp/files $ cd subfolder
/system/bin/sh: cd: /data/data/com.myapp/files/subfolder: Permission denied
shell:/data/data/com.myapp/files $ run-as com.myapp
shell:/data/data/com.myapp $ cd files
shell:/data/data/com.myapp/files $ ls -l
total 72
drwx------ 3 u0_a226 u0_a226 4096 2016-11-06 11:49 subfolder
shell:/data/data/com.myapp/files $
Therefore, you have to explicitly give your newly created folder world-execute permission using File#setExecutable method (added in API 9):
subdir.setExecutable(true, false);
And only then, as suggested by others, you can create your file and give it world-readable permission:
File file = new File(subdir, "newfile");
if(!file.exists()) {
file.createNewFile();
file.setReadable(true, false);
}
Doing that will allow any external application read your file:
shell:/ $ cd /data/data/com.myapp/files
shell:/data/data/com.myapp/files $ cd subfolder
shell:/data/data/com.myapp/files/subfolder $ cat newfile > /sdcard/1
shell:/data/data/com.myapp/files/subfolder $ cd /sdcard
shell:/sdcard $ ls 1
1
If you are running it on a rooted device, change file permissions using:
Runtime.getRuntime().exec("chmod 777 " + PATH + fileName);
Or try File.setReadable(), File.setWritable while creating the file.
One workaround I used in the past was to re-open the already existing file using openFileOutput in append mode, and pass in the world readable and/or world writable flags during that time. Then immediately close the file without writing to it.
I like the new methods added in API 9 better though.