OpenGLRenderer flushing caches (mode 0) - android

i have i problem that i don't know the cause, so when running my application after an asynctask call in POST i change activity and when the new Activity is setting the main content to the screen the app crashes with any log.
The activty chages code is written in onPostExecute method of asynctask and i've tried to do this in another thread calling the runOnUIThread method from activity but isn't working.
the only log that I see:
03-10 12:03:20.312: I/MyHttpClient(3160): HTTPResponse received in [1210ms]
03-10 12:03:20.367: I/my.app.package.ActivationActivity(3160): SendActivation onPostExecute: ActivationResponse [my.app.result.json.with.SUCCESS:result.code]
03-10 12:03:25.398: D/OpenGLRenderer(3160): Flushing caches (mode 0)
EDIT: now i have changed some names of classes and objects but is the code that don't work for me
class MyAsincTask extends AsyncTask<String, Void, String>
{
private Exception exception;
private Gson gson;
protected void onPostExecute(String response) {
hideProgressDialog();
if (exception != null) {
//deleted log code here
} else if (response != null) {
// I manage the json response from the server
try {
// I manage the json response
// determining if the server call was SUCCESS or ERROR
if (resultCode.equals(Constants.RESULT_ERROR)) {
//deleted log code here
}else if (resultCode.equals(Constants.RESULT_SUCCESS)) {
launchRegistration(); // I enter Here and then crashes
}
} catch (Exception e) {
//deleted log code here
}
//deleted log code here
} else {
//deleted log code here
}
}
}
protected void launchRegistration(){
runOnUiThread(new Runnable() {
#Override
public void run() {
Intent mIntent = new Intent(mContext, ActivityToOpen.class);
mIntent.setAction(Constants.ACTION_TO_OPEN_ACTIVITY);
mIntent.putExtra(Constants.SOME_EXTRA, extras);
startActivity(mIntent);
finish();
}
});
}
is inside other activity, and the asynctask class is inner in other activity class. this code for me work on many recent device, with recdent hardware and recent version like 4.4 and 5 and 4.3, but the problem is happening in other devicewith 4.0 and 4.1 with less hardware resource.

`<activity android:name="com.example.Activity"
android:excludeFromRecents="true"
android:icon="#drawable/app_icon"
android:label="#string/wizard.welcome.title"
android:theme="#style/Theme.NoDisplay" /> `
the error that I did, is in the manifest declaration, some activity has the theme "NoDisplay" that don't work in recent version of android, but works in previous versions. And for this I had an issue.
Thank

Related

Parse Android SDK nested saveInBackground not working

I'm working on an existing Android App with parse back-end (localDatastore is enabled but not used in this context) which has the following object structure:
Object A has an array of objects B
Object B has an array of objects C
I save this object structure using saveInBackground in calling the next saveInBackground in the done SaveCallback in reverse Order(C,B,A). For the inner two that works fine, but the top level object isn't saved.
Here's the code (frame, newStep and order are objects of classes inheriting from the ParseObject class)
frame.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.i("Info", "frame.save callback OK");
frames.add(frame);
newStep.setTimeFrames(frames);
newStep.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.i("Info", "newStep.save callback OK");
List<ProcessingStep> steps = order.getProcessingSteps();
steps.add(newStep);
order.setProcessingSteps(steps);
order.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null){
Log.i("Info", "order.save callback OK");
}else{
Log.i("Info", "order.save callback FAIL");
}
}});
} else {
Log.i("Info", "newStep.save callback FAIL");
e.printStackTrace();
}
}
});
} else {
Log.i("Info", "frame.save callback FAIL");
e.printStackTrace();
}
}
});
In the console log I see only "frame.save callback OK", the "newStep.saveInBackground()" seems to be executed too (object appears in backend) however I never get the log message in the callback.
If I save all objects before synchronously without references to each other first and then call the code here, it seems to work (worked at least once) but took for ever (minutes). Queries from the back-end are super fast and the frame object is also saved almost instantly but the done-callbacks seem to bugging. When it fails I do not get any exception, log anything it just seems to fail silently.
I'm looking for any insight why Parse behaves like that as well as how to fix it.
edit: The problem seems to be with the double relation (A to B and B to C). If I try with only A to B or B to C it works just fine. What remains mysterious to me, however, is why splitting the operation up with callbacks doesn't seem to work.
The problem was the enabled localdatastore. Without localdatastore enabled everything works as it should.

Android Branch IO referringParams is false

I'm handling branch io on Android now.
It's weird. If I close my app first and click the link, the link leads me to my app and opens the page which is supposed to be shown. But If I open my app and click the home button, and click the link, the link leads me to ap.. but the page is not shown. I just could see the main page without routing by branch io.
here this is my code.
#Override
protected void onStart() {
super.onStart();
branchIO();
}
private void branchIO() {
Branch branch= Branch.getInstance();
branch.initSession(new Branch.BranchReferralInitListener(){
#Override
public void onInitFinished(JSONObject referringParams, BranchError error) {
if (error == null) {
try{
Log.d("log", referringParams.toString());
//...my routing logic...
}catch(Exception e){
Log.e("log", "branch io error",e);
}
} else {
Log.i("log", error.getMessage());
}
}
}, this.getIntent().getData(), this);
BranchIO.branchUniversalObject.generateShortUrl(this, BranchIO.linkProperties, new Branch.BranchLinkCreateListener() {
#Override
public void onLinkCreate(String url, BranchError error) {
if (error == null) {
}
}
});
}
If I close my app first, the log is this
D/log: {"$og_title":"₩230000", "~creation_source":5, "$og_description":"blah blah", "+click_timestamp":1512100123,........"}
but If I open my app first and put it in the background, the log is this
D/log: {"+clicked_branch_link":false,"+is_first_session":false}
I read many StackOverflow and GitHub pages but couldn't find the solution.
Thanks for reading!
EDIT
I forgot to use this.setIntent(intent) in onNewIntent.
so after adding this, It worked well.
#Override
public void onNewIntent(Intent intent) {
this.setIntent(intent);
}
Thanks!
Aaron from Branch.io here.
There might be a few reasons you are seeing this error. Here are a few:
You aren't initializing Branch and handling deep linking in your
Main/Splash activity.
Your Main/Splash activity does not have the
launchMode set to singleTask
You aren't overriding onNewIntent()
in your Main/Splash activity
If you are using a
CustomApplicationClass, make sure you are initializing Branch with
Branch.getAutoInstance(this);
You can find an example Main/Splash activity here.
You can also check out our testbed application which is a complete working example of the Branch Android SDK here

Anonymous Listener of volley request causing memory leak

I am using volley library for making web-services call. I made a general class for making all web services call and making service call from there and made anonymous listener for successful and error response.
But when I use leak canary it is showing memory leak related to context. Below is my snippet of code:
public void sendRequest(final int url, final Context context, final ResponseListener responseListener, final Map<String, String> params) {
StringRequest stringRequest;
if (isNetworkAvailable(context)) {
stringRequest = new StringRequest(methodType, actualURL + appendUrl, new Listener<String>() {
#Override
public void onResponse(String response) {
dismissProgressDialog(context);
try {
(responseListener).onResponse(url, response);
} catch (JsonSyntaxException e) {
// Util.showToast(context, context.getResources().getString(R.string.error));
Crashlytics.logException(e);
}
}
}, new ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// Util.showToast(context,context.getString(R.string.error));
dismissProgressDialog(context);
if (error instanceof NetworkError) {
Util.showToast(context, context.getResources().getString(R.string.network_error));
} else if (error instanceof NoConnectionError) {
Util.showToast(context, context.getResources().getString(R.string.server_error));
} else if (error instanceof TimeoutError) {
Util.showToast(context, context.getResources().getString(R.string.timeout_error));
} else {
Util.showToast(context, context.getResources().getString(R.string.default_error));
}
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
return params;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
return request.getHeaders(context, actualURL, false);
}
};
stringRequest.setRetryPolicy(new DefaultRetryPolicy(30000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
VolleySingleton.getInstance(context).addRequest(stringRequest);
} else {
Util.showToast(context, context.getString(R.string.internet_error_message));
}
}
And I created an interface named response listener for redirecting responses to activity or fragment. I made request as follows.
Request.getRequest().sendRequest(Request.SOME URL, SplashScreenActivity.this, SplashScreenActivity.this, new HashMap<String, String>());
But I am facing memory leak as:
In 2.1.1:31.
* activity.SplashScreenActivity has leaked:
* GC ROOT com.android.volley.NetworkDispatcher.<Java Local>
* references network.Request$5.mListener (anonymous subclass of com.android.volley.toolbox.StringRequest)
* references network.Request$3.val$responseListener (anonymous implementation of com.android.volley.Response$Listener)
* leaks activity.SplashScreenActivity instance
* Retaining: 1.2MB.
* Reference Key: b8e318ea-448c-454d-9698-6f2d1afede1e
* Device: samsung samsung SM-G355H kanas3gxx
* Android Version: 4.4.2 API: 19 LeakCanary: 1.4 6b04880
* Durations: watch=5052ms, gc=449ms, heap dump=2617ms, analysis=143058ms
Any idea to remove this leak any help is appreciated.
Generally, Anonymous classes have a strong reference to the enclosing class instance. In your case, that would be SplashScreenActivity. Now I guess, your Activity is finished before you get the response from your server through Volley. Since the listener has a strong reference to enclosing Activity, that Activity cannot be garbage collected until the Anonymous class is finished. What you should do is tag all the requests you are sending with the Activity instance, and cancel all the requests at onDestroy() callback of Activity.
stringRequest.setTag(activityInstance);
To cancel all pending requests:
requestQueue.cancellAll(activityInstance);
Also, use Application context inside VolleySingleton to create the RequestQueue.
mRequestQueue = Volley.newRequestQueue(applicationContext);
Don't use your Activity context there and don't cache your Activity instance inside VolleySingleton.
Basically the anonymous approach is terrible in Android or in any ClientSideSystem where you don't have massive memory. What is happening is, you have passed Context as parameter in method and anonymous holds a reference of it. The real mess comes now in the scene when the thread inside which makes network call could not finish it's job and before that the calling activity for some reason either destroys or recycles in that case GC is not able to collect the activity as wokerThread might still be holding reference onto it. Please go through this for detail description.
The solution could be either static inner classes or independent classes, in both cases use WeakReference to hold resources and do a null check before using them.
Advantage of WeakReference is it will allow GC to collect the object if no-one else if holding reference onto it.
I had a similar problem detected with LeakCanary where Volley's mListener was referencing my response listener, and my listener was referencing an ImageView, so it could update it with the downloaded image.
I made my response listener an inner class within the activity ..
private class MyVolleyResponseListener <T> implements com.android.volley.Response.Listener <Bitmap> {
#Override
public void onResponse(Bitmap bitmap) {
thumbNailView.setImageBitmap(bitmap);
}
}
.. and stopped and started the volley request queue inside onDestroy() in the activity ..
requestQueue.stop();
requestQueue.start();
This has fixed the leak.
I know I m a bit late to join the party, but few days back this problem did spoil my weekend. In order to figure out, I went on to research a bit which finally got the solution.
The issue lies in the last request object getting leaked in Network Dispatcher & Cache Dispatcher.
#Override
public void run() {
if (DEBUG) VolleyLog.v("start new dispatcher");
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
// Make a blocking call to initialize the cache.
mCache.initialize();
Request<?> request;
while (true) {
// release previous request object to avoid leaking request object when mQueue is drained.
request = null;
try {
// Take a request from the queue.
request = mCacheQueue.take();
} catch (InterruptedException e) {
// We may have been interrupted because it was time to quit.
if (mQuit) {
return;
}
continue;
}
try {
request.addMarker("cache-queue-take");
// If the request has been canceled, don't bother dispatching it.
if (request.isCanceled()) {
request.finish("cache-discard-canceled");
continue;
}
// Attempt to retrieve this item from cache.
Cache.Entry entry = mCache.get(request.getCacheKey());
if (entry == null) {
request.addMarker("cache-miss");
// Cache miss; send off to the network dispatcher.
mNetworkQueue.put(request);
continue;
}
// If it is completely expired, just send it to the network.
if (entry.isExpired()) {
request.addMarker("cache-hit-expired");
request.setCacheEntry(entry);
mNetworkQueue.put(request);
continue;
}
// We have a cache hit; parse its data for delivery back to the request.
request.addMarker("cache-hit");
Response<?> response = request.parseNetworkResponse(
new NetworkResponse(entry.data, entry.responseHeaders));
request.addMarker("cache-hit-parsed");
if (!entry.refreshNeeded()) {
// Completely unexpired cache hit. Just deliver the response.
mDelivery.postResponse(request, response);
} else {
// Soft-expired cache hit. We can deliver the cached response,
// but we need to also send the request to the network for
// refreshing.
request.addMarker("cache-hit-refresh-needed");
request.setCacheEntry(entry);
// Mark the response as intermediate.
response.intermediate = true;
// Post the intermediate response back to the user and have
// the delivery then forward the request along to the network.
final Request<?> finalRequest = request;
mDelivery.postResponse(request, response, new Runnable() {
#Override
public void run() {
try {
mNetworkQueue.put(finalRequest);
} catch (InterruptedException e) {
// Not much we can do about this.
}
}
});
}
} catch (Exception e) {
VolleyLog.e(e, "Unhandled exception %s", e.toString());
}
}
As you can see a new request object is created before it takes from the queue. This overcomes the problem of memory leak.
P.S: Don't use Volley from the Google repository as it is deprecated and has this bug since then. In order to use Volley, go for this :
https://github.com/mcxiaoke/android-volley
The above repository is free from any memory leaks whatsoever. Ciao.

How can I run an AsyncTask with a dialog after finishing activity?

I have two activities, one for displaying entries and another for creating them. Here's a standard use case:
User opens app and it displays entries.
User clicks button to create new entry and it opens the new activity.
User finishes creating entry and clicks "Done".
Activity finishes with setResult() and finish().
What I want to add is an AsyncTask that runs after the viewing activity is completely loaded. This AsyncTask shows a dialog while it's running. The problem is, when I put this code into onActivityResult() like this:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(resultCode) {
case (Activity.RESULT_OK): {
mEntryListFragment.updateContent();
runAsyncTaskHere();
}
}
}
It runs the AsyncTask before it goes back to the main activity, and no dialog shows. Any ideas what I can do?
Edit: here's the AsyncTask.
public static class LogInTask extends AsyncTask<String, Void, Integer> {
protected String username = "";
protected String password = "";
protected ProgressDialog dialog;
protected boolean showDialogs;
public LogInTask(boolean sd) {
this.showDialogs = sd;
}
#Override
protected void onPreExecute() {
if (this.showDialogs) dialog = ProgressDialog.show(MainActivity.getContext(), null, "Logging in...");
}
#Override
protected Integer doInBackground(String... login) {
if (Config.DEBUG) Log.d(Config.APP_NAME, "in doInBackground() of LogInTask");
HttpResponse response = null;
String username = login[0];
String password = login[1];
try {
HttpPost httpPost = new HttpPost(URL_BASE + URL_LOGIN);
// main (JSON) login method
JSONObject json = new JSONObject().put("user",
new JSONObject()
.put("email", username)
.put("password", password)
.put("remember_me", Config.REMEMBER_LOGIN)
);
this.username = username;
this.password = password;
StringEntity se = new StringEntity(json.toString());
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
httpPost.setEntity(se);
response = httpclient.execute(httpPost);
String responseEntity = EntityUtils.toString(response.getEntity());
JSONObject result = new JSONObject(responseEntity);
return result.getBoolean("success") ? 1 : KEY_ERROR; // Return 1 if successful and -1 if not
} catch (UnknownHostException e) {
e.printStackTrace();
KEY_ERROR;
} catch (Exception e) {
e.printStackTrace();
return KEY_ERROR;
}
}
#Override
protected void onPostExecute(Integer result) {
if (this.showDialogs) {
dialog.dismiss();
String text = result == 1 ? "Login was successful." : "Login failed!";
makeToast(text);
}
}
}
Edit 2: I tried this:
boolean needToUpdate = false;
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(resultCode) {
case (Activity.RESULT_OK): {
mEntryListFragment.updateContent();
needToUpdate = true;
}
}
}
#Override
public void onResume() {
super.onResume();
if (needToUpdate) {
runAsyncTaskHere();
mEntryListFragment.updateContent();
}
needToUpdate = false;
}
and it did the same thing.
Edit 3: here're the relevant sections of the AndroidManifest:
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".AddEntryActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:configChanges="orientation" />
AsyncTask is a class for background processing, please, don't try to use it to do something with your UI or Activities, it always leads to a bad and unpredictable behaviour.
Maybe I should elaborate a little. Activities come and go, get killed and restored, destroyed and recreated as a usual way of theirs lives. It's absolutely normal.
Your AsyncTask may easily outlive your Activity, so when you're trying to access UI, it's already gone. Destroyed and recreated again, and all you've got is a dead pointer, which gives you an exception. Load your files in AsyncTask, do networking, access database. Just don't try to access UI/Activities, or your application will eventually crash and burn.
When you click on the Button to create new Entry, launch New Activity. but keep the Activity with entries. do not call finish() after intent.
After creation, and on clicking DONE, just close the Current Activity.(call finish())
mEntryListFragment.updateContent write this method in onStart() of the activity displaying entries.
Use ProgressDialog to achieve this.Start the dialog onPreExecute() and finish it onPostExecute() methods.You have to override those methods in your async task.
i think , you have to use Concept of callbacks ,
like when ever , loading is complete , implement your callback inside which you can deal with AsyncTask and after performing your task inside doInBackGround() , you can use onPostExecute() .
try something like this ,
Callback_interface
{
void async_run_after_some_time() ;
}
main_activity_class extends Activity Implements Callback_interface
{
void async_run_after_some_time()
{
// implement your toast here
}
}
onPostExecute()
{
main_activity_class ob = new main_activity_class ();
ob.async_run_after_some_time();
}
Just a thought.
Are you sure you are retrieving the proper context.
Is the boolean set correctly?
Plus, I do believe you are using HttpCore. From what I remember it requires some more attention networking and dis/connection wise due to it's granularity (compared to the HttpConnection class available by default). As such I don't think it is the best to use it with AsyncTask classes since they have little connection with the UI thread. Thus don't give much control for the user and may live beyond application's lifespan.

Android Honeycomb: Fragment not able to start AsyncTask?

I've run into this error before, but thought it was some mistake by the strict mode system. However, it apparently was right as I sadly found out now. :(
My programm is made of one Activity and loads of Fragments. I have a NetworkWorker fragment, which starts URL requests like this:
public void startURLRequest(Fragment target, String url, String message)
{
if (asyncTask != null) asyncTask.cancel(true);
asyncTask = new FragmentHttpHelper(url, message, target);
asyncTask.doInBackground();
return;
}
FragmentHttpHelper is a custom inner class derived from AsyncTask:
private class FragmentHttpHelper extends AsyncTask<Void, Void, String>
{
//...
#Override
protected String doInBackground(Void... params)
{
if (CheckInternet())
{
try
{
URL myURL = new URL(url);
httpClient = new DefaultHttpClient();
if (this.message == null)
{
httpRequest = new HttpGet(myURL.toExternalForm());
}
else
{
httpRequest = new HttpPost(myURL.toExternalForm());
HttpEntity myEntity = new StringEntity(message, "UTF-8");
((HttpPost) httpRequest).setEntity(myEntity);
}
// and so on...
}
//catches
finally
{
// auf jeden Fall Verbindung beenden
if (httpRequest != null) httpRequest.abort();
// if (httpClient != null) httpClient.close();
}
}
else
{
showDialog(getString(R.string.net_notify_no_network), target);
}
//...
}
/**
* gets called after AsyncTask has finished
*/
protected void onPostExecute(String result)
{
if (target == null)
{
((NetworkWorkerListener) getActivity()).onDownloadHasFinished((!result.contentEquals(ERROR)), result);
}
else
{
((NetworkWorkerListener) target).onDownloadHasFinished((!result.contentEquals(ERROR)), result);
}
}
}
NetworkWorkerListener is just an interface for a callback on the Fragment which started the URL request. This class has always worked fine when I used it in my 2.2 app. I would derive it in my Activities then.
Now, if a menu item is selected, another worker Fragment starts the URL request via the above method and opens a loading dialog:
FragmentManager fragmentManager = getFragmentManager();
NetworkWorker network = (NetworkWorker) fragmentManager.findFragmentByTag(TabletMain.NETWORK);
if (network == null) return WorkerFeedback.NO_NETWORK_WORKER;
myDialog = LoadingDialog.createInstance(getString(R.string.notify_download), this);
myDialog.show(fragmentManager, TabletMain.ONETIME);
network.startURLRequest(this, someurl, null);
At least that's what supposed to happen.
Instead, when I click the menu item, my app freezes and no loading dialog is shown until. Next happening is the reaction to the end of the download (or, in my case an error message, as I am sending nonsense strings). Meaning onPostExecute() was reached.
I feel really stuck now - is it not possible to use AsyncTask with Fragments? Or did I do something wrong?
Thanks for your help,
jellyfish
Don't call doInBackground directly, call execute instead (on the async task)

Categories

Resources