0

I am developing long running application, my application uses DefaultHttpClient (I also tried with AndroidHttpClient) periodically. I don't know but after working a while, somehow httpClient.execute sleeps. Literally sleeps, when I wake(unlock or connect to PC) my device httpClient immediately continues to work(throws an exception if I set timeout or just returns the response of execution). I searched and tried similar cases and non work. For wake and wifilocks, I just acquire wifi lock and wake lock before execution and release it after getting response. Nothing work, and I have no idead.

The devices I work is Galaxy S3(v4.0+) and Ace(v2.3.6)

thanks in advance.

This is MyTask that stucks, and it stucks at the line response = new MyClient(ctx).client.execute(post); and MyClient is a wrapper in order to handle https & certificate things.

public abstract class GenericTask extends AsyncTask<Object, Object, Document> {


public final static String TAG = "GenericTask";
private WakeLock wakeLock;
private WifiLock wifiLock;
protected HttpPost post;
public String taskId;
public Context ctx;
Object parameter;

public GenericTask(Context ctx, Object parameter) {
    this.parameter = parameter;
    this.ctx = ctx;
    post = null;
    initLock(ctx);
    lock();
}
private void lock() {
    try {
        wakeLock.acquire();
        wifiLock.acquire();
        Log.d(TAG,"LockAcquired");
    } catch (Exception e) {
        Log.e("WlanSilencer", "Error getting Lock: " + e.getMessage());
    }
}

private void unlock() {
    Log.e(TAG,"unlock");
    if (wakeLock.isHeld())
        wakeLock.release();
    if (wifiLock.isHeld())
        wifiLock.release();
    Log.d(TAG,"LockReleased");
}

private void initLock(Context context) {
    wifiLock = ((WifiManager) context
            .getSystemService(Context.WIFI_SERVICE)).createWifiLock(
            WifiManager.WIFI_MODE_FULL_HIGH_PERF, "GenericTaskWifiLock");
    wakeLock = ((PowerManager) context
            .getSystemService(Context.POWER_SERVICE)).newWakeLock(
            PowerManager.FULL_WAKE_LOCK, "GenericTaskWakeLock");
    Log.d(TAG,"LockInitiated");
}

public boolean cancelTask(boolean bln) {
    if(post!=null)
        post.abort();
    return super.cancel(bln);
}

public void execute(){
    if(Build.VERSION.SDK_INT >= 11){
        startNew();
    }else{
        startOld();
    }
}
private void startOld() {
    super.execute();

}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void startNew(){
    executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR );
}
@Override
protected void onPostExecute(Document doc) {
    unlock();
    if(doc==null){
        Log.e("GenericTask: " +getClass(),"onPostExecute doc=null");
    }
    Log.e(TAG,"onPostExecute");
        TaskManager.getInstance().returnFromTaskSuccess(doc, getClass(), taskId, parameter);

}

@Override
protected Document doInBackground(Object... params) {
    Log.e(TAG,"doInBackground");
    try {
        return call();
    } catch (InvalidKeyException e) {
        OtherUtils.printStackTrace(e);
    } catch (NoSuchPaddingException e) {
        OtherUtils.printStackTrace(e);
    } catch (InvalidAlgorithmParameterException e) {
        OtherUtils.printStackTrace(e);
    } catch (IllegalStateException e) {
        OtherUtils.printStackTrace(e);
    } catch (NoSuchAlgorithmException e) {
        OtherUtils.printStackTrace(e);
    } catch (IOException e) {
        OtherUtils.printStackTrace(e);
    } catch (TransformerException e) {
        OtherUtils.printStackTrace(e);
    } catch (ParserConfigurationException e) {
        OtherUtils.printStackTrace(e);
    }
    return null;
}
protected abstract String getUrl();

protected abstract Document getRequest();

public int initialSleep() {
    return 0;
}

public String getTaskId() {
    return taskId;
}

public void setTaskId(String taskId) {
    this.taskId = taskId;
}

protected Document call() throws IOException, TransformerException, ParserConfigurationException, InvalidKeyException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalStateException, NoSuchAlgorithmException{


Document doc = getRequest();
    String url = getUrl();
    Document responseXml = null;
    try {

        post = HttpUtils.postXml(doc, url, null);

        HttpResponse response;
        HttpParams httpParams = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout(httpParams, 16000);
        HttpConnectionParams.setSoTimeout(httpParams, 20000);
        post.setParams(httpParams);
        response = new MyClient(ctx).client.execute(post);
        HttpEntity resEntity = response.getEntity();
        responseXml = XmlUtils.entityToXml(resEntity, null);
        resEntity.consumeContent();
        return responseXml;
    } catch (TransformerException e) {
        throw e;
    } catch (IOException e) {
        throw e;
} 


}
}

HttpUtils:

public class HttpUtils {
public static HttpPost postXml(Document doc, String url, WrapperAsByteArrayOutputStream baos) throws IOException, TransformerConfigurationException, TransformerException
{
    StringWriter xmlAsWriter = new StringWriter();
    StreamResult result = new StreamResult(xmlAsWriter);
    TransformerFactory.newInstance().newTransformer().transform(new DOMSource(doc), result);
    HttpPost post = new HttpPost(url);
    InputStreamEntity req;
    if ( baos == null ) {
        req = new InputStreamEntity(new ByteArrayInputStream(xmlAsWriter.toString().getBytes()), -1);
    }
    else {
        req = new InputStreamEntity(new WrappedInputStream(new ByteArrayInputStream(xmlAsWriter.toString().getBytes()), baos), -1);
    }
    req.setChunked(true);
    post.setEntity(req);
    return post;
}

MyClient:

public class MyClient extends DefaultHttpClient { public HttpClient client;

public MyClient(Context ccc) {
    super();
    KeyStore localTrustStore = null;
    try {
        localTrustStore = KeyStore.getInstance("BKS");
    } catch (KeyStoreException e) {
        e.printStackTrace();
    }
    InputStream in = ccc.getResources().openRawResource(
            R.raw.localcert);
    try {
        localTrustStore.load(in, "local_trust_password".toCharArray());
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(new Scheme("http", PlainSocketFactory
            .getSocketFactory(), 80));
    SSLSocketFactory sslSocketFactory = null;
    try {
        sslSocketFactory = new SSLSocketFactory(localTrustStore);
    } catch (KeyManagementException e) {
        e.printStackTrace();
    } catch (UnrecoverableKeyException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    }
    schemeRegistry.register(new Scheme("https", sslSocketFactory, 443));
    HttpParams params = new BasicHttpParams();
    ClientConnectionManager cm = new ThreadSafeClientConnManager(params,
            schemeRegistry);

    this.client = new DefaultHttpClient(cm, params);
}

onrecieve of AlarmReciever

public void onReceive(Context context, Intent intent) {
    try {
        TaskManager.getInstance().sendBatteryStatus();
         }
    } catch (Exception e) {
        Toast.makeText(
                context,
                "There was an error somewhere, but we still received an alarm",
                Toast.LENGTH_SHORT).show();
        e.printStackTrace();

    }

returnfromtask success simply checks id for thread safety, handles doc and setups new alarm like below:

 Calendar cal = Calendar.getInstance();
    cal.add(Calendar.SECOND, 30);
    Intent intent = new Intent(ctx, AlarmReceiver.class);

    PendingIntent sender = PendingIntent.getBroadcast(ctx, 2131225, intent,
            PendingIntent.FLAG_CANCEL_CURRENT);

    AlarmManager am = (AlarmManager) ctx
            .getSystemService(Context.ALARM_SERVICE);
    am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);

sendBatteryStatus gethers some info to send, and pass it to a task which extends GenericTask and it normally executes new MyAsyncTask(..bla bla).execute();

guness
  • 6,336
  • 7
  • 59
  • 88
  • where do you call http client from? an activity? `AsyncTask`? other background thread? something else? – andr Feb 07 '13 at 18:58
  • it is called within an AsyncTask which is created within a service. – guness Feb 07 '13 at 21:06
  • This doesn't appear to be your problem, but the symptoms sound *exactly* like what happens if you don't close the HttpEntity: http://stackoverflow.com/a/14088063 – blahdiblah Apr 01 '16 at 01:30

1 Answers1

0

As soon as you release the wake lock the CPU is allowed to go to sleep and that is most probably what happens. You perform an action using HttpClient several times, but at some point, after releasing wake lock, the CPU hibernates.

Since you want to execute a code periodically you should use the AlarmManager service documented here: http://developer.android.com/reference/android/app/AlarmManager.html. The alarm manager service is active even if the phone is asleep. You use it by scheduling a PendingIntent via one of AlarmManager.set*() methods. The alarm manager will hold a wake lock for the duration of receivers onReceive() method but you will most probably need to acquire the WiFi lock.

andr
  • 15,970
  • 10
  • 45
  • 59
  • I acquired both wifilock(FULL_MODE) and wakelock(PARTIAL_AWAKE) in a background service which is started when my application starts, and it releases locks when user intentionally exits application in order to make sure that OS never releases locks itself(yes it somehow releases, they say it is coz of power button). but even it did not work, I just acquired FULL_WAKE_LOCK and WIFI_MODE_FULL_HIGH_PERF at start of my asynctask(which is responsible for single post) and release it in onPostExecute. after a while (some hours later) still my devices might stuck at same position. ty for your concern. – guness Feb 08 '13 at 20:15
  • The periodic thing my application is to send these posts, and I am using alarmanager too. sleep thing occurs not between my single posts, it is exactly occurs at httpClient.execute(post) – guness Feb 08 '13 at 20:18
  • sorry, I thought that you didn't use `AlarmManager` because you mentioned wake locks but not AM. that's strange what you're describing. can you post actual code of your Service, ssyncTask, Receiver and UI? it would be great if it was a minimal fragment of your app that is still presenting this issue, i.e. so called SSCCE: http://sscce.org/ without this, it's just guessing... – andr Feb 08 '13 at 20:31
  • when I am posting the problem, I was not using alarm manager. and I am preparing some kind of sscce. – guness Feb 08 '13 at 20:33
  • ok. to try it I'll need: source of `HttpUtils.postXml()`, how is `MyClient.client` created and finally - how are your `GenericTask`s created via `AlarmManager`. the rest is of no interest for me and I can mock it. – andr Feb 12 '13 at 08:37
  • I have added some other codes, lemme know if you need something else. – guness Feb 12 '13 at 10:00