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).
Related
I wanted to know the best approach to passing information from an app to another app on the same devices in android.
For example:
I open google apps and I share a document with my App A.
Google App generated an intent and sends a content URI. From my
understanding, the content uri contains information about the file
(filename, file size, mimetype) and the ability to extract the
content which is located in the cache of the google app on the
device.
When App A opens, it reads the content URI. Ideally, it
should be able to extract the information from the content uri and
then render the image. What this means is that App A will display the image shared. In this example, google app shares a docement, and App A wants to open and display the document within it's own app.
The confusing part
From searching the web, it seems that some people actually try to
extract the file path from the content URI. This requires that you
have permission to access another app's cache or storage space
within the device. Let's say this is possible. It also makes some
assumptions that it's possible to extract the file path.
After reading some articles:
https://commonsware.com/blog/2016/03/14/psa-file-scheme-ban-n-developer-preview.html
https://commonsware.com/blog/2014/07/04/uri-not-necessarily-file.html
https://commonsware.com/blog/2016/03/15/how-consume-content-uri.html
it seems that, ideally you should never assume that you can extract the file path and that google has made some updates that makes this not possible.
Work around:
Eventhough i'm not able to extract the file path from the
contentUri, I'm able to read the bytes of what the contentUri is
pointing to. So I could save it to a file that is relevant to the
local cache of App A and pass that path along to get render or pass
the bytes back. This refers to App A displaying the content. That is passing the path or bytes and let's make the assumption that it knows how to display it given that information.
Question:
The work around does not seem ideal because technically you are
save the file again on the device. There are two locations with the
same content ( google app storage and App A's storage). You also
have to manage when to delete the App A's file that you created.
This doesn't really seem ideal and was wondering what the best
approach would be? Or is this the expected flow?
Also I don't know
if it's ideal to pass the bytes back up vs. just a file path.
Update
To be more specific, the app i'm creating is a hybrid where i'm using cordova plugin to interact with a web app. The web app has methods to process or display the shared document based on file path. So ideally I want to keep it consistent with just reading the file path so that the other platforms that the web app supports does not break.
Any advice appreciated,
D
Eventhough i'm not able to extract the file path from the contentUri, I'm able to read the bytes of what the contentUri is pointing to.
Correct. This is not significantly different than how you use an HTTPS URL, where you also do not have direct filesystem access to the content (in that case, resident on a different server).
So I could save it to a file that is relevant to the local cache of App A and pass that path along to get render or pass the bytes back.
Or, just consume the bytes. Again, drawing an analogy to an HTTPS URL, there is no requirement to save those bytes to disk to use them.
The work around does not seem ideal because technically you are save the file again on the device. There are two locations with the same content ( google app storage and App A's storage). You also have to manage when to delete the App A's file that you created.
Then do not save the file again on the device, and simply use the stream of bytes. Again, this is not significantly different than using an HTTPS URL.
This doesn't really seem ideal and was wondering what the best approach would be?
Do not write the bytes to disk. Just use them.
So ideally I want to keep it consistent with just reading the file path so that the other platforms that the web app supports does not break.
Your choices are:
Improve the Web app code, such that a local file path is one possible source of the data, or
Suffer the problems with making copies of that data
After all, bear in mind that the Uri you are given via ACTION_SEND does not have to be a content Uri. It could very easily be an http or https Uri.
Are there any custom open-source libraries that don't rely on the default MediaStore (so that I don't reinvent the wheel)? Or do I have to write my own scanner? The problem:-
I've created a music player in Android that can also create playlists from local files. The details about the local media is obtained from Android's MediaStore. Everything works fine until I relocate my music files. When a media file is moved, the ID field in its entry in the Android MediaStore gets changed. Obviously that means any attempts to get to the file using the stored (stale) ID's will fail. How do I get around this? Thanks!
You are able to manually refresh the content of the Media library.
Read this related post - I think you will find it useful!
I have some sensitive content data that I provide with my Android application and this data (almost say 1 gb of it) is stored on an SD Card. I want to prevent users from using this card in other places other than the tab itself and reading/copying content off it on a computer or another tablet. I've thought about encryption mechanisms but for the amount of data I have these are very slow and not an option. Are there any hardware settings I could change or file data formats I could use to achieve this? Basically when I remove the card and put into another device I should not be able to copy data from it unless say I have a Pin number or some security mechanism. Most of the content is either pdf files or mp4 videos and I need a sort of software/hardware DRM mechanism.
I haven't done anything of this sort, but THIS might be your best bet.
If you can't implement an online service for your content, you could try creating a proxy local service which will handle the DRM Info Requests for you.
On Android I understand an app can ingest an image file from the user's Downloads folder, and then use that image to direct content inside the app. Amazon MP3 Cloud Player is good example.
I understand that on iOS the Saved Photos folder can be accessed by apps as well, using the UIImagePickerController Class Reference. I understand that I can limit which media assets can be browsed, just video or just photos, but can I tell the app to only launch the media asset picker for the user ONLY if an exact-match to photo file extension is made in the first-place?
In other words: IF in the Saved Photos folder there is a .ONE or a .TWO file present, then launch the media browser, and only show .ONE or .TWO files, if not, do not launch the media browser.
I want to be able to use a custom file extension -not the standard PNG, JPG, etc...
Ultimately my goal is to use this custom image file as a kind of token that tells the app the user has done something in the browser to acquire the image file, and therefore is entitled to a special experience in the app.
What you want is not a UIImagePicker, because you need to enumerate user photos programmatically. Have a look at ALAssetsLibrary, with which you can enumerate ALAssets, which are proxy objects for saved photos (and videos).
Upon further reading: I don't think your custom extension idea would work. And it shouldn't, because you're exposing implementation details to the user by putting certain specialized files into a content library where they don't belong (which probably won't work). Do not misuse OS facilities like that. It will only get your app rejected from the app store (if it even works), create more headaches in implementation, and create very poor user experience. While this might not be enforced on Android, it is a bad idea even there, but on iOS, you won't even be able to release your app to the public.
See this question for how to declare your app to open specific document types (which means that when the user downloads a .yourSpecialFileType file in Safari, it will launch your app and hand the file over to you).
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.