File Modification check on Android - android

I have written a loop that checks the file modification date on two files.
This is successful as far as the Toast text is concerned.
However I cannot seem to work out the syntax to actually compare the dates, comparing Date1 > Date2 is actually rejected by android studio.
Lots of advice on how to get the most recent modification date is on Stack Overflow, just not the answer as to how to craft the necessary if statement.
Any help would be most appreciated. (yes I have read documentation! Usage examples poor on this subject)
Handler mHandler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Email sync loop (maybe change for watcher method)
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
Thread.sleep(10000);
mHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, "Loop", Toast.LENGTH_SHORT).show();
File file = new File(String.valueOf(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS + "/Database1.db")));
if (file.exists()) {
Date lastModified = new Date(file.lastModified());
String modified = lastModified.toString();
Toast.makeText(MainActivity.this, modified, Toast.LENGTH_LONG).show();
}
File file2 = new File(String.valueOf(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS + "/Database2.db")));
if (file2.exists()) {
Date lastModified2 = new Date(file2.lastModified());
String modified2 = lastModified2.toString();
Toast.makeText(MainActivity.this, modified2, Toast.LENGTH_LONG).show();
}
}
});
} catch (Exception e) {
// TODO: handle exception
}
}
}
}).start();
}

You don't need the separate thread, the loop and the sleep() call, you can simply schedule the check on the Handler instance using postDelayed() method. It will be executed on the main thread which is perfectly fine for you and won't block the app. As a final step in your Runnable instance you can schedule it again, so it will run in a loop.
If you want to stop it then call removeCallbacksAndMessages(null) on the handler.
I am not sure what do you want to achieve with this, but maybe instead of doing a polling loop you can use FileObserver class for monitoring file changes, here is an example how to use it.

For comparing two dates you can always compare their millisecond values.
For e.g. date1.getTime() > date2.getTime()
getTime() method returns the time in milliseconds and it is a long value that can be easily compared.

Related

Reading data from USB host every 200ms in android app

My USB Host is receiving sensor data and it is getting updated every 200ms. I would like to read this data in my android app every 200ms. I am able to read it using bufferreader, It reads the data for sometime and then hangs. It is not consistent. I am new to this and may be I am not doing it the correct way. Below please find my code and let me know your suggestions. Thanks in advance.
public void startProcessOne()
{
new CountDownTimer(110,100)
{
#Override
public void onTick(long millisUntilFinished)
{
StringBuilder text = new StringBuilder();
line = "";
try {
FileReader in = new FileReader("/mnt/udisk/TEST.TXT");
BufferedReader br = new BufferedReader(in);
int i=0;
char[] buf = new char[10000];
while((i = br.read(buf,i,100))!= -1)
{
String h = new String(buf);
text.append(h);
text.append('\n');
}
br.close();
}
catch (IOException e) {
//You'll need to add proper error handling here
}
TxtRead.setText(text.toString());
}
#Override
public void onFinish()
{
startProcessOne();
}
}.start();
}
TxtRead.setText(text.toString());
This line is causing the problem. You can't touch UI elements from a background thread. You should instead run those codes in the UI/Main thread.
In your case, I'd personally prefer using Java threads. So, create a background thread to keep running periodically. If you would need to run UI methods from that background thread. You probably need a handler attached to the main thread.
// Instantiate a handler in UI thread
final Handler handler = new Handler();
new Thread(new Runnable(){
// Once you're done and want to break the loop, just set this boolean
private boolean stopped = false;
#Override
public void run(){
while(!stopped) {
// Read from the file
// Whenever you need to update an UI element,
// you should wrap it inside this runnable object
handler.post(new Runnable(){
#Override
public void run(){
// Update UI
TxtRead.setText("new_text");
}
})
try {
// This thread will sleep for 9 seconds
Thread.Sleep(9000);
} catch(Exception e){}
}
}
}).start();

Android, if/else construct always fails (Compiler fails to read changes)

What i'm trying to do should be pretty simple, i'm calling an IntentService to check periodically in background if the current time is before or after a specified time (passed as Extras in the intent from the MainActivity) and get a notification when it happens.
In Thread's run() method i get an instance of the current time and use it as comparison to the previously specified one in an if/else construct, before re-running the Thread.
The problem is that it always go for "else" even if the current time is after the other one. This problem is just too strange, can anyone explain me where is the error?
Here is my IntentService class:
public class MyCheck extends IntentService {
int hour = 0; int minute = 0;
int i = 0;
private static final String TAG = "Check";
int hourNow;
int minuteNow;
Handler handler = new Handler();
public MyCheck() {
super(MyCheck.class.getName());
}
#Override
protected void onHandleIntent(Intent intent) {
Log.w(TAG, "Service Started!");
hour = intent.getIntExtra("hour", 0);
minute = intent.getIntExtra("minute", 0);
Log.w(TAG, "Step 1 ");
Thread runnable = new Thread() {
#Override
public void run() {
/* do what you need to do */
Log.w(TAG, "Step 2 ");
/* get current time */
Calendar c = Calendar.getInstance();
hourNow = c.get(Calendar.HOUR);
minuteNow = c.get(Calendar.MINUTE);
//HERE, IT SEEMS THAT IT'S ALWAYS BEFORE hour AND minute
if(hourNow > hour || (hourNow == hour && minuteNow > minute)) {
//SEND
Log.w(TAG, "RUN ");
Intent broadcast = new Intent();
broadcast.setAction(NOTIFICATION_SERVICE);
sendBroadcast(broadcast);
handler.removeCallbacks(this);
}
else {
//NOTHING
i++;
Log.w(TAG, "NOT YET " + i);
}
//REPEAT EVERY 6 SECONDS
try {
sleep(6000);
handler.post(this);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
runnable.start();
}
}
EDIT
I've found the trivial problem as you can see in my answer below.
If someone wants to complete the answer with some more information about the problems that can occur during the building process they will be apreciated. TIA
The simple solution to this was to wait and reboot Windows. The code wasn't flawed after all, it's just something on the building process that needed some time to tell the compiler that the error wasn't there: maybe there was a copy in cache of a past error that was still taken in account, i'm not sure.
Maybe you can add some information to my last statement, posting an answer or a commenting about it.

Android - How to avoid deadlock between the two runOnUIThread calls

I have this process which runs through some "if"s depending if a user insert or eject a memory pen drive:
int userStatus = StopActivity.USER_HAS_NEVER_INSERTED_MEMORY;
while (true) {
File usbDirectoryFile = new File(usbDirectory);
if (usbDirectoryFile.exists()) {
verMasInfoDirectory = usbDirectory + File.separator + "vermasinfo";
File verMasInfoDirectoryFile = new File(verMasInfoDirectory);
if (verMasInfoDirectoryFile.exists()) {
break;
} else if (userStatus != StopActivity.USER_HAS_BEEN_NOTIFIED) {
userStatus = StopActivity.USER_HAS_BEEN_NOTIFIED;
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(StopActivity.this, R.string.stop_activity_directory_not_exists_toast_text, Toast.LENGTH_LONG).show();
}
});
}
} else if (userStatus == StopActivity.USER_HAS_BEEN_NOTIFIED) {
userStatus = StopActivity.USER_HAS_NOT_BEEN_NOTIFIED;
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(StopActivity.this, R.string.stop_activity_ejected_memory_toast_text, Toast.LENGTH_LONG).show();
}
});
}
usbDirectoryFile = null;
}
The problem is that when the user insert/eject the pen drive fast, both calls to runOnUIThread can cause a deadlock.
How can I avoid that deadlock?
Thanks in advance.
These calls cannot cause a deadlock. First, they are run one at a time by the system. That is, one runs (on the event thread) to completion (until the run() method returns) before the other one is dequeued and run by the event thread. Second, the runnables are not locking resources, so there is no reason for a deadlock.
Perhaps you are concerned about two Toasts on the screen at the same time (since each Toast is on display for a time after show() returns). The only problem with this is that one will hide the other; however, there is still no deadlock.
If your app is deadlocking, the problem is elsewhere.

Not able to execute loop based on thread.sleep

I'm trying to display a series of images from a specific folder in sdcard - in the form of slideshow. filelist[] contains names of all files present in that directory.
I'm filtering out the images here. Next, thread.sleep(1000) does not seem to have any effect. Only the last image in the directory is displayed after a time of 1000ms. Where am I going wrong? Any other way I could accomplish this?
Maybe I've gone completely wrong. I'm a newbie so plz help.
public class List_imgActivity extends Activity {
/** Called when the activity is first created. */
Bitmap[] bitmapArray = new Bitmap[1000];
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button pf=(Button) findViewById(R.id.pick_button);
pf.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
Intent intent = new Intent("org.openintents.action.PICK_DIRECTORY");
intent.setData(Uri.parse("file:///sdcard"));
intent.putExtra("org.openintents.extra.TITLE", "Please select a folder");
intent.putExtra("org.openintents.extra.BUTTON_TEXT", "Use this folder");
startActivityForResult(intent, 1);
}
});
}
protected void onActivityResult(int requestCode, int recievecode, Intent intent)
{
if (requestCode == 1 )
{
Uri uri = intent.getData();
try {
File f=new File(new URI(uri.toString()));
final String nx=f.toString();
if(f.isDirectory()) {
File filelist[] = f.listFiles();
for(int i=0;i<filelist.length;i++)
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String filename = filelist[i].getName();
int pos = filename.lastIndexOf(".");
String ext = filename.substring(pos);
if(ext.equals(".jpg"))
{
TextView tv1= (TextView) findViewById(R.id.textView1);
tv1.setText(filelist[i].toString());
ImageView iv1=(ImageView) findViewById(R.id.imageView1);
bitmapArray[i] = BitmapFactory.decodeFile(filelist[i].toString());
iv1.setImageBitmap(bitmapArray[i]);
}
}
}
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
In Android behaviour like this will make the UI-Thread sleep. This will freeze the whole UI of the phone your App will look crashed to the user and the System will automatically kill your application after a while.
There is a mechanism to change things in specific time intervalls. You should use this handlers for doing this. Handlers
A handler has a postDelayed and sendMessageDelayed methods that allow you to either build a Runnable that will be executed after a certain time or send a message that must be handled by the implementation of your handler.
The initialization of the handler would look something like this:
showNextImageHandler = new Handler() {
#Override
public void handleMessage(android.os.Message msg) {
showNextImage();
}
};
showNextImageHandler.sendMessageDelayed(showNextImageHandler.obtainMessage(), 1000);
This code creates a new handler that calls the function showNextImage every time it receives a message. I would store the Handler in an instance variable of your activity to send further messages later on. After the handler is created a first empty message is send in a way that will delay the posting of the message 1000 milliseconds. After a second the showNextImage function will be called. In this function you can change the view and if a next image exists you can post another delayed message to trigger another call to the function later on.
U Must synchronise the current object before applying Thread.sleep() method

Android alarmmanager synchronized

I am referring to http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/AlarmService_Service.html
There the runnable of the thread looks like this
Runnable mTask = new Runnable()
{
public void run()
{
Log.v("service", "thread is running after 5 min");
// Normally we would do some work here... for our sample, we will
// just sleep for 30 seconds.
long endTime = System.currentTimeMillis() + 15*1000;
while (System.currentTimeMillis() < endTime)
{
synchronized (mBinder)
{
try
{
mBinder.wait(endTime - System.currentTimeMillis());
}
catch (Exception e)
{
}
}
} // Done with our work... stop the service!
AlarmService_Service.this.stopSelf();
}
}
I admit that I have some problems with the concept of synchronized... The thread runs the while loop to wait 15s, within that loop I have wait for 15s. So how would the runnable look like if I just want to write a log entry e.g. Log.v(TAG,TEXT);? What would change if I want to write a new entry into my own database table?
Thanks, A.
If you just want a log statement then the following will work fine
Runnable mTask = new Runnable()
{
public void run()
{
Log.v("TAG", "Some verbose log message");
}
}
Whether you need to use synchronized on an object depends on whether object is thread-safe or not. If it is not thread-safe, then you will need to ensure that only one thread access the object at a time by using a synchronized block. In your example mBinder is not thread-safe, so in order to call the wait method of the binder you need to ensure that you are the only thread accessing it.
A runnable is most often used to execute code in a different thread, so that long running operations (such as IO, but in this case just waiting) do not block the UI thread.
Simply replace
try
{
mBinder.wait(endTime - System.currentTimeMillis());
}
catch (Exception e)
{
}
...with the code you want to execute?
Synchronized is just to assert that only one process accesses the thread at one time.

Categories

Resources