I manage media (images, sound) of my app directly, reading and saving to the SD card. Should I be using the MediaStore instead? I'm not quite sure what the MediaStore is for, and the javadoc is not very helpful.
When should an app use the MediaStore? A brief overview of the pros and cons of the MediaStore will be much appreciated.
As an avid android user.
I think MediaStore is the "Public Link" between the internal Android Media Scanner Application (You can manually invoke it through Spare Parts) and 3rd party applications, like yours.
I'm guessing MediaStore is this "public link" based on its android.provider packaging.
As providers in android, is how applications provide information to other applications
If MediaStore is a ContentProvider, reading information populated by MediaScanner.
Then MediaStore is for User media, such as music, video, pictures etc.
For ringtones, notifications; I think you are supposed to use android.media.RingtoneManager
Also don't hardcode the path "/sdcard/" There is an api call to get it, Environment.getExternalStorageDirectory()
http://twitter.com/cyanogen/status/13980762583
====
The pro is that Media Scanner runs every time you mount the removable storage to the phone, and it also scans the internal memory (if it has any like the HTC EVO & incredible)
I am no expert in this but as far as my common sense goes, well its the easy way to search for certain types of files.
If your app has a library of sorts, then using MediaStore instead of searching all by yourself is more useful, faster and less power consuming. Also you can be assured that those are all the files present in the system.
I hope this helps.
Related
I am trying to build an application in which user can share media files over internet. Now I am confused that there are lots of functions in the library through which we can get access to files stored in the users storage. I don't know which to use..
In Context#getExternalFilesDir(String) documentation, they insist using Environment.getExternalStoragePublicDirectory() to write media that must be shared with other apps and that must be kept even after uninstall of an app. But in Environment#getExternalStoragePublicDirectory(string) documentation, they say that this method is deprecated, and recommend using alternatives such as Context.getExternalFilesDir(). If that was deprecated in first place, then why did they insist to use that method. What is the reason behind them playing these tricks, I don't understand.
Please suggest me a function that is: not deprecated, should return a directory where I can read and write, media stored there should be visible to other apps, they must not be deleted when user uninstalles this app.
I believe you are looking for Shared Storage.
Android file system and storage changed a lot during this years.
Data and file storage overview
Okay, so I've done as much research as I can to try and figure out if I'm doing anything wrong, but nothing on Google or the Android tutorials could really answer me in my scenario.
The Scenario:
Let's say I have an Android device that comes with 16GB of built-in storage. Let's also assume that the device has a 32GB SD scard. Basically, the device has a total 48GB of storage space. My app needs to scan every user-accessible location on the device. In other words, I need to be able to access and read every place that a regular user (non-root) can read and write to.
What I'm doing right now:
I'm using the recommended Environment.getExternalStorageDirectory() which points me to /mnt/sdcard.
The Question:
Is Environment.getExternalStorageDirectory() going to give me access to every user-accessible storage on the device? I'm confused because there can be 16GB of built-in storage and 32GB of SD card storage, but how does Android handle the two separate locations? Does it simply combine the two into a singular /mnt/sdcard or am I only able to access one of the two storage directories with my line of code?
Sorry if this sounds like a noob question, but coming from an iPhone background where the only storage available is internal storage, I'm really stumped by Android's method of handling this situation. Thanks for all your help!
Is Environment.getExternalStorageDirectory() going to give me access to every user-accessible storage on the device?
No. It points you to external storage.
how does Android handle the two separate locations?
Android itself mostly only cares about the one spot designated as external storage. Anything above and beyond that is device-specific and is up to the manufacturer (or, possibly, ROM mod maintainer).
This is why you do not see anything in the current Android SDK for accessing multiple volumes that all might be considered "external storage".
Does it simply combine the two into a singular /mnt/sdcard
No.
or am I only able to access one of the two storage directories with my line of code?
Yes.
UPDATE: I wrote a series of blog posts to try to help developers make sense of the Android storage situation.
The idea is that.
My application allows user to listen to music and watch videos from the social network. User can save these files in cache to be able to play them offline. This data is saved to SD-card and can be accessed by file managers e t.c.
I want to limit access to these files to other application. The most obvious solution is data encryption.
Can you please recommend me some libraries or frameworks for quick file encryption/decription? It is very desirable to encrypt files "on the fly" during the are loading.
Would this procedure be too slow and resource intensive?
May be there exist some other ways - protected folder in the SD filesystem or something like that?
Yes there is a more standard way to do this.
By using openFileInput on your Context and setting the MODE_PRIVATE flag, you will be able to create files and even folders within your application. Also, these resources will be completely private to your application.
EDIT :
Most of the time, these files will be stored in /data/data/<app_package_name>/files. That is, on the phone memory most of the time, although this is implementation specific.
Regarding the comment of #Carlos mentionning file spamming, yeah you can flood the NAND with multiple files, but /data will be in most cases mounted on a dedicated partition. So you'll be hitting the virtual size of the partition at some point. Please look at this post, the accepted answer gives more details about this.
In fewer words, this is implementation specific (depends on the manufacturer).
Your only option would be to use Encryption, if you want to keep using the external storage. SpongyCastle can help with that. It is an android version of the BouncyCastle APIs.
Apart from that, you could move your files to the internal storage, which may not be feasible in your case as media files tend to be big, and internal storage on most devices is very limited. Even if you do move them to internal storage, any rooted user can access them (or any app with root privileges).
Protecting the folder isn't an option, as anything on the external storage is available to any app with permission to access the external storage. There is nothing you can do about that.
I'm looking for a solution (possibly implementing it) that would allow me to create a cache on my SD card (say, 25G) which would be used by some "caching layer" to store media on demand. The issue being that all of my media doesnt fit on a 32G SD card, so I want to be able to transparently have my missing data downloaded (ie: I dont want to have to download using another app) while I am attempting to play it in the stock media player or the Gallery or whatever. Does anyone know of an existing solution like this? I'm already familiar with the various dedicated apps out there which do this for music, but I'm looking more for a generic cache which caches anything that passes through it on an LRU basis. I want my NAS at home (or on S3, dropbox, Ubuntu One, whatever) to be an extension of my Android device(s).
If one doesnt exist, is it possible to chain ContentProviders? Could I create a CacheProvider which keeps track of what is currently in my cache and what isnt, and use the URIs from the CacheProvider to populate the MediaStore? All examples I can find so far show that what comes out of the MediaStore is always a URI to a file, so I suspect its not currently possible.
After a little POC, it appears that this is not possible using ContentProviders alone. While it is possible to chain providers together if you override ContentProvider.openfile(), since the MediaProvider currently assumes that everything in _data points to a file or an HTTP stream, the Music app will fail to play any content which sticks another content URI into _data. If MediaProvider were changed to handle content URIs then this would be possible, but I think the only way to achieve that would be to copy/paste the MediaStore framework and rename it all, or to do the change in a mod (like CyanogenMod).
I'm developing an app that would have an In-app purchase and download Videos from my server and store them on the device.
The problem is, the Videos are paid videos and are to be maintained in a highly secure place inside the app itself.
What are the possibilities of doing it? I had a look at setting android:exported="false", but it just restricts other apps to access my app's data. But how do I store the videos in a place which are restricted to be viewed by default even when connecting the device to a PC?
Are the apps allowed to store data in the device's \data folder? If so, please tell me how!
You can store files in your app's data folder, and as long as the phone isn't rooted, only your app should be able to access them.
However. The local storage on phones is generally limited, so storing videos there is a bad idea. Also, unless you're integrating your own video player, you might have issues trying to get the phone to play videos in your private folder.
To speak to the security issue, I'd suggest trying to keep them on the sd card, and experiment with either encrypting them, so they can't be read raw from disk, or (possibly) experimenting with file permissions, although I doubt the latter would work.
To do the encryption, I'd download the video, encrypt it and save it to the sd card. When you want to watch, decrypt and temporarily save to local storage for viewing. Not sure what kind of performance that will get, though. Plus, if you're relying on the OS to play your videos, you could have the same permission issues mentioned above. Depending on how critical this all is, you could explore something where the file/folder structure is obscured, so getting at them manually is more complex. Won't prevent all grab attempts, but will deter casual users.