android: How to remember file passed via ACTION VIEW intent - android

I have an android app that is able to open a certain file type via a VIEW intent.
After a file is opened using my app for the first time, I would like the app to "remember" the file so that the user can choose to open it again from a list of "recent" files inside the app...
My question is: what is the best way to implement this kind of "remembering" - should I:
Automatically copy any files passed to my app into my app's own storage area, and then list "recent/old" files there?
Or, should I record a list of files that my app has been passed previously, and access them via the same path later if necessary? If that is recommended, is there any guarantee that I will be able to access them again later? (I guess not!)
Option 1. seems like more work and doubles the storage space needed for all files passed to my app, but will guarantee the files will be accessible in future. Option 2. is easy if the files are always readable by my app in future, and are not renamed/deleted for some reason - it seems there's no guarantee of that though...
If it helps, I expect most files passed to my app to come from "Downloads" via the user's browser, but some might come from email/other apps etc.
Thanks

I would go with Option #3: drop the proposed feature.
As DeeV pointed out in a now-deleted answer, Option #1 is not a great solution for a "recent files" list. It would be the right option for other verbs than "remember", such as "import".
Option #2 will not work much of the time. Your app needs to support the content scheme, in addition to (or even instead of) the file scheme. By default, you will only have rights to access the content at a content Uri until your process terminates (at best). You may be able to takePersistableUriPermission() to get durable access, but that will not work much of the time — it depends upon whether the other app is granting you such access. Hence, you might have a Uri that you can remember, but remembering will do you little good.

Related

Shared Files - Can't find Solution for new Android 10 Scoped Storage restrictions?

We have a suite of applications that depend on the sharing of a directory/files on external storage.
I've currently opted out of the Android 10 OS changes to scoping (requestLegacyExternalStorage), but this is going away and I've spent many hours trying to find a solution for simply sharing files between applications.
The only solutions that I see offered are:
SAF - which appears to make the user choose through UI. This is completely undesirable.
Use a File Content Provider - the way I understand this, I would have to make the user install an apk with my provider in it before installing any of my applications. Forcing the user to install two apks to run one application is very undesirable. (Yes, they could both be in one apk manifest but who knows which of my suite they will want to install)
Media Store - My understanding is that this also forces the user to pick something he should have no knowledge of - and is really intended for audio, video, image and downloaded directory.
Am I missing a solution for these simple requirements?
Am I missing a solution for these simple requirements?
There is no simple solution. You would basically need to have each app have its own copy of the shared data (to deal with potential uninstalls) and have some sort of synchronization protocol so each app in the suite can inform others about changes to their copy of the data.
Using SAF is the simplest approach for your scenario. Or, move the data off the device into "the cloud".
My understanding is that this also forces the user to pick something he should have no knowledge of
It is the user's device. It is the user's storage. If you put files in a user-visible location on the user's storage, they are the user's files. Your apps are merely one set of tools for working with those files, nothing more.

Getting root directory contents

I have an app with data stored (by previous developer) in user-based directories: context.getDir(userLoginHash, Context.MODE_PRIVATE). And there is no users list - when user logs in app tries to load contents of his directory (or creates new one), when user logs out directory remains on the device.
And now I wan't to clean the data. So I need to get list of such folders, but didn't find method for that. It confused me a lot because task looks too obvious. Do I miss something? How can I do this?
So I need to get list of such folders, but didn't find method for that
There is nothing really built-in for that.
How can I do this?
Start with:
File motherOfAllUserDirectoriesAndOtherStuff = getDir("whatever", Context.MODE_PRIVATE).getParentFile();
You can iterate over all of the contents of motherOfAllUserDirectoriesAndOtherStuff using standard Java I/O (e.g., listFiles()). However, bear in mind that not everything in motherOfAllUserDirectoriesAndOtherStuff will be your user directories. SharedPreferences, databases, other files, etc. will also be in there. You will need to devise an algorithm that can determine whether a subdirectory of motherOfAllUserDirectoriesAndOtherStuff is one of your user directories or not, perhaps based on what a hash looks like.
If you can someday rewrite this, create your own root and put the user directories in there. IOW:
File userDir = new File(getDir("myAppRoot", Context.MODE_PRIVATE), userLoginHash);

updating static resource files in android

I am very new to Android development.
Suppose my application has a few static HTML files that I expect will need frequent updates. Suppose I do not want to publish a new version of my application every time a file changes, but I do want to keep these files up-to-date.
What I imagine I could do, is to write a piece of code within the app to go to a known URL and check for updates every few days. If the updated resources bundle is available, the code will download and unpack it, replacing old files, so that the user will see the most resent content.
Questions I have:
- is such approach a good/bad idea? In other words, are their specific disadvantages to doing update in such manner or is it a commoin practice?
- how can I implement something like that? Service? Is there an existing sample piece of code that I could reuse?
Thanks!
If the updated resources bundle is available, the code will download and unpack it, replacing old files, so that the user will see the most resent content.
This is fine, except for the "replacing old files" part. Resources are read-only and cannot be modified at runtime. However, you can adjust your code that uses these files to look for your downloaded-and-cached updated files first and use those, falling back to the resources if updates are not available.
how can I implement something like that?
If your app involves other data synchronization, and you are using something like SyncManager for that, just include these files as part of the synchronization work.
Otherwise, use AlarmManager to arrange to get control every so often to check for updates. You will probably need to use WakefulBroadcastReceiver or my WakefulIntentService to do the actual downloading, as the device will want to fall asleep right away otherwise, if the user is not using the device right then. Use HttpUrlConnection or your favorite HTTP wrapper library to download the files to getFilesDir() or getCacheDir().

How to extend app with downloadable APKs (plugin sort of)

I'm just wondering how the following scenario can be solved:
I want to write a very simple app for my daughter. The app displays 4 colored fields on the activity and through speech output says something like "tap green". She should then tap the green field to get positive feedback. So far, so easy.
I then thought it might be nice if the app would also "grow" as she grows older. Maybe later I want to have a game mode where I display animals, numbers, vehicles, etc., so it would be nice if I could have something like "Shape sets" - basically a set of images along with a description of what the app should say for each image. Also easy enough - all you need is a set of images and an XML file describing the images.
BUT
I'd like to be able to install these "Shape sets" as additional APKs later on, so that I don't have to modify the app every time. I'd like to install the APKs, so that the contents are added to a specific sub folder on the SD card, into which my app looks to enumerate available "Shape sets".
If I ever published the app to the Play Store, other people should also be able to download the "Shape sets" I create (no need for user contributions, though).
Is that possible? If so, what would I have to do to have the Android OS "copy" the contents of an APK to a specific folder (lets say "/TapGame/Shape Sets/Animals") on the SD card? Or is there even another way of achieving what I want that I didn't think of?
The term "plugin architecture" just came to my mind as I wrote the question. Searching using that term I found this question: Extend my android app in different APK
It seems to provide a solution to my problem - I'll investigate this further, but please feel free to suggest other possible solutions!
Is that possible?
Um, sure.
If so, what would I have to do to have the Android OS "copy" the contents of an APK to a specific folder (lets say "/TapGame/Shape Sets/Animals") on the SD card?
Android won't do any of that. You have to do that. You would have to detect that a "shape set" APK was installed (either watching for package-installed broadcasts, scanning all installed apps for ones that seem to be a "shape set", etc.). Then you would have to arrange to copy whatever you wanted to wherever you wanted it, either by:
Asking the "shape set" app to do it (e.g., send a command to some IntentService), or
Using createPackageContext() and trying to do the copying from your main app
Or is there even another way of achieving what I want that I didn't think of?
Um, just use ZIP files that your app downloads itself from a well-known location. That corresponds to Dave Smith's final paragraph of his answer on the question you just linked to in your edit.
Or, just update the main app. I'm not quite certain what effort you think that you are saving otherwise.
Or, just keep the content online, using a Web service to indicate the available "shape sets" and downloading them as needed (with optional caching).
Fascinating question. If you really want to go for plug-ins then OSGi would probably be the way to go, but it's a lot of work to get to know and to use and seems like overkill in this case.
I don't know how your shapes are defined, but they are probably each defined in a separate file-set, providing the shape (maybe a png or jpg?) as well as the audio-file that will be used as a command for this shape. If the folder in which these file-sets are stored is fixed (TapGame/Shape Sets/...) the app could scan the folder each startup and the views could be generated accordingly (in this case, the activity cannot be build entirely in the XML-File, but must be partially done programmatically).
The Plugin-Aps would be rather easy. They are an apk which includes the file sets (jpg and mp3 or whatever). Started once they deposit all these files into the specified folder (they probably check before if these files exist) and then the apk can shut down again and be uninstalled.
on the next startup the Tap Game App would find the new symbols and include them into the game.
This seems rather straight forward to me. Another way would be to actually store the shapes and audio files on the internet and with each start of the App check if the number of shapes and audio-files has changed and create local copies of new ones. This would mean no downloads of apks... probably a more usual approach to the issue.
I am very interested to hear what you make of it, seems like a different approach then the norm, which is always cool to see.

iOS equivalent to Android MODE_WORLD_READABLE

As the title says - is there something in iOS that lets you say 'this file is allowed to be accessed by other apps' - preferably only readable, but read/write would be good enough.
Basically I am trying to place a file outside the sandbox so other apps can read it - preferably via the openURL that points to a local file rather than an http address.
Thanks
Edit:
I just received an answer from Apple Tech support and they told me that this is currently impossible (just after iOS 6 released)
I don't think it's possible to do it the way you describe. Last I checked, apps can only write inside their sandbox dir and cannot read inside other apps' sandboxes (though IIRC there used to be a few other writable directories).
What, exactly, is the end result you are trying to achieve?
If you know the app you want to read the data, you can use a custom URL scheme.
If you have a file of a certain type (extension/content-type, I think), you can use UIDocumentInteractionController to let the user pick an app to open it in.
If you just want to share some data with any app, the closest I can think of is a custom UIPasteboard. OpenUDID does this for a slightly dubious purpose.

Categories

Resources