I need to read all files in a directory every say 5 minutes and check if any new files have been created.
What would be the best way to do this?
I thought of using a DB to store all file names and then compare one by one but it seems like it would take too long.
I also thought of writing the file names to a text file and the looking if the file name is on the list or not.
Is there a better way?
Why don't you try with FileObservers
private final class DirectoryObserver extends FileObserver {
private DirectoryObserver(String path, int mask) {
super(path, mask);
}
#Override
public void onEvent(int event, String pathString) {
event &= FileObserver.ALL_EVENTS;
switch (event) {
case FileObserver.DELETE_SELF:
//do stuff
break;
case FileObserver.CREATE:
case FileObserver.DELETE:
//do stuff
break;
}
}
}
Ref:FileObserver CREATE or DELETE received only for files
Related
In Android I use the FileObserver to observe a folder and do something when a new file is created.
I noticed that the CREATE event is generated on Android 5 and Android 7 but it is NOT generated on Android 8. Any idea why?
This is the pseudocode.
public class FolderObserver extends FileObserver {
String path;
static final int mask = (FileObserver.CREATE);
public FolderObserver(String path) {
super(path,mask);
this.path = path;
}
void doSomeAction(string file){}
#Override
public void onEvent(int i, #Nullable String s) {
switch (i) {
case FileObserver.CREATE:
// this event is generated on Android 5 and 7
// but is NOT generated on Android 8
doSomeAction(s);
break;
default:
break;
}
}
}
....
/*
in my client
*/
FolderObserver observer = new FolderObserver(myPath);
observer.startWatching();
Finally I found a workaround.
Copying a new file into the observed folder generates the CREATE event on Android 5 and 7 while it generates the MOVE_TO event on Android 8, strange but ok.
So I simply listen for both events like that
static final int mask = (FileObserver.CREATE | FileObserver.MOVED_TO);
....
public void onEvent(int i, #Nullable String s) {
switch (i) {
case FileObserver.CREATE:
case FileObserver.MOVED_TO:
doSomeAction(s);
break;
default:
break;
}
}
I want to mount .obb file from external storage. I wrote these codes.
storageManager.mountObb(obbPath, key, new OnObbStateChangeListener() {
#Override
public void onObbStateChange(String path, int state) {
switch (state) {
case ERROR_ALREADY_MOUNTED:
storageManager.unmountObb(rawPath, true, this);
break;
case UNMOUNTED:
storageManager.mountObb(rawPath, key, this);
break;
case MOUNTED:
File mountedDir = new File(storageManager.getMountedObbPath(path));
// do something with mountedDir
break;
case ERROR_COULD_NOT_MOUNT:
case ERROR_INTERNAL:
case ERROR_PERMISSION_DENIED:
// Error occurred!!
break;
}
}
});
Now I execute this, my OnObbStateChangeListener gets state = ERROR_INTERNAL (20).
What is this error code? How to fix this?
Addition: I found this post: What causes jobb tool to throw FAT Full IOException?
Probably this is an answer. My obb file is broken.
thank you.
It looks like this constant is set in the MountService class (package com.android.server). You can take a look at the source code here : http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/com/android/server/MountService.java but as you can see, there are various reasons for setting the state at ERROR_INTERNAL
I have an application about pmt function. However there are so many conditions that need to be handled. Somehow the app will not work with having more than 12 if-else. I want to use switch case, but i still not really understand how to use switch case(been 1 and half month since my 1st try using eclipse).Any example will be highly appreciated.
here is my example code:
if(String1.toString().equals("condition1")){
//do something
if(String2.toString().equals("condition1.1")&& String3.toString().equals("condition1.2")){
//do something else
}
.
.
.
.
.
if(String2.toString().equals("condition1.##")&& String3.toString().equals("condition1.##")){
//do something else
}
}
else if(String1.toString().equals("condition2")){
//do something
if(String2.toString().equals("condition2.1")&& String3.toString().equals("condition2.2")){
//do something else
}
.
.
.
.
.
if(String2.toString().equals("condition2.##")&& String3.toString().equals("condition2.##")){
//do something else
}
}
if(String1.toString().equals("condition3")){
//do something
if(String2.toString().equals("condition3.1")&& String3.toString().equals("condition3.2")){
//do something else
}
.
.
.
.
.
if(String2.toString().equals("condition3.##")&& String3.toString().equals("condition3.##")){
//do something else
}
}
and still keep going....to handle all possibilities .I am wondering, How to do this in switch case . Or a better implementation if we have 3 times 3 conditions. For example a,b,c(suppose these three conditions can only be used once) and d,e,f and g,h,i then condition 1 is a,d,g ; condition 2 is a,d,h condition 3 is a,d,i ; condition 4 a,e,g........on so on
Note:Suppose that the API version is 8-11 (old android)
thanks
The answer is dependent on your target version of android. From KitKat and upwards (API Level 19+), Java 7's switch (String) is available. I'd also strongly suggest trying to group the subcases (condition n.x) into different methods. It just gets very unwieldly quickly, otherwise:
switch (String1.toString) {
case "condition1":
handleCase1(String2, String3);
break;
case "condition2":
handleCase2(String2, String3);
break;
}
If that still results in too complex code, you can try a lookup table together with a command pattern:
class ConditionKey {
final String String1;
final String String2;
final String String3;
public int hashCode(); // hash strings
public boolean equals(); // compare strings
}
interface ConditionCommand {
// use whatever arguments the operation needs, you can also
// add fields and initialize in the constructor
void perform(final ConditionKey key, /* [...] */);
}
Map<ConditionKey, ConditionCommand> actionMap = new HashMap<>();
actionMap.put(
new ConditionKey("condition1", "condition1.1", "condition1.2"),
new ConditionCommand() {
void perform(final ConditionKey key) {
// perform actions that need to be done
}
}
);
And then instead of the if-else or switch-case:
[...]
ConditionKey key = new ConditionKey(string1, string2, string3);
// get the action from the map
ConditionCommand command = actionMap.get(key);
// perform the command
command.perform(key);
since java 1.7 switch on string is supported.
you could annidate two switch:
switch(String1) {
case "condition1": {
switch(String2) {
case "condition1.1":
break;
// ... other cases
default:
break;
}
}
break;
// ... other cases
default break;
}
Hi I am fairly an amateur at android so I might not be realizing something obvious.
I have a method that populates a global File Array variable with a list of flies in a specific directory. Problem is everything works fine if the directory has been made before by using my app to save a file there however when the user hasn't done that an error message is suppose to pop up saying they haven't saved a file yet.
I do a check if the directory exist but the app crashes when the directory has not been created.
This is what my code looks like any assistance would be appreciated
private void getTemplates()
{
//Gets file directory for saved templates
File finalMarkTemplateDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Final Mark Templates");
//Checks if path exists in other word if any templates have been saved before
if(finalMarkTemplateDir.exists())
{
templatePaths = finalMarkTemplateDir.listFiles();
}
else
{
Toast.makeText(this, "No previous templates have been saved.", Toast.LENGTH_LONG).show();
setResult(RESULT_CANCELED);
finish();
}
}
I am too an amateur, you have not created a file in your code, calling a new file() method does not create a file. Pls check that out
try {
finalMarkTemplateDir.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I managed to solve my problem when I call the setResult and finish methods I did not realize the flow of the program is returned to my onCreate method which meant the rest of my method calls in onCreate was still being called and they require the templatePaths array.
So basically I thought finish would stop the processing and move back to the calling class(using startActivityForResult). Instead I now call finish from my onCreate and use a boolean to determine if I could successfully access the directory.
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//setContentView(R.layout.dialog_load_template);
boolean fileLoadStatus = getTemplates();
if(fileLoadStatus)
{
populateTemplateList(templatePaths);
}
else
{
setResult(RESULT_CANCELED);
finish();
}
}
private boolean getTemplates()
{
boolean fileLoadStatus = false;
//Gets file directory for saved templates
File finalMarkTemplateDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Final Mark Templates");
//Checks if path exists in other word if any templates have been saved before
if(finalMarkTemplateDir.isDirectory())
{
templatePaths = finalMarkTemplateDir.listFiles();
fileLoadStatus = true;
}
else
{
Toast.makeText(this, "No previous templates have been saved.", Toast.LENGTH_LONG).show();
}
return fileLoadStatus;
}
Is there any way to detect when a file is created or modified or downloaded in the android phone? I checked the available intents, but none of them are related to files. I am working on the broadcast receiver and couldnt figure out a way to detect a new file creation. Can someone please help?
use FileObserver...
public class MyFileObserver extends FileObserver {
public MyFileObserver(String path) {
super(path);
}
#Override
public void onEvent(int event, String path) {
switch (event) {
case DELETE:
// file deleted
break;
case ACCESS:
// file accessed;
break;
case MODIFY:
// file modified;
break;
case OPEN:
// file opened
break;
// see documentation for available events
default:
break;
}
}
}
sample usage:
MyFileObserver fileObserver = new MyFileObserver(Environment.getExternalStorageDirectory().getPath());
fileObserver.startWatching();