How to get notified of updates on the Android filesystem? - android

Specifically I am looking for a way to update the current view of my app (which displays media files) based on whether new files are added or deleted in the background, or when the app is in a paused state.
The only way I know of is the query the MediaStore and check the count of the returned tuples, and recreate the whole view if counts are different. Ofcourse this has certain caveats.
Is there a way so that I can establish a call-back when certain type of files are written or removed from a certain directory ?
TIA

On Linux, people use inotify to achieve this goal,
And in Android, we can use FileObserver:
See the ref here:
http://www.roman10.net/android-fileobserverthe-underlying-inotify-mechanism-and-an-example/
Android file system hooks

Related

Is there any way to force a system media rescan before querying `MediaStore.Audio.Media.EXTERNAL_CONTENT_URI`?

I would like to know if there is any way to force Android to update its media table before querying MediaStore.Audio.Media.EXTERNAL_CONTENT_URI.
There is a flow where the user can insert or delete songs media from his device through USB, and after that the media table doesn't update by itself.
Maybe this is not the answer you are looking for, but it is easier to monitor those changes instead of somehow forcing the update of the MediaStore, you can even apply this approach for when it detects changes to make your query again.
You need FileObserver to monitoring file changes, but first your need setup it, let me explain.
You need to create a BroadcastReceiver, which tells you when the device starts. Why? Because you need to know when the device starts to start monitoring changes to your files.
Then you need create one service that observe changes, the class that can help you are FileObserver, SingleFileObserver.
But that is general, you can see the solution in this answer in similar question.
How to monitor folder for file changes in background?

How can I get notification of any file being deleted from SD card

I want to create Dumpster like app, for this I want notification when user is deleting any file so that I can save it to my app memory.
I used File Observer but it is giving notification after file deletion and in marshmallow it does not notify for deletion also.
I referred this link for file observer.
Somewhere I read it is possible using native programming language (C), but couldn't get any solution. How can I do this?
Thanks in advance.
I have tried this:
#Override
public void onEvent(int event, String path) {
if (path == null) {
return;
}
//the monitored file or directory was deleted, monitoring effectively stops
if ((FileObserver.DELETE_SELF & event)!=0) {
FileAccessLogStatic.accessLogMsg += absolutePath + "/" + " is deleted\n";
}
}
Lets clarify the things First.
Dumpster Uses .trash directory which may and may not be present always. This should be noted that Dumpster does not run correctly in many devices as it can be seen through google reviews.
Dumpster uses (i guessed it from the code for educational purpose only) it's own System File Handler that uses a service to check for the onClick event and if its a file onClick it saves the File as well as its path to a separate folder (usually hidden) and also saves it in a database that is local. If it is deleted you know where the file is and if not lets delete that file from that hidden folder. Well that's kinda not worth the pain because you need to almost make your service run for almost all the time which uses CPU resources. It also runs on rooted devices but why root device for this purpose only.
As the Security in devices are increasing it is becoming less possible to perform these tasks. As latest of 1-09-2017 all these of files recycle bin have Negative reviews on latest android versions. Hence, proving my point.
FileObserver uses the concept for checking any changes on the file or even directories but you cannot influence it meaning you cannot prevent deletion it will notify everything after the user has deleted.
inotify.h it is the used for NDK purposes for creating application using to check the events on folders and files but if the folder is mentioned the sub sub folder will not be covered in this or notify you any change for the file. Moreover the concept used in inotify is same as FileObserver. you can only receive the notification after the file is deleted.
The code used in the inotify is something like this.
Create the inotify instance by inotify_init().
Add all the directories to be monitored to the inotify list using inotify_add_watch() function.
To determine the events occurred, do the read() on the inotify instance. This read will get blocked till the change event occurs. It
is recommended to perform selective read on this inotify instance
using select() call.
Read returns list of events occurred on the monitored directories. Based on the return value of read(), we will know exactly what kind of
changes occurred.
In case of removing the watch on directories / files, call inotify_rm_watch().
The two methods present in inotify is as follow:
IN_DELETE – File/directory deleted from watched directory
IN_DELETE_SELF – Watched file/directory was itself deleted
both of which are almost same as in FileObserver
This Solution can be of help not fully but still can help in creating any Dumpster type Application.
It can be said that you need to create your own File Manager where you can Create your own Custom FileV2(Just a cool name File version 2.0) class that extends File and you can override the delete method (and all others) as you like. You can create a custom pop up saying do you want to delete the file with your own backing up the file on yes and dismissing the pop up on no. (Make Sure User uses this File Manager to Delete otherwise it will not work because overriding the system File delete() will just mess up other applications as well).
class filev2 extends File {
public filev2(#NonNull String pathname) {
super(pathname);
}
public filev2(#NonNull URI uri) {
super(uri);
}
#Override
public boolean delete() {
// return super.delete();
//Do as you want and return the boolean.
}
}
But make sure your files will be saved if the user uses your File Manager for this.
You can set the intent-filters for the task so that your FileManager comes in ACTION_VIEW for that matter.
Last but I am not sure about this maybe registerContentObserver can be used also. (Not Sure though)
Sources:
Inotify.h help website
registerContentObserver help
Kind of Similar Question
FileObserver Help
Linux Help Deleted Log for Files
I hope it helps and I hope you can now have a start to what you want.

Design for downloading files before starting of an Activity

I have a use case where I want to download some files from the server and store them locally before starting another activity that is dependent on this file. This kind of design can be found on karaoke kind of applications where clicking on one song would
Load the required files from the server
Once the download is finished, open the required activity.
Let us assume that my app is a karaoke app. My question is how to design this flow. Basically, on clicking on one song, I want to show progress on the screen and when the download is finished, I want to move to the activity. Another requirement is that once I am inside the karaoke activity screen and playing a song, I have an option which leads to loading of another lesson. If a user uses that option, I want to again download the required files. Based on this requirement, should I:
Have the file loading thing as a separate activity?
OR
It can be used as Fragmentinside the activity where I choose a particular song. In this case, once entering the karaoke screen, if I choose an option which leads to downloading some files and reloading of this activity, is this the best design?
I would recommend two different approaches depending on how long you plan on keeping the data that you've downloaded. If it is single use than a bound service would be ideal. However, if you are planning on keeping the downloaded content for more than a single use, I would recommend you use a content provider and possibly a sync adapter(Depending on how frequent/predictable content downloading is). This combo would help guide you into not having to think about the 'design' as much(Since it is pretty standard at this point), plus it would provide a lot of features that you may/may not find useful: you can make your internal data 'public' via the content provider/authority(s), you can make an 'account' on the phone associated with your app so that the user can manage its syncing via the sync manager(actually via widgets/apps using the sync manager, but still), and most importantly a set of clean(ish)/standard means to interact with it/propagate UI, etc.
My simple version would be an Activity that spawns either a async-AIDL service with callback (which is in my opinion the only way to use a bound service) that would allow you to asynchronously design your 'starter' activity, its "currently downloading" spinner (which can get progress updates via the callback if you design it that way). Then once the download is complete then send the results (via a parcel file descriptor in the Intent's bundle) to the new activity that makes use of it.
However, if you are planning on using the data more than once, I'd recommend downloading the content like you did above, but then also store it in a content provider for easy access later. Providers also have a lot of nice associated functionality related to cursor loaders, etc. that will help keep a list of the content currently being stored nice and clean/up-to-date/dynamic/etc. However, this is a lot more work to setup once, then later it would save you time in reduced.
A sync adapter is best when the data to be downloaded is predictable, either based on user's account or temporally (such as someone having an account to download data from (email account, etc.) or when the target is fairly constant, but the data should be updated every hour or so(such as the current weather)). So this will depend a lot on your application's exact specifics.
Here is an assignment for an Android App Development course I wrote that is an even more simplified version of the first option (it has intent service + broadcast receiver for returning download results back to the Activity). Obviously since this is an assignment it has sections cut out to make skeleton code, but the documentation is ABSURDLY detailed and should be fairly easily implemented.
https://gitlab.com/vandy-aad-3/aad-3-assg-2/tree/master
Here is the extension of that assignment for that same course that focuses on implementing a simple content provider's 4 main methods (Create, Read, Update, & Delete). Everything else about the provider is given to you.
https://gitlab.com/vandy-aad-3/aad-3-assg-3/tree/master
Obviously the content being downloaded in both applications is probably not what you intended, but that is a simple swap to replace in what you do want.
Not to shill to hard, but here is the (free) Specialization that this course is a part of: https://www.coursera.org/learn/androidapps
Point one : Don't download video file within the Activity level. You can start a Service to handle it. Once the download function is finished you can start the second Activity. While download function is in progress you can show a ProgressBar
Point Two : Best Design is show a ProgressBar with percentage to user. Or disable the function. After download complete enable or start the second activity.

Handle android expansion file (OBB) removal during gameplay

Accordingly to http://developer.android.com/google/play/expansion-files.html,
The main activity in your application (the one started by your launcher icon) is responsible for verifying whether the expansion files are already on the device and initiating the download if they are not.
And they really check existance of OBB in onCreate method of main activity.
I wonder how do I handle situation when OBB is present at application launch, but afterwards, during gameplay, user erases it and returns to the app. And do I need to take care at all?
I've only started with android development, but ...
You should be able to implement a http://developer.android.com/reference/android/os/FileObserver.html to watch for deletion or movement.
However as Kai stated, most people don't delete things they don't know about. So I wouldn't worry about it.
This might be as simple as checking if the file exists, you could easily do a File mFile = new File(pathToFile); then do a check if (!f.Exists()) { //do something }. You could do this every time content is accessed.
Another option is to use getSystemService(STORAGE_SERVICE); and pass commands to see if the OBB is mounted or not. StorageManager android

Implementing a robust persistent undo/redo feature

I'm writing a bitmap editor where I use the Command Pattern to represent actions that will transform the document. I keep all the commands executed so far in a list and, to implement undo, I restore the document to its initial state and then replay all but the last command.
I would like my undo/redo system to have the following feature: When the user closes the editor and returns, the document, including the available undo and redo commands, should be restored to the state it was in when the user left.
I'm implementing this for Android where your application can be given very little notice before it will be cleared from memory if e.g. the user gets a phone call. Also, some of my commands are e.g. a list of all the x,y co-ord the user painted on so these might take a few moments to save to disk.
My current idea is as follows:
When a new action is performed, the command object is added to a list S for commands that need to be saved to disk.
A background thread is used that will continually take commands from list S and save them to disk. The postfix of the filenames used will be numbered in sequence. For example, if the user filled the screen then drew 2 circles, the command files might be called FillCommand1.cmd, DrawCircleCommand2.cmd, DrawCircleCommand3.cmd.
Periodically, we save a "checkpoint" command whose purpose is to store the full document state so that, even if one of the .cmd files is corrupted, we can restore a recent version of the document.
When the user exits the app, the background thread attempts to finish up saving all the commands it can (but it might get killed).
On startup, we look for the most recent .cmd file that represents a checkpoint that we can load successfully. All the .cmd files we can load after this (i.e. some files might be corrupt) go in the redo command list, all the .cmd files we can load between the first checkpoint loaded and the oldest checkpoint we can load go in the undo list.
I want the undo limit to be about 20 or 30 commands back so I need extra logic for discarding commands, deleting .cmd files and I've got to worry about multi-threading behaviour. This system seems pretty complex and will need a lot of testing to make sure it doesn't go wrong.
Is there anything in Java or Android than can help make this easier? Am I reinventing the wheel anywhere? Maybe a database would be better?
Rather than reverting to the original then performing all actions, consider making Commands reversible. That way, if you ever decide to increase the size of your undo history, you won't be introducing the potential for lag while undoing. Alternatively, as Jared Updike notes, your application may benefit from caching render results in the near past and future.
I think you're overcomplicating things with your filesystem-based solution. If you want to maintain a backup of the entire history of current working document, you should just keep an unbuffered log open in append mode, and log actions to it. The log should be associated with the particular instance of the application and file being edited, so you don't have to worry about another thread stepping on your toes. Loading from that log should be very similar to loading from an ordinary save file. Just discarding the last-read action whenever you encounter an undo action.
Well, your code is probably imperative in nature, where the state of the application is modified in place by the user's actions. This is probably fast and straightforward. Undo is basically time-travel and if you clobber old states by modifying state in place you will have to store either recipes to recompute it in reverse, or a history that can recompute it forwards.
Like you said, you can store the actions and the initial state and play them forward (stopping at the new point in history the user selects) but that means undoing one action can cause n actions to replay. One approach is to store saved state copies in the history list so you can immediately jump to a given state. To avoid using too much RAM/storage you if your system is clever it can detect the nearest (non-null) saved state in the history and recompute those few stpes forward (assuming you have all the actions you need -- this assumes actions are small and state is large(r)) until the correct state is reached. In this manner you can start eliminating old saved states (delete or set to null) (drop the state based on a cost function inversely linear to how far back in time the state is), making undo fast for the recent past, and memory/storage efficient for ancient history. I've had success with this method.

Categories

Resources