I am doing an app where I click the START button and get current time, and hitting STOP gets the time again. I´ve been using system time without any errors, recently I changed it to server time, which is in an Asynctask, but the app is unstable since, slowed down and exits without error messages, but on faster connections it can process. Any idea why? This is my code:
class getDST2 extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... arg0) {
try {
TimeTCPClient client = new TimeTCPClient();
try {
client.setDefaultTimeout(60000);
client.connect("time.nist.gov");
simpledate = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
do_casu = simpledate.format(client.getDate());
} finally {
client.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Void result) {
getDSTdone = true;
}
}
Also doing a graphic timer of the current time since Start was clicked so I need to get server time every second inside a handler.. code:
handler.post(r = new Runnable() {
public void run() {
hasStartedtt2 = true;
calendar = Calendar.getInstance();
simpledate = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
new getDST2().execute(); // THIS IS THE ASynctask, returns the "do_casu" String
zaciatok_hour = zaciatok.substring(11, 13);
zaciatok_minute = zaciatok.substring(14, 16);
koniec_hour = do_casu.substring(11, 13);
koniec_minute = do_casu.substring(14, 16);
zaciatok_sekundy = zaciatok.substring(17, 19);
koniec_sekundy = do_casu.substring(17, 19);
final_hour = ((Integer.parseInt(koniec_hour) - Integer.parseInt(zaciatok_hour)));
final_minute = Integer.parseInt(koniec_minute) - Integer.parseInt(zaciatok_minute);
final_seconds = Integer.parseInt(koniec_sekundy) - Integer.parseInt(zaciatok_sekundy) - 1;
}
});
Handler is called every second.
ServerTimeThread sth = new ServerTimeThread();
sth.start();
from_time = simpledate.format(sth.time);
when you call 'sth.time',the thread just start and is still in progress.
'time' is remain uninitialized,it is init at end of thread
So when accessing 'time',it is null absolutely.
2 way for AsyncTask
Blocking operation:
public class NTPDateTask extends AsyncTask<Void,Void,Date> {
#Override
protected Date doInBackground(Void... voids) {
Date date=fetchYourDate();
//fetch your date here
return date;
}
}
then call
Date result = new NTPDateTask().execute().get();
Non-Blocking operation(Callback pattern):
public class NTPDateTask extends AsyncTask<Void,Void,Date> {
#Override
protected Date doInBackground(Void... voids) {
Date date = fetchYourDate();
//fetch your date here
return date;
}
#Override
protected void onPostExecute(Date date) {
//this is 'callback'
//do the thing you want when task finish
//onPostExecute is called when doInBackground finished,and it runs on UIThread
}
}
then
new NTPDateTask().execute();
EDIT:
class TCPTimeDisplayWorker implements Runnable {
static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");
boolean isActive = true;
private Handler targetHandler;
public TCPTimeDisplayWorker(Handler targetHandler) {
//pass the handler ref here
this.targetHandler = targetHandler;
}
#Override
public void run() {
while (isActive) {
long startTime = System.currentTimeMillis();
Date date = fetchDateFromTCPClient();
//fetch Server Date here
String currentDateText = simpleDateFormat.format(date);
targetHandler.sendMessage(Message.obtain(targetHandler, 0, currentDateText));
long endTime = System.currentTimeMillis();
long lapse = endTime - startTime;
if (lapse < 1000) {
try {
Thread.sleep(1000 - lapse);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Handler:
// Non-static inner class will hold outer-class reference,may risk in memory leak
static class MainHandler extends Handler {
private WeakReference<TextView> textViewWeakReference;
// declare as WeakRef to avoid memory leak
public MainHandler(Looper looper, WeakReference<TextView> textViewWeakReference) {
super(looper);
this.textViewWeakReference = textViewWeakReference;
}
#Override
public void handleMessage(Message msg) {
if (textViewWeakReference.get() != null) {
//handle the message from message queue here
String text = (String) msg.obj;
textViewWeakReference.get().setText(text);
}
}
}
then
// must use the same handler to send msg from Background thread and
// handle at Main Thread
// a handler create on a thread will bound to that thread
mainHandler = new MainHandler(Looper.getMainLooper(), new WeakReference<>(mTextViewSystemTime));
new Thread(new TCPTimeDisplayWorker(mainHandler)).start();
btw,CamelCase is the common naming convention in Java.
Hope these are helpful.
Related
I am making an app where i have a url with date.I need to check if the url has data and if it had data then add date to list.I have made a method which i have posted below and it is being call on main thread.But the problem is it takes few seconds to start the app.I need to optimise the app.Is there any other way to "REDUCE THE LOADING TIME".
Code
private List<String> getDateList(int counter, String date) {
String urlth = "https://www.example.com/json/" + date.trim().replaceAll("/", "") + "-12.json";
if (validateUrl.exists(urlth)) {
dateList.add(date);
} else {
date = givePreviousDate(date);
return getDateList(counter, date);
}
if (dateList.size() == 7) {
return dateList;
} else {
date = givePreviousDate(date); //gives previous date
return getDateList(++counter, (date));
}
}
You can use a handler to call your method in background, something like this
Handler handler = new Handler();
ListView<String> myList = new ArrayList<>();
handler.post(new Runnable() {
#Override
public void run() {
//call your method here
myList = getDateList(2, "date"); //with int and date data
}
});
Hope this will help!
I have two datepickers in my activity.
I want startdate of datePickerB dialog to be updated automatically based on date selected in datePickerA dialog.
I use setMinDate for datePickerB. setMinDate works fine for the very first time. But couldn't update or reset the mindate of datePickerB for consecutive updates in datePickerA. Kindly help.
Searched for all possible solutions but of no use. Kindly help
Below is my code. The code used in oncreate gets executed , but further setMinDate function called in HandleResponse ( this is the function that gets called once datepickerA is set )
//On OnCreate
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_YEAR, 1);
Date tomorrow = calendar.getTime();
long t = tomorrow.getTime();
fromDatePicker.getDatePicker().setMinDate(t);
//
toDatePicker.getDatePicker().setMinDate(t);
public void HandleResponse(Response response)
{
String sqlRes = "";
try {
String sResJson = response.body().string();
JSONObject jReader = new JSONObject(sResJson);
JSONObject jRes = jReader.getJSONObject("Result");
sqlRes = jRes.getString("res");
final int sqlMilkQty = jRes.getInt("qty");
String enddate = jRes.getString("date");
Date d = null;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
d = sdf.parse(enddate);
} catch (ParseException e) {
e.printStackTrace();
}
if (d != null && fromDate!= null) {
long t = d.getTime();
long t1 = fromDate.getTime();
toDatePicker.getDatePicker().setMinDate(t1);
toDatePicker.getDatePicker().setMaxDate(t);
}
Handler mainHandler = new Handler(Looper.getMainLooper());
if (sqlRes.equals("PASS"))
{
mainHandler.post(new Runnable() {
#Override
public void run() {
milkQuantity = sqlMilkQty;
txtMilkQuantity.setText(String.valueOf(milkQuantity));
}
});
}
else {
}
} catch (IOException e) {
DisplayError();
}
catch (JSONException e) {
DisplayError();
}
}
I have the array of objects that look like this:
public class Time {
public String start_time;
public String finish_time;
public Time(String start_time, String finish_time) {
this.start_time = start_time;
this.finish_time = finish_time;
}
}
I need to implement a timer in my Fragment in the following way:
it should start counting down from the first element in array in a way that on one single Time element it should first start counting down to the time left to reach start_time, then when the timer reaches start_time, it should start counting down to finish_time and, eventually, when it reaches finish_time it should do the same previous actions for the next element in the array. And when the whole array is finished, it should display 00:00:00.
PS: start_time and finish_time are formatted like this: HH:mm however the timer should be HH:mm:ss
Can anybody help with implementing that or at least give an idea?
Finally, found the appropriate answer. Thanks a lot to the guy who helped me with it:
class Clazz {
private Timer dateTimer;
private Timer remainderTimer;
private Date nextDate;
private boolean remainderTimerStarted;
private static final long REMINDER_UPDATE_INTERVAL = 1000;
private static final String[] DATES = { "12.04.2015 22:21", "12.04.2015 22:22", "12.04.2015 22:23" };
private int currentIndex;
public Clazz() {
dateTimer = new Timer();
}
public static void main(String[] args) {
Clazz instance = new Clazz();
instance.run();
}
private void run() {
nextDate = parseDate(DATES[currentIndex]);
schedule();
}
public void schedule() {
runSecondsCounter();
dateTimer.schedule(new TimerTask() {
#Override
public void run() {
System.out.println("Current date is:" + new Date());
currentIndex++;
if (currentIndex < DATES.length) {
nextDate = parseDate(DATES[currentIndex]);
System.out.println("Next date is:" + nextDate);
schedule();
} else {
remainderTimer.cancel();
}
}
}, nextDate);
}
private Date parseDate(String nextDate) {
Date date = null;
DateFormat format = new SimpleDateFormat("dd.MM.yyyy HH:mm",
Locale.ENGLISH);
try {
date = format.parse(nextDate);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
private void runSecondsCounter() {
if (remainderTimerStarted) {
remainderTimer.cancel();
}
remainderTimer = new Timer();
remainderTimer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
remainderTimerStarted = true;
long remains = nextDate.getTime() - new Date().getTime();
System.out.println("Remains: " + (remains / 1000) + " seconds");
}
}, REMINDER_UPDATE_INTERVAL, REMINDER_UPDATE_INTERVAL);
}
}
I am having an issue with StrictMode i have the following AsyncTask
class pruneDiskCacheTask extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
pruneRecursive(DiskCache);
return null;
}
void pruneRecursive(File fileOrDirectory){
if (fileOrDirectory.isDirectory()) {
for (File child : fileOrDirectory.listFiles()) {
pruneRecursive(child);
}
}else {
if(checkForPruningAsync(fileOrDirectory)){
fileOrDirectory.delete();
}
}
}
public boolean checkForPruningAsync(File file){
String fileName = file.getName();
String type = fileName.substring(fileName.lastIndexOf(".")+1);
Date lastModified = new Date(file.lastModified());
if(type.equals("json")){
Date cacheLifetime = new Date(new Date().getTime() - keepJsonFor);
if(lastModified.before(cacheLifetime)){
return true;
}
}else if(type.equals("txt")) {
Date cacheLifetime = new Date(new Date().getTime() - keepTxtFor);
if(lastModified.before(cacheLifetime)){
return true;
}
}else{
Date cacheLifetime = new Date(new Date().getTime() - keepImagesFor);
if(lastModified.before(cacheLifetime)){
return true;
}
}
return false;
}
}
It is throwing a StrictMode error (does not seem to be crashing the program but i don't like it popping up)
android.os.StrictMode$AndroidBlockGuardPolicy.onReadFromDisk
My understanding is that if you put something into an Async Task it meets the requirements of StrictMode. But in this case i seem to be wrong. can someone tell me what I am doing wrong please?
EDIT
Here is how i call the Async Task as requested
public void pruneDiskCache(){
synchronized (mDiskCacheLock) {
// Wait while disk cache is started from background thread
while (mDiskCacheStarting) {
try {
mDiskCacheLock.wait();
} catch (InterruptedException e) {
}
}
if(DiskCache.exists()) {
new pruneDiskCacheTask().execute();
}
}
}
This is called from within my Cache Class which is created as so
mActivity = this;
cacheHandeler = new Cache(mActivity);
from within my main thread.
Should new pruneDiskCacheTask(); not be "new pruneDiskCacheTask().execute()"?
Thanks to Shirish Hirekodi i have found the answer. it wasn't the method itself it was the
if(DiskCache.exists()){
}
comparison when i called was creating the task that needed to be be put inside the async task.
Thanks.
My MainActivity has 2 views: TextView and a Button. On button click, I am running an AsyncTask which further creates 10 new AsyncTasks for network operations. Every new task creation is delayed by 1 sec. The code is:
public class MainActivity extends ActionBarActivity
{
TextView tv;
Button t;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.textView1);
t = (Button) findViewById(R.id.toggleButton1);
t.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
getData();
}
});
}
void getData()
{
SuperNetworkAsyncTask s = new SuperNetworkAsyncTask();
s.execute("");
}
private class SuperNetworkAsyncTask extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... urls)
{
for(int i=0;i<10;i++)
{
{
nTask = new NetworkAsyncTask();
nTask.execute("");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return "";
}
#Override
protected void onPostExecute(String result)
{
}
}
private class NetworkAsyncTask extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... urls)
{
return String.valueOf(System.currentTimeMillis());
}
#Override
protected void onPostExecute(String result)
{
tv.setText(result);
}
}
}
I was expecting that the moment first NetworkAsyncTask execute method is called, it will start execution. But when I run it, I do not find any NetworkAsyncTask begin its execution until the control comes out of SuperNetworkAsyncTask. Is there any way to push the execution of NetworkAsyncTask thread as soon as execute method is called?
Some clarifications:
Why NetworkAsyncTask are created by SuperNetworkAsyncTask? Because If I create the NetworkAsyncTask in main thread, I get my UI freeze for some time.
Why making 10 object? The purpose of NetworkAsyncTask is to read data from a server at interval of 1 sec for n seconds, here n=10.
Part 2: Updates after doing some tests.
Observation 1:
As a fellow Brian shared a way to avoid creating AsyncTasks in nested way, I tried his code:
void getData() {
Runnable runnable = new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 10; i++) {
nTask = new NetworkAsyncTask();
nTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
new Thread(runnable).start();
}
This freezes my UI for few seconds and then the screen is updated in a fraction of second. It is quite surprising to me too.
Observation 2:
With java.lang.Thread, I experimented to make sure that 1) The threads should be executed right away when run() called. 2) The next task will be created only after previous task is finished.
Code:
public static void main(String[] args) {
myThread m;
for (int i=0;i<10;i++)
{
m=new myThread(String.valueOf(i));
m.start();
synchronized (m)
{
try {
m.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class myThread extends Thread
{
public String name = "";
public myThread(String n)
{
name = n;
}
public void run()
{
synchronized (this)
{
System.out.println(" Thread Name = " + name);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
notifyAll();
}
}
}
Output:
Thread Name = 0
Thread Name = 1
Thread Name = 2
Thread Name = 3
Thread Name = 4
Thread Name = 5
Thread Name = 6
Thread Name = 7
Thread Name = 8
Thread Name = 9
Based in this, I updated my NetworkAsyncTask & SuperNetworkAsyncTask as:
private class NetworkAsyncTask extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... urls)
{
synchronized (this)
{
return String.valueOf(System.currentTimeMillis());
}
}
#Override
protected void onPostExecute(String result)
{
synchronized (this)
{
tv.setText(result);
notifyAll();
}
}
}
private class SuperNetworkAsyncTask extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... urls)
{
for(int i=0;i<10;i++)
{
nTask = new NetworkAsyncTask();
nTask.execute(url);
synchronized (nTask)
{
try {
nTask.wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return "";
}
#Override
protected void onPostExecute(String result)
{
}
}
With this code the wait() keeps on waiting indefinitely.
Finally I replaced:
nTask.execute(url);
with
nTask.executeOnExecutor(THREAD_POOL_EXECUTOR, "");
This worked well as expected.
The UI will be updated only at onPostExecute(). See notes on AsyncTask
Click here! And Try to avoid 10 AysncTasks, it does not make any sense.
You don't need to use a "super async task" use a runnable and then create new async tasks in parallel
void getData() {
Runnable runnable = new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 10; i++) {
nTask = new NetworkAsyncTask();
nTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
new Thread(runnable).start();
}
Post honeycomb you can specify to run async tasks in parallel
An AsyncTask should be started in the UI thread, not on the one doInBackground runs on. You could call publishProgress after every sleep, and spawn each AsyncTask in the resulting calls to onProgressUpdate, which run on the UI thread.