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
Related
I want my app to automatically load data from a file at startup & then display a summary of this data for the user. I thought this would be simple, but...
I almost had it working, but found out that it would be tricky putting the data file on the emulated Android provided by Android Studio. So I put a basic version of the file in the package as an asset. My code checked for the file, and if not found, copies the file from assets to the phone storage. So far so good, but then I realized that this didn't really meet the requirements, because the user couldn't customize the file (through another app or by putting a new version of the file on her phone).
I found I needed to use "external" storage (which isn't really external, it's merely shared / public storage). So I used getExternalStoragePublicDirectory() to get access to the Documents folder. In the part of my code which copies the asset file to the Documents folder, I get "java.io.IOException: No such file or directory" when I try to create the target file.
This really threw me for a while, since I had preceded it with mkdirs() to ensure the folder(s) existed and I was trying to create the file in the first place.
After lots of poking around on S/O, it seems my problem may be that I don't have permissions to read / write in the Documents folder. So this is where I can't get my head around how this is supposed to work.
In my Activity's OnCreate(), I want to load the data from my file. But I need to check the permissions first. This is guaranteed to fail the first time, because the user has never granted my app this permission before.
So then I need to request the permission. But this means I can no longer load my data in the OnCreate() method, as I will get the response from the user asynchronously, in a callback method (onRequestPermissionsResult).
If the user says 'No' to my request, I need to make sure the app quits gracefully. If she says 'Yes', then... what? At this point I'm in a callback and my OnCreate() method is no longer running. How can I get back to setting up my Activity?
If I load the data file in the callback method, that only works for the initial case where the user must give permission. But after that, my app (most likely) will not lose permission, so my app will not need to ask for it. The callback will never be executed in this case. So my data file must be loaded... where?
But all of this only happens if the user is running Android 6.0 or higher. If it's an earlier version of Android, then my app can load the data in my Activity's OnCreate() method.
Oh... my head hurts!
How is all of this supposed to work? I don't need a link to the relevant methods. I need a conceptual model - a diagram would really help!
Here's the solution in a diagram: Permissions Conceptual Diagram
How can I get back to setting up my Activity?
Move the "setting up my Activity" code that depends on file I/O to a separate method. In onCreate(), check to see if you have the permission, and if you do, call that method to set up your activity. If not, call requestPermissions(). In onRequestPermissionsResult(), if you now have the permission, call that method to set up your activity.
See this sample app, which performs disk I/O from external storage using runtime permissions. The permission-handling logic is isolated in an AbstractPermissionsActivity, leaving the main activity class to handle the real business logic.
If it's an earlier version of Android, then my app can load the data in my Activity's OnCreate() method.
Well, you should be doing this disk I/O on a background thread. You can kick off that I/O from onCreate().
If you are using ContextCompat and ActivityCompat for checking and requesting permissions, respectively, your code will "do the right thing" on older devices, as those classes do the version checks for you.
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.
At some point in my app, I have to save some temporary image files. I've tried using file.deleteOnExit(), after some research I found out it does not ensure the file will be actually deleted. So I tried to follow one of the alternatives listed on deleteOnExit() documentation that says:
• Maintain your own set of files to delete, and process it at an appropriate point in your application's lifecycle.
I am wondering, what is this appropriate point? I've tried to delete a set of files on application.onTerminate(), but the result is the same, if the app process is killed, it'll never reach onTerminate() method.
In order to keep performance and delete temporary files safely, when (where) should I place my code to delete them?
As soon as you are sure you won't use them, but no sooner.
More seriously, you should store them in the cache directory. You can get that with Context.getCacheDir(). That way if your cleanup methods don't end up getting called, the user can delete them from the Applications menu, or the system may delete them if space is required.
You can (and should) try to delete them in onDestroy() or even onPause(), depending on your implementation, but those are also not guaranteed to be called.
You might also put a timestamp in the filename, and run a cleanup periodically with AlarmManager and BroadcastReceiver by comparing the filename (which should reflect the last time that file was accessed, ideally) with the current time, and deleting it if the difference is greater than some constant. For performance sake I would probably run this daily or a couple times a day, and also (in a background thread) when the app opens or the relevant activity starts.
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
I want to determine whether my application being run for the first time, and so it will be hard to pass around it.
The preferences or empty file approaches are not going to work because you can simply clear the application data or delete the empty file.
Also I want to do it offline so no server checking is going to work either.
Maybe it's possible to add some code to the installation of the apk so it will only run once.
So my best bet is spawning a lot of empty files all around and hope the user won't find them, but this is pretty messy.
Has anyone ever done this somehow before? Any suggestions?
The preferences or empty file approaches are not going to work because you can simply clear the application data or delete the empty file.
One possibility is to have a BroadcastReceiver, registered in your manifest, that you do not actually use for anything. On first run of your app, disable that receiver via PackageManager and setComponentEnabledSetting(). On future runs, you can determine if that BroadcastReceiver is already disabled via PackageManager and getReceiverInfo().
If the user uninstalls and reinstalls the app, the app will return to its original state. Rooted device users can also get past this. Otherwise, this should be reasonably solid.
I know you said you dont want files, but if you create them as local internal storage then the user can not delete them as they wont have access unless it is rooted phone. Clearing data "may" delete them.
There is another solution but it is lengthy one. Use SQLite database.IT is local and I dont think it can be deleted otherwise the whole application will crash