Android Dev - Strict Mode Problems - android

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.

Related

Getting server time freezes and crashes my application

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.

The doInBackground() method in the AsyncTask gets executed only sometimes

I'm using the AsyncTask to render a graph from a list. Sometimes it works alright and the graph is rendered. However in some cases the graph is not being rendered, and the reason for this is that the doInBackground() method is not being triggered. Here's the code of the AsyncTask.
private class HistoryPlotAsync extends AsyncTask<Void, Void, Void> {
boolean isAnalysisMode = false;
List<Byte> listECG;
List<Byte> listHS;
HistoryPlotAsync(List<Byte> listECG, List<Byte> listHS, List<Byte> listMur, boolean isAnalysisMode) {
this.listECG = listECG;
this.listHS = listHS;
this.isAnalysisMode = isAnalysisMode;
HistoryPlot.this.multiHsRenderer.setPanEnabled(false, false);
HistoryPlot.this.multiEcgRenderer.setPanEnabled(false, false);
}
protected Void doInBackground(Void... params) {
if (HistoryPlot.this.pcgPlayer != null) {
HistoryPlot.this.pcgPlayer.start();
} else {
try {
HistoryPlot.this.startSound();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
int i = 0;
int loopCounter = 0;
if (this.listHS != null && this.listHS.size() > 0) {
loopCounter = this.listHS.size();
}
double xValue = 0.0d;
double xValueEcg = 0.0d;
do {
xValueEcg += 0.0015625d;
if (this.listHS != null && i % 2 == 0) {
xValue += 0.0032012d;
hsSeries.add(xValue,listHS.get((i/2)));
}
try {
if (this.listECG != null && i < this.listECG.size()) {
ecgSeries.add(xValueEcg, listECG.get(i));
}
} catch (Exception e) {
try {
Log.d("HistoryPlot -> ", "doInBackground: Exception " + e.getMessage());
} catch (Exception e2) {
Log.e("HistoryPlot -> ", "Error in Analysis mode point conversion");
}
}
if (i > HistoryPlot.this.refRange && i % 94 == 0) {
HistoryPlot.this.xMin = HistoryPlot.this.xMin + 0.15d;
HistoryPlot.this.xMax = HistoryPlot.this.xMax + 0.15d;
HistoryPlot.this.multiHsRenderer.setXAxisMin(HistoryPlot.this.xMin);
HistoryPlot.this.multiHsRenderer.setXAxisMax(HistoryPlot.this.xMax);
HistoryPlot.this.multiEcgRenderer.setXAxisMin(HistoryPlot.this.xMin);
HistoryPlot.this.multiEcgRenderer.setXAxisMax(HistoryPlot.this.xMax);
}
if (i % 16 == 0) {
publishProgress(new Void[0]);
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
i++;
if (i >= loopCounter) {
break;
}
} while (!HistoryPlot.this.taskHistoryPlot.isCancelled());
return null;
}
protected void onProgressUpdate(Void... values) {
HistoryPlot.this.mHsChart.repaint();
HistoryPlot.this.mEcgChart.repaint();
}
protected void onPostExecute(Void result) {
HistoryPlot.this.stopSound();
HistoryPlot.this.enableReplay();
HistoryPlot.this.multiHsRenderer.setPanEnabled(true, true);
HistoryPlot.this.multiEcgRenderer.setPanEnabled(true, true);
}
}
The AsyncTask is executed via the following code in the onCreate() method of the Activity.
protected void onCreate(Bundle savedInstance) {
...
this.taskHistoryPlot = new HistoryPlotAsync((List) mapData.get("fileEcg"), (List) mapData.get("fileHs"), (List) mapData.get("fileMur"), isAnalysisMode);
this.taskHistoryPlot.execute();
}
Instead of using the execute() method, I have also tried using the executeOnExecutor(THREAD_POOL_EXECUTOR) method with the same results.
I got the issue resolved using the following code. The problem was that I had simply tried using the execute() method and the executeOnExecutor() method as is. You need to define an Executor and a Blocking Queue variables and define pool sizes for this to work.
static int mCorePoolSize = 60;
static int mMaximumPoolSize = 80;
static int mKeepAliveTime = 10;
static BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(mMaximumPoolSize);
static Executor mCustomThreadPoolExecutor = new ThreadPoolExecutor(mCorePoolSize, mMaximumPoolSize, mKeepAliveTime, TimeUnit.SECONDS, workQueue);
this.taskHistoryPlot = new HistoryPlotAsync((List) mapData.get("fileEcg"), (List) mapData.get("fileHs"), (List) mapData.get("fileMur"), isAnalysisMode);
this.taskHistoryPlot.executeOnExecutor(mCustomThreadPoolExecutor);
Asynctask methods will surely run, if you have have call to this class.
Please debug that, the conditions inside doInBackground(), for example
"if (HistoryPlot.this.pcgPlayer != null) "
because it may be possible that condition is not working well, or throws xception and led the function not being called.
If you want that code to execute multiple times, do not use the onCreate function. Create one that you can call everytime you want, onCreate() only runs once in the Activity lifecycle. That can be the cause.
You can call it from the onCreate as well, if you need ;)
Replace these two lines:
this.taskHistoryPlot = new HistoryPlotAsync((List) mapData.get("fileEcg"), (List) mapData.get("fileHs"), (List) mapData.get("fileMur"), isAnalysisMode);
this.taskHistoryPlot.execute();
with:
new HistoryPlotAsync((List) mapData.get("fileEcg"), (List) mapData.get("fileHs"), (List) mapData.get("fileMur"), isAnalysisMode).execute();
You dont need to pass context of activity here "this." will give the context of activity which you dont need it here so apply above mentioned changes.
OnCreate will run it one time only create another method in which you need to run your async task and call that new method wherever you want.You can also call that method in onCreate too.

Best approach to make a login screen

I am writing here because this is my last solution of understanding this type of programming.The problem is that I got stuck on what to use to handle the connection to a server and log-in. Should I use async task, handler or thread ? I didn't find a concrete answer stating which one to use, only found that async task is used to download images or other download stuffs.
Until now I have used a thread to connect to the server. The problem I encountered was when I catch the exception ( Putting invalid username/password ) and try to log-in again. ( I needed to "close" the last thread and start one again )
After this I started to use async task but I don't really understand how it should work and I am stuck on a toast of invalid username/password.
private class connectStorage extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
api = DefaultClientFactory.create(host, getUser, getPassword);
if (api.getAuthToken().trim().length() > 3) {
//TO DO LAYOUT CHANGE;
}
} catch (StorageApiException e) {
e.printStackTrace();
Log.i("TEST", "" + e.getMessage());
}
return null;
}
Also, I am 100% sure that calling inflate in the doInBackground method won't work too ( there I wanted to change the activity ).
I am starting the async task on a button press.
When you are using asynctask
You have doInBackground and onPostExecute
So basically get a json or string or boolean as a result from doinbackground
and in onpostexecute check if the login in succesful or not if its succesful save the data from server and start an intent to go to another activity or toast the user that that user login details are wrong and try again.
So your asynctask can be an inner class of your activity class which is login and onClickSubmit button call the asynctask class and on post execute parse the json and according to the result decide what to do
Example:
public class SignInAsycTask extends AsyncTask<RequestParams, Void, String> {
#Override
protected String doInBackground(RequestParams... params) {
return new HttpManager().sendUserData(params[0]);
}
#Override
protected void onPostExecute(String result) {
String[] details = parseJsonObject(result);
if (details != null) {
user.setUser_id(Integer.valueOf(details[0]));
user.setName(details[1]);
if (details.length > 2) {
user.setProfilePic(details[2]);
}
setSharedPreferences();
startActivity(new Intent(Signin.this, MainActivity.class));
finish();
} else {
Toast.makeText(Signin.this, "please try again",
Toast.LENGTH_LONG).show();
}
}
}
public String[] parseJsonObject(String result) {
JSONObject obj = null;
try {
obj = new JSONObject(result);
if (obj.has("success")) {
if (obj.getInt("success") == 1) {
if (obj.has("user_pic")) {
return new String[] {
String.valueOf(obj.getInt("user_id")),
obj.getString("user_name"),
obj.getString("user_pic") };
} else {
return new String[] {
String.valueOf(obj.getInt("user_id")),
obj.getString("user_name"), };
}
} else {
return null;
}
} else {
return null;
}
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
here my RequestParams are just a object where I stored all the details like url parameters to send etc and the output of the doinbackground is a String and I am parsing it in my postexecute method

AsynTask - onPostExecute is called before doInBackground

i got a problem getting my AsyncTask to work correct. My App offers the possibility to connect with your Google Account and add and receive tasks by using the Tasks API. When the users wants to synchronize with his account, the doInBackground() method is started. Right before that, a ProgressDialog is displayed in the onPreExecute() method of the AsyncTask class.
If the synchronisation has been successfully executed, the onPostExecute() method 'should' be called fading out the ProgressDialog.
But there is problem: the onPostExecute() ethod is called before the work in the doInBackground() is finished.
In doInBackground() I receive the token used for the authorization:
token = future.getResult().getString(AccountManager.KEY_AUTHTOKEN);
That's all. But right before that, the onPostExecute() is called and the ProgressDialog disappears while the token is still retrieving. The wired thing is that when I start the app and synchronizes for the first time, it works like it should. But after that the onPostExecute() method finishes before the work is completed. Does this have to do that there are requests to a server while executing
future.getResult().getString(AccountManager.KEY_AUTHTOKEN);
How can I tell the onPostExecute() method that there is still work to do?
private class SynchronizeGoogle extends AsyncTask<Void, Integer, Void>
{
private final ProgressDialog dialog = new ProgressDialog(RememberMe.this);
protected void onPreExecute()
{
this.dialog.setMessage("Listen werden geladen...");
this.dialog.show();
}
#Override
protected Void doInBackground(Void... arg0)
{
try
{
switch(startSynchronize())
{
case 0:
publishProgress(0);
return null;
case 1:
publishProgress(1);
return null;
case 2:
publishProgress(2);
return null;
}
}
catch (IOException e)
{
e.printStackTrace();
}
synchronize();
return null;
}
protected void onProgressUpdate(Integer... type)
{
int typeCase = type[0];
switch(typeCase)
{
case 0:
showDialog(DIALOG_INTERNET_ACCESS);
break;
case 1:
showDialog(DIALOG_CREATE_ACCOUNT);
break;
case 2:
showDialog(DIALOG_ACCOUNTS);
break;
}
}
protected void onPostExecute(final Void unused)
{
if (this.dialog.isShowing())
{
this.dialog.dismiss();
}
}
}
And here my startSynchronize() and synchronize() methods:
private int startSynchronize() throws IOException
{
googleAccountManager = new GoogleAccountManager(RememberMe.this);
Account[] accounts = googleAccountManager.getAccounts();
if(checkAccess.internetAccess() == false)
{
return 0;
}
if(accounts.length == 0)
{
return 1;
}
else
{
if(accounts.length == 1)
{
account = accounts[0];
}
else
{
return 2;
}
}
return -1;
}
private void synchronize()
{
myPrefs = this.getSharedPreferences("myPrefs", MODE_PRIVATE);
String oldToken = myPrefs.getString(MY_TOKEN, "");
if(oldToken.length() > 0)
{
// invalidate old token to be able to receive a new one
googleAccountManager.invalidateAuthToken(oldToken);
}
googleAccountManager.manager.getAuthToken(account, AUTH_TOKEN_TYPE, true, new AccountManagerCallback<Bundle>()
{
public void run(AccountManagerFuture<Bundle> future)
{
try
{
token = future.getResult().getString(AccountManager.KEY_AUTHTOKEN);
prefsEditor.putString(MY_TOKEN, token);
prefsEditor.commit();
useTasksAPI(token);
}
catch (OperationCanceledException e)
{
//...
}
catch (Exception e)
{
//...
}
}
}, null);
}
In the Optionsmenu i start it like this
new SynchronizeGoogle().execute();
Thanks everybody for your help
If I do not misunderstand your question, you're wrong with getResult() method usage.
When getResult() called by anywhere in your code, AsyncTask does not wait until finish. So you need to do your process in onPostExecute method.
I recommend you this question&answer. I hope, it's gonna help you.

AsyncTask return value

My android app connects to my website to retrieve and upload information so I use an AsyncTask thread.
In one instance, I need my thread to return a true or a false value to my main thread.
Is there a way to get this return value from an AsyncTask execute function?
When I do the following:
Toast.makeText(Locate.this, "Testing : "+locationUpdate.execute(location), Toast.LENGTH_LONG).show();
I just get alot of gibberish.
I think what I need is a means to pause the main thread until the second thread completes. The second thread calls a function in the main thread to set my return value.
So when the second thread completes, the main thread can unpause and access the return value as set by the second thread
If this logic is sound, please offer suggestions ... thanks!
You can use AsyncTask get() method for this. It waits if necessary for the computation to complete, and then retrieves its result:
Toast.makeText(Locate.this, "Testing : " + locationUpdate.execute(location).get(), Toast.LENGTH_LONG).show();
But be sure to not block the main thread for a long period of time, as this will lead to unresponsive UI and ANR.
UPDATE
I missed the point that question was about async web download/upload. Web/network operation should considered as a long one and thus the approach "pause UI thread and wait till download finishes" is always a wrong one. Use usual result publishing approach intstead (e.g.: AsyncTask.onPostExecute, Service + sendBroadcast, libraries like Volley, RoboSpice, DataDroid etc).
Handler is the best way to do this
in onPostExcecute() method simply do
#Override
protected void onPostExecute(Boolean bool) {
super.onPostExecute(bool);
Message msg=new Message();
msg.obj=bool;
mHandler.sendMessage(msg);
}
}
and your message handler will be
mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
bool i=(String)msg.obj;
}
};
public class RunWebScript {
String mString;
public RunWebScript(String url){
try {
URL updateURL = new URL(url);
URLConnection conn = updateURL.openConnection();
// now read the items returned...
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
ByteArrayBuffer baf = new ByteArrayBuffer(50);
int current = 0;
while((current = bis.read()) != -1){
baf.append((byte)current);
}
String s = new String(baf.toByteArray());
mString = s;
} catch (Exception e) {
Log.e("ANDRO_ASYNC", "exception in callWebPage",e);
mString = "error";
}
}
public String getVal(){
return mString;
}
}
this is executed as... (showing teh end of a method in teh calling class
asyncWebCall (url1,CONSTANT);
}
private void asyncWebCall(String url,int actionPostExecute){
new WebCall().execute(url,String.format("%d",actionPostExecute));
}
The Async part of the business is ... Note the case statement in onPostExecute this is the key to getting the returned value ito your program again. Note that the call new WebCall().execute(url,String.format("%d",actionPostExecute)); is the last thing done in a thread, no further statements can be executed, control returns through the onPostExecute.
class WebCall extends AsyncTask<String, String, String>{
int chooser = -1;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
try {
chooser = Integer.parseInt(params[1]);
} catch(NumberFormatException nfe) {
Log.d("ANDRO_ASYNC",String.format("asyncReturn() mString numberformatexception = %s",params[1]));
chooser = 0;
}
return(new RunWebScript(params[0])).getVal();
}
protected void onProgressUpdate(String... progress) {
}
#Override
protected void onPostExecute(String gotFromDoInBkgnd) {
Log.d("ANDRO_ASYNC",String.format("chooser = %s",chooser));
switch (chooser){
case CONSTANT:
printStringx(gotFromDoInBkgnd);
asyncWebCall(url2,5);
break;
case 0:
Log.d("ANDRO_ASYNC",String.format("case 0 = %s",gotFromDoInBkgnd));
break;
case 5:
Log.d("ANDRO_ASYNC",String.format("case 5 = %s",gotFromDoInBkgnd));
asyncWebCall(url3,7);
break;
default:
Log.d("ANDRO_ASYNC",String.format("man we got problems = %s",gotFromDoInBkgnd));
break;
}
}
} // end of class
Here is a complete example of the issue of returning values from an async task. It may occur that there are many tasks to be done one after the other asynchronously.
Basics.
1. get a return value from a class.
public class Snippet {
int computVal;
public Snippet(){
computVal = 17*32;
}
public int getVal(){
return computVal;
}
}
this is called as...
int hooray = (new Snippet()).getVal();

Categories

Resources