I have spent many hours trying to find/create files for an app I am writing. When I pull the application directory name I get: /data/data/com.example.android.[myapp]/files. I am using File(getFilesDir():
File fileDir = new File(getFilesDir() + File.separator);
Log.i(TAG, "File directory: "+fileDir);
When I try to find this path I find many application folders here: Android/data/com but no /data/data folder under Android. There are many other application folders there but not mine. I see the same results whether I use Android Files app or Windows Explorer over USB. I've also tried to look using Eclipse DDMS tab. I see a data folder with a (+) to the left but when I click, it does not expand.
I have also tried creating the directory and file manually with Windows explorer and my app still can't find neither the Android/data/com.example... nor the Android/data/data/com.example... paths.
Also puzzling to me is when the app creates the path and file and write to it (using MODE_WORLD_WRITEABLE) I get no exceptions thrown but then I am unable to read it back or see it with either of the tools mentioned above. I have set the manifest permissions to WRITE_INTERNAL_STORAGE and WRITE_INTERNAL_STORAGE for the app.
Obviously, I am making a very basic mistake.
I am on Android 4.1.2 (API 16).
Sincerely,
ScratchingMyHead
To get the path of my application directory, Try this code sample
PackageManager m = getPackageManager();
String s = getPackageName();
try {
PackageInfo p = m.getPackageInfo(s, 0);
s = p.applicationInfo.dataDir;
} catch (NameNotFoundException e) {
Log.w("yourtag", "Error Package name not found ", e);
}
When I try to find this path I find many application folders here: Android/data/com but no /data/data folder under Android.
That is because you are looking on external storage, not internal storage where your files are. Use DDMS on an emulator to examine internal storage.
I've also tried to look using Eclipse DDMS tab. I see a data folder with a (+) to the left but when I click, it does not expand.
That would sound like what you will get when testing on hardware, as neither you nor DDMS have access to the contents of /data on production hardware.
In my android app, I create a file and write some test text into it:
File externalPath = getExternalFilesDir(null);
File importPath = new File(externalPath, "pd-import");
if(!importPath.exists()) {
Log.d(this.getClass().getSimpleName(), "Create import dir: " + importPath.getAbsolutePath());
importPath.mkdirs();
}
File readme = new File(importPath, "README.txt");
try {
FileWriter fw = new FileWriter(readme);
fw.write("This is a test");
fw.flush();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
This writes the file, which can be approved with an android file browser like B1 File Manager. It's written to HOME/Android/data/JAVA_PACKAGE_NAME/files/pd-import/README.txt
The logcat shows me:
D/MainActivity﹕ Create import dir: /storage/emulated/0/Android/data/JAVA_PACKAGE_NAME/files/pd-import
When I connect my Nexus, where I tested the code, to my Ubuntu Laptop via USB, I see all the other applications data directories like NEXUS 5/Interner Speicher/Android/data/ALL_THE_OTHER_JAVA_PACKAGE_NAMEs ("Interner Speicher" stands for: internal memory). But the folder is not listed for my app is not listed.
Do I need to set some additional medatdata/information/whatever, to have the folder listed over the MTP connection? Anny suggestions?
Does the directory appear when the device is rebooted ? If yes, I think this bug is the cause : https://code.google.com/p/android/issues/detail?id=38282
All phones using MTP instead of USB Mass storage do not properly show
the list of files when that phone is connected to a computer using a
USB cable. Android apps running on the device also cannot see these
files.
This affects files written using Java APIs, but does not appear to
affect files written using the C API.
The solution is to reboot the device.
It does not seem to be resolved.
I want to get the external and internal storage in my app. I'm using this code
Scanner scanner = new Scanner(new File("/etc/vold.fstab"));
while (scanner.hasNext()) {
String line = scanner.nextLine();
if (line.toLowerCase().contains("dev_mount")) {
if (line.toLowerCase().contains("nonremovable")) {
VoldMounts.put(line.split(" ")[2],true);
}else {
VoldMounts.put(line.split(" ")[2],false);
}
}
}
It's working fine on Android 4.2.2 and below, but on Android 4.3 the file is changed to /fstab.<device> and this file needs root access. How can I read the fstab without the need of root access? I don't want to use /proc/mount.
Thanks.
Here is some official information that confirms that "for Android releases 4.3 and later, the various fstab files used by init, vold and recovery were unified in the /fstab. file". As that file has -rw-r----- root root permissions there is no way to read it from an app on a non-rooted device.
The scenario I am going for is as follows:
Android application (apk) that is "generic", i.e. I do not want to recompile with different resources
APK will be "pre-installed" on devices and so will not be a "market" app
The application needs a custom configuration file that customizes it with text, etc. that can be different for each installation. (config file needs to be in same location with same name)
On app start-up the config file gets read and configures app according to the data in the config file
In essence, this would be a way to provision the application so that it takes on a specific look and feel based on the config file without having to recompile. Be able to load custom image files, text data, etc.
The problem is that the config file needs to be easily updated and "copied" to a non-rooted device without a SD card. So I need access to the a non-app specific location that is easily accessible via a USB connection and that the APK has access to at run-time. It seems that SharedPreferences and Android file IO is limited to the private app directory under /data/data/pkg/... or external storage. Any ideas would be greatly appreciated. Thanks.
Just thought I would update with at least a partial answer. At least some of my issue has to do with testing in debug mode on my Razr Maxx. When I am connected via USB debugging then the call to create a new file fails as follows:
06-06 10:04:30.512: W/System.err(2583): java.io.IOException: open failed: EACCES (Permission denied)
06-06 10:04:30.512: W/System.err(2583): at java.io.File.createNewFile(File.java:940)
When I am running the app standalone on my device or in an emulator then it all works as expected. Not sure if this is related specifically to Razr Maxx or some other issue?
My code that is working is (from: Write a file in external storage in Android) :
private void writeToSDFile(){
// Find the root of the external storage.
// See http://developer.android.com/guide/topics/data/data- storage.html#filesExternal
File root = android.os.Environment.getExternalStorageDirectory();
mStatusTV.append("\nExternal file system root: "+root);
// See https://stackoverflow.com/questions/3551821/android-write-to-sd-card-folder
File dir = new File (root.getAbsolutePath() + "/download");
dir.mkdirs();
File file = new File(dir, "myData.txt");
try {
file.createNewFile();
FileOutputStream f = new FileOutputStream(file);
PrintWriter pw = new PrintWriter(f);
pw.println("Hi , How are you");
pw.println("Hello");
pw.flush();
pw.close();
f.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.i(TAG, "******* File not found. Did you" +
" add a WRITE_EXTERNAL_STORAGE permission to the manifest?");
mStatusTV.append("Write File 1: " + e.getMessage());
} catch (IOException e) {
e.printStackTrace();
mStatusTV.append("Write File 2: " + e.getMessage());
}
mStatusTV.append("\n\nFile written to "+file);
}
I'm trying to simply write a simple XML file to the SD card and I noticed that my Nexus 4 does write the file, but it is not viewable via the MTP protocol using Windows 7.
code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
CustomerQueryRqType customerQueryRequest = new CustomerQueryRqType();
Serializer serializer = new Persister();
File myFile = new File(Environment.getExternalStorageDirectory() + "/customerQueryRequest.xml");
try {
boolean created = myFile.createNewFile();
serializer.write(customerQueryRequest, myFile);
} catch (Exception e) {
e.printStackTrace();
}
}
I can see the file on the phone itself with Astro File Manager:
but Windows doesn't see it...:
adb shell on the directory shows:
ls -l
drwxrwxr-x root sdcard_rw 1970-01-16 20:51 Alarms
drwxrwxr-x root sdcard_rw 1970-01-16 20:51 Android
drwxrwxr-x root sdcard_rw 2012-11-21 19:30 DCIM
drwxrwxr-x root sdcard_rw 1970-01-16 20:51 Download
drwxrwxr-x root sdcard_rw 1970-01-16 20:51 Movies
drwxrwxr-x root sdcard_rw 1970-01-16 20:51 Music
drwxrwxr-x root sdcard_rw 1970-01-16 20:51 Notifications
drwxrwxr-x root sdcard_rw 2012-11-19 12:06 Pictures
drwxrwxr-x root sdcard_rw 1970-01-16 20:51 Podcasts
drwxrwxr-x root sdcard_rw 2012-11-19 13:22 Ringtones
drwxrwxr-x root sdcard_rw 2012-11-19 14:33 bluetooth
-rw-rw-r-- root sdcard_rw 79 2012-12-05 22:26 customerQueryRequest.xml
drwxrwxr-x root sdcard_rw 2012-11-20 02:50 data
-rw-rw-r-- root sdcard_rw 11394 2012-11-19 13:54 eightpen_custom_gestures
drwxrwxr-x root sdcard_rw 2012-11-19 13:17 media
What's going on with my Nexus 4? Why is it hiding my things from Windows?
Seems to be a known issue affecting Android USB file access over MTP. The MTP cache gets out of date until a reboot of the phone.
A workaround is:
Clear the "Media Storage" app's data
Use the SDrescan or the SD Scanner (also works on Android 4.4/5, available on F-Droid) app to force an update
Or just avoid using USB at all. The issue does not affect other methods of accessing the files. For example, try AirDroid to transfer files.
Note: This doesn't work for Android 5.0.2: After clearing "Media Storage" and using an SD Rescanner, the folders appears in Windows 7 as unopenable 4K files. The only solution at that point is to clear once again Media Storage and restart the device
You can use the following code after file close
MediaScannerConnection.scanFile(this, new String[] { file.getAbsolutePath() }, null, null);
Source:
https://code.google.com/p/android/issues/detail?id=38282
After spending hours on this issue I solved like this:
private void rescanFolder(String dest) {
// Scan files only (not folders);
File[] files = new File(dest).listFiles(new FileFilter() {
#Override
public boolean accept(File pathname) {
return pathname.isFile();
}
});
String[] paths = new String[files.length];
for (int co=0; co< files.length; co++)
paths[co] = files[co].getAbsolutePath();
MediaScannerConnection.scanFile(activity, paths, null, null);
// and now recursively scan subfolders
files = new File(dest).listFiles(new FileFilter() {
#Override
public boolean accept(File pathname) {
return pathname.isDirectory();
}
});
for (int co=0; co<files.length; co++)
rescanFolder(files[co].getAbsolutePath());
}
The thing is that you have to scan files only (not folders) and then repeat recursively for each fubfolder
EDIT
In addition, if you don't want pictures to be added to your photo album (but just your contents to appear over mtp protocol), remember to place an empty .nomedia file in your folder before rescanning it, like this:
new File(myFolder + File.separator + ".nomedia").createNewFile();
rescanFolder(myFolder);
The best workaround I found to the bug mentioned in the accepted answer is to copy data from Android OS to a another machine/server (Linux, MacOS, windows) using SSH.
Make sure that the device (Android) and the machine (where you want to copy the data) are reachable per IP or host name, for example by connecting them to the same wifi network.
Optional and recommended
Connect the android device using USB tethering. This ensures fast speed because of the wired connection and guarantees that both IP addresses are visible to each other because both are in the same network.
In the Android device
Install an SSH server. SSHelper worked like a charm
Run the SSHelper and go to the configuration tab to get the IP address, port, and password. In the example below, they are 192.168.1.5, 2222 and 'admin'.
The default password is admin but if you decide to change it hit the button "Restart server with new values" after changing it
In the machine
Install rsync. If happen to use Ubuntu it is already installed by default.
Open a shell and type the following command. Change the IP address and port to your values
rsync -avzhP --inplace --info=progress2 -e 'ssh -p 2222' 192.168.1.5:/storage/emulated/0/DCIM/Camera/ /home/username/path/to/pics/
you will get the following prompt, enter your password
SSHelper Version 8.5 Copyright 2014, P. Lutus
Default password is "admin" (recommend: change it)
username#192.168.1.5's password: admin
receiving incremental file list
The other suggestions did not work for me:
Using USB storage mode instead of MTP is not supported by the device (as many other newer devices).
There was no option in my OS (Android 6.0.1) to clear the "Media Storage" app data.
Other methods of sharing files over the network had their draw backs. FTP does not ensure the files integrity. If the connection is dropped it either overwrites or skips all files, so one of the files might be incomplete. Other protocols might be hard to install and other apps might use proprietary protocols.
On Xperia Z below code worked just fine:
String screenShotFile = "....";
activity.sendBroadcast(new Intent(
Intent.ACTION_MEDIA_MOUNTED, Uri
.fromFile(screenShotFile)));
for 4.4+ use:
activity.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
Uri.fromFile(screenShotFile)));
(unfortunalelly I dont remember if I have tested it well enough)
http://commonsware.com/blog/2013/11/06/android-4p4-permission-regressions.html
notice /storage/emulated. Android 4.2 has some funky emulated per-app/user access stuff going on, for example a separate /sdcard/ for each user. Try moving the file to /sdcard/ instead of the emulated sdcard that is shown.
The simple code proposed to question How can I refresh MediaStore on Android? does the necessary update of MediaStore, if called after I put a file on external storage. Content on my Nexus 4 is refreshed instantly in Window 7 file explorer.
I needed to create a directory and copy some sample files for my app. After a lot of experiments and research the following procedure worked flawlessly for me:
1) Created directory using File.mkdir().
2) Copied files in directory and run MediaScanner on each file.
MediaScannerConnection.scanFile(context, new String[]{file.getAbsolutePath()}, null, null);
3) Run MediaScanner on directory.
MediaScannerConnection.scanFile(context, new String[]{directory.getAbsolutePath()}, null, null);
Result: The files and directory appear instantaneously on PC over MTP.
Had a similar issue with my OneplusOne:
After software update (to 6.0.1) i was not able to see my camera pictures when connecting to the computer (PTP and MTP). Both app's SDRescan and SDscanner had no effect.
My solution was to copy all pictures from DCIM to another folder using terminal or any file Explorer app on the Phone. When connecting to computer i was able to see the copied files.. i moved them to my computer and cleared my camera folder. No permanent solution but it fixed the problem for me at least until i do the next backup. =D
The above answers are fine for creating the file. If you later delete the file and want that change to be reflected as well, you can do one of the following; let's first cover two solutions that seem like they work, but will cause problems on some devices. The first one is to scan the deleted file:
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));
This works on many devices for deleted files, but on some devices it'll actually cause a new 0-byte file to be created, which probably isn't what you want. In that case, if you're running on < 4.4 KitKat, you can do this:
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.fromFile(folder)));
Where folder is equal to file.getParentFile(). Unfortunately, on KitKat 4.4 and above, this will cause a SecurityException to get thrown, so for those devices, you can try deleting directly from the Media Store:
final Uri externalFilesUri = Files.getContentUri("external");
context.getContentResolver().delete(externalFilesUri, Files.FileColumns.DATA + "=?", new String[] {file.getAbsolutePath()});
I've tested this one as a workaround for ACTION_MEDIA_MOUNTED not working on KitKat, and it works in my testing on the Nexus 5.
Recently I faced with the same problem but some additional research helped find hidden files. It seems that Google has made some changes in storage structure. All these files were moved to another folder This Computer\HTC One\Internal Storage\storage\emulated\0. But it's strange that not all files were moved.
Android 4.4.2
From the documentation here, you need to call MediaScannerConnection.scanFile :
// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.scanFile(this,
new String[] { file.toString() }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});