I'm using Xamarin Forms for a photo capture app and using James' Media Plugin PCL to capture photo using the device camera.
I realize that, for every photo, it creates a file in
/storage/emulated/0/Android/data/com.myapp/files/Pictures
(and I can provide a subdirectory within Pictures folder and the name of the file). What I want to do is delete all these files the next time my app starts up.
Since I'm only focused on the Android version, I've set up a dependency service call to locally delete the file (which I thought was trivial) but for some reasons I simply can NOT find that file programmatically or through ADB shell.
When I plug my device in for USB file transfer on windows computer, I can see the photos I want to delete in
Computer\Moto G (4)\Internal shared storage\Android\data\com.myapp\files\Pictures
But I can't get to these files through code or shell. In code, I'm getting the path through
Forms.Context.GetExternalFilesDir(Android.OS.Environment.DirectoryPictures).AbsolutePath
which gives me the path
/storage/emulated/0/Android/data/com.myapp/files/Pictures
which I think is the path where my files SHOULD be. But it's come up blank. Whether I try System.IO or Java.IO, the directory comes up empty and file.delete() or System.IO.File.Delete(path) doesn't work for me.
tldr; What does
Computer\Moto G (4)\Internal shared storage\Android\data\com.myapp\files\Pictures
translate to in terms of actual physical path in Android OS which we can list from ADB Shell?
What I want to do is delete all these files the next time my app starts up.
Try using the following code, it works fine on my side :
public void DeleteFolder()
{
var path = Forms.Context.GetExternalFilesDir(Android.OS.Environment.DirectoryPictures).AbsolutePath;
Java.IO.File directory = new Java.IO.File(path);
if (directory.IsDirectory)
{
foreach (Java.IO.File child in directory.ListFiles())
{
deleteRecursive(child);
}
}
directory.Delete();
}
It was a false negative. I was looking at the files through Windows Explorer and for some reason, Windows kept showing me those files even after they were deleted. Obviously, the reason I couldn't se those files through ADB Shell or from within Android File Manager was because those files were never there.
Forms.Context.GetExternalFilesDir(Android.OS.Environment.DirectoryPictures).AbsolutePath
gives me
/storage/emulated/0/Android/data/com.myapp/files/Pictures
which is the same as
Computer\Moto G (4)\Internal shared storage\Android\data\com.myapp\files\Pictures
Both System.IO.File.Delete(path) and new Java.IO.File(dir, children[i]).Delete(); methods work fine. It's just that windows chooses to keep showing the empty "ghost" files.
This issue has apparently been raised before to no answer: Programatically deleted files still show up in Windows Explorer
Related
Changes like renaming a file triggered by an app only appear to the USB-MTP interface after reboot of the Android device or after you registered the new file at the MediaScanner them like this (see Trigger mediascanner on specific path (folder), how to?):
file.renameTo(newFile);
MediaScannerConnection.scanFile(context,
new String[] { newFile.getAbsolutePath() }, null, null);
USB-MTP is used to access the storage of an android device via USB. E.g. with the Windows Explorer.
However, with the Sony XPERIA Tablet Z (SGP321) under Android 5.0.2 (Build 10.6.A.0.454) folders supplied in newFile will become a file with 4KB. I am no more able to access the folder structure using Windows Explorer anymore, nor can I copy the file to my computer. Even after reboot of the tablet! The same device with Android 4.4.4 does not show the behavior. It appears that only the USB-MTP view is broken. The file structure accessed by an android app still looks fine.
Question: Is this behavior a bug or did I implement it incorrectly? What would be the correct implementation?
What I've tried so far to fix the issue:
My current workaround is to avoid scanFile for directories.
I can convert files back into directories by renaming them with an android app without MediaScannerConnection#scanFile. After reboot, I can access the directory with Windows Explorer again.
Renaming files with Windows Explorer that actually are directories does not restore them. Even after Reboot.
This line as suggested in https://stackoverflow.com/a/21918085/433718
does not refresh USB-MTP view, but also does not convert directories
into files:
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
Uri.fromFile(newFile.getParentFile()));
Maybe related:
https://stackoverflow.com/a/27321544/433718
Using content resolver for all sorts of File operations like deleting a file in this answer: Android Deleting Files MediaScannerConnection
I ended up creating a dummy text file in each directory I wanted to make visible, and use scanFile on the file.
1) create directory, but don't "scan" directories
2) copy file to directory
3) run scanFile on the filePath
MediaScannerConnection.scanFile (_application, new String[] { filePath }, null, null);
I created a new Folder from within my app. I did so via
new File(folder-path).mkdirs();
The folder is called "Albums" and is located in /storage/emulated/0/Pictures.
On Android there are no problems, the folder appears in several filemanagers as it should. But when I connect the phone to my computer (Fedora 21), the Folder is just a binary file with filesize ~4kb, so I cant access the files inside. I checked Permissions on the folder but I think its okay.
What can I do?
Do I have to scan the file somehow to be recognized as a folder?
Im on Android 5.0.2
After creation (or after deletion) run:
MediaScannerConnection.scanFile(this,
new String[]{"/storage/emulated/0/Pictures/Albums/image1.jpg",
"/storage/emulated/0/Pictures/Albums/image2.jpg",
....}
, null, null}
Every file you change (create or delete) should be in the string array. Alternatively, you can restart your device every time you make a change. Note that this command does not work correctly on empty folders. It will show a 4 kb file instead, as you are seeing now.
I am working on a project that needs to store some .txt to android, and get it from the computer for other use. From what I read from the documentation, I know that there are two types of storage: 1 Internal, which is somewhere deep in the phone that is private to the app. 2 External, which includes the SD card and the Internal Storage of the phone. I want to store it to External->Internal, and I am using this line of code to do that:
public String WalkDir = android.os.Environment.getExternalStorageDirectory().getAbsolutePath() + "/Walks/";
When I logged WalkDir, LogCat says "/storage/emulated/0", I stopped the app, checked with the adb shell, and there is no folder "0" but "legacy". I unplugged the phone and plugged it back in, the "Walks" folder is now in the root directory, and I don't need adb shell to access it.
So my question is, can you help explain how this system works? Why did "0" disappear? What is "legacy"? Why is the file in Internal Storage when I unplug&plug it?
Thank you very much!
Those are what in Linux are called symlinks (like shortcuts in Windows) that various system apps in Android are using..
/storage, /sdcard are sym linked folders,that means when you open one of those, it redirects to the original(/data/media/0), as for the 0 is just a multi user feature implemented in android 4.2, but only enabled on tablet androids.
Why do this Sym-Link?: simple so it dosent break apps(not only file explorer type of app, but all apps).
Still dont get, why it would break?.Simple. android api have lots of ways to write/read files from folders, u can do manually,u can get the data path, u can get the sdcard path, etc,etc. so to not break that they just does these sym links, thats why in one app the storage contentents are listed on /sdcard but on others, is /storage, etc,etc. one example of an app that broke because of these changes to android is titanium backup, u need to change the internal storage on it, so it work.
2 mount points pointing to the same storage device and partition.
If you create something in one folder, it will show up in the other. Same applies for deleting stuff.
They do not take away more storage space, as it is only available once but shown twice.
You also don't need to worry about it in any way because file browsers normally set their default directory to one of these locations.
As far as i know, Google changed the mount points in Android 4.2 to /storage/emulated/0/ due to them switching to MTP and EXT4(?) for the sdcard. The other mount points are still there for compatibility.
I have developed an Android app using Appcelerator Titanium. This app will create a file in applicationDataDirectory and install a database as well.
If run on emulator, I can locate those files using "adb" command. But how about on Android device? Can I use the "My Files" app to view those file I created? (since I can see files created by other application there.)
Moreover, I expect once I removed the app on device, it will automatically remove the related files and database. Is that true?
Because I found that even I removed the app from the device, the database seems left behind. I can tell because after deleting app and re-run on device(from Titanium), it show previous data.
I am using Ti SDK 2.0.1GA2, Android Runtime V8. And using Samsung Galaxy Tab for testing.
Thanks in advance.
Application Private Data files are stored within <internal_storage>/data/data/<package>
Files being stored in the internal storage can be accessed with openFileOutput() and openFileInput()
When those files are created as MODE_PRIVATE it is not possible to see/access them within another application such as a FileManager.
On Android 4.4 KitKat, I found mine in:
/sdcard/Android/data/<app.package.name>
Use Context.getDatabasePath(databasename). The context can be obtained from your application.
If you get previous data back it can be either a) the data was stored in an unconventional location and therefore not deleted with uninstall or b) Titanium backed up the data with the app (it can do that).
You can get if from your document_cache folder, subfolder (mine is 1946507). Once there, rename the "content" by adding .pdf to the end of the file, save, and open with any pdf reader.
This is a simple way to identify the application related storage paths of a particular app.
Steps:
Have the android device connected to your mac or android emulator open
Open the terminal
adb shell
find .
The "find ." command will list all the files with their paths in the terminal.
./apex/com.android.media.swcodec
./apex/com.android.media.swcodec/etc
./apex/com.android.media.swcodec/etc/init.rc
./apex/com.android.media.swcodec/etc/seccomp_policy
./apex/com.android.media.swcodec/etc/seccomp_policy/mediaswcodec.policy
./apex/com.android.media.swcodec/etc/ld.config.txt
./apex/com.android.media.swcodec/etc/media_codecs.xml
./apex/com.android.media.swcodec/apex_manifest.json
./apex/com.android.media.swcodec/lib
./apex/com.android.media.swcodec/lib/android.hidl.memory.token#1.0.so
./apex/com.android.media.swcodec/lib/libcodec2_soft_common.so
./apex/com.android.media.swcodec/lib/android.hardware.graphics.mapper#2.0.so
./apex/com.android.media.swcodec/lib/libcodec2_soft_vorbisdec.so
./apex/com.android.media.swcodec/lib/libcodec2_soft_h263dec.so
./apex/com.android.media.swcodec/lib/libhidltransport.so
./apex/com.android.media.swcodec/lib/libcodec2_soft_h263enc.so
./apex/com.android.media.swcodec/lib/libcodec2_vndk.so
./apex/com.android.media.swcodec/lib/android.hardware.graphics.mapper#2.1.so
./apex/com.android.media.swcodec/lib/libmedia_codecserviceregistrant.so
./apex/com.android.media.swcodec/lib/libhidlbase.so
./apex/com.android.media.swcodec/lib/libcodec2_soft_aacdec.so
./apex/com.android.media.swcodec/lib/libcodec2_soft_vp9dec.so
.....
After this, just search for your app with the bundle identifier and you can use adb pull command to download the files to your local directory.
Beginner android question. Ok, I've successfully written files. E.g.
// get the file name
String filename = getResources().getString(R.string.filename);
FileOutputStream toWriteTo;
try {
toWriteTo = openFileOutput(filename, MODE_WORLD_READABLE);
// get the string to write
String toWrite = getResources().getString(R.string.contentstowrite);
toWriteTo.write(toWrite.getBytes());
toWriteTo.close();
...
}
catch (Exception ex) {
Toast.makeText(HelloFilesAppActivity.this, "fail!", Toast.LENGTH_SHORT).show();
}
}});
And I've proved that it is there by reading it and displaying contents, even using getFilesDir() and displaying all of the files in the folder.
Everything I read says that the files are in /data/data//files/
But I cannot find them. (I'm on Windows XP). My install didn't use default locations because my C:\ is pretty full. I looked in C:\Documents and Settings\Mike\.android\avd and in the project folder and in the place I installed the SDK: D:\Program Files\Android\android-sdk-windows. So where is /data/data/ ?
I read that I can use ADB to push and pull files back and forth, but I'm using Eclipse ADT and I'd prefer to use something other than command line. The book I'm using seems to imply that you can use Eclipse but then proceeds to give the command-line commands.
I found info about the Project Explorer in the DDMS, but I don't see the files I have written.
I've been working under the assumption that I might want to create a text file using some other means in Windows that I would read with my App. So if the answer is "why do you want to do this?", that's what I'm after. Eventually a DB probably too (that's in the next chapter :-) ).
Do I have to use the ADB command line?
thanks
Mike
http://developer.android.com/guide/topics/data/data-storage.html
The method your using to get the directory you read/write to:
openFileOutput()
You can save files directly on the device's internal storage. By default, files saved to the internal storage are private to your application and other applications cannot access them (nor can the user). When the user uninstalls your application, these files are removed.
You'll want to save the files your working with to the SD card.
Try this:
getExternalStoragePublicDirectory Example
It's on your phone. Your phone has its own file system. If you are using an emulator, then it's on the emulated file system, which is completely separate from yours. Your only way to access the phone's (or emulator's) file system is via ADB (unless we're talking about the SD card, which however does NOT host /data/data).
Side note - if your phone is not rooted, you won't have access to a lot of stuff on /data/data. I suppose that you are using an emulator, which is "rooted" in the sense that you have full access to its filesystem.