I have a screen that overlays the SpenSurfaceView with Android layout components. When the user switches the screen to load different components, the old components leak into this class:
com.samsung.android.sdk.pen.engine.SpenInView
from the native stack according to MAT (Memory Analyzer T)
The overlayed components are custom controllers to take in user input in the form of strokes. They have a reference to the SurfaceView, but it is nulled before the components are deleted.
The problem remains even if I completely exit the application.
I am using example PenSample5_6_TextRecognition as reference.
This is using Samsung Mobile SDK (http://developer.samsung.com/samsung-mobile-sdk)
What strategy should I employ to continue to chase this memory leak ?
The NDK side of the SDK is likely closed source.
Does the SpenObjectBase retains references to the SpenSurfaceView ?
Can somebody with more reputation than I have create the "spen sdk" tag.
Please check onDestroy() from sample application. Do you close all resources?
#Override
protected void onDestroy() {
super.onDestroy();
if (mTextRecognition != null) {
mSpenTextRecognitionManager.destroyRecognition(mTextRecognition);
mSpenTextRecognitionManager.close();
}
if (mSpenSurfaceView != null) {
mSpenSurfaceView.closeControl();
mSpenSurfaceView.close();
mSpenSurfaceView = null;
}
if(mSpenNoteDoc != null) {
try {
mSpenNoteDoc.close();
} catch (Exception e) {
e.printStackTrace();
}
mSpenNoteDoc = null;
}
}
Samples are closing resources in onDestroy. That may happen well after user leaves activity (even never if device has enough memory). Consider releasing resources in onPause and re-creating them in onResume instead.
Finally, in my code I am removing registred callbacks
private void removeListeners() {
spenPageDocContainingNoteDoc.setObjectListener(null);
try {
spensBasicShapeConverter.setResultListener(null);
} catch (Exception e) {
..
}
When investingating heap dumps, I saw my Activity (callback handler) held inside some data structure in Spen API. Removing listeners removed that memory leak.
Related
I want to make some classes that catch runtime errors on android and offers the user the option to restore the last saved instance state of the app.
I was thinking of extending the Activity and Fragment classes and implement something that saves their state. In the meantime, another class handles every start of an activity or fragment, putting them in a stack.
I want to catch every possible exception in the app, hopefully making errors less bothersome for the user.
Any advice on how I should handle this?
How would this error checking influence the performance of an app?
It's not a good solution and i don't know if it's useful for you, but you can caught exceptions in Application Class.
public class MyApplication extends Application
{
public void onCreate ()
{
// Setup handler for uncaught exceptions.
Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler()
{
#Override
public void uncaughtException (Thread thread, Throwable e)
{
handleUncaughtException (thread, e);
}
});
}
public void handleUncaughtException (Thread thread, Throwable e)
{
e.printStackTrace();
// do what ever you want.
}
}
You can use try catch blocks to catch runtime errors. If you use try catch efficiently with throws your app won't crash in first place hence no need to maintain stack of activities. btw maintaining stacks of previous activity in neither memory efficient nor advisable.
I'm developing an Android app that has to update it's UI depending on receiving and processing some server responses, I'm using runOnUiThread for that. I have like five activities in that app, all is working very well but one requires me to relaunch the Activity(like going to another one and then returning to it) or interacting with it in order to that update takes place, and that is the way i'm using with all the Activities including the infected one:
runOnUiThread(new Runnable() {
public void run() {
try {
response_received(response);
} catch (Exception e) {
e.printStackTrace(); // never catch any Exceptions
}
}
});
private static void response_received(JSONObject response) throws Exception{
try {
int volume_setted = response.getInt(volume);
Normal_Activity.volume_value.setText(String.valueOf(volume_setted)); // the Volume TextView updated efficiently
Infected_Activity.volume_value.setText(String.valueOf(volume_setted)); // has the problem mentioned above
} catch (JSONException ex) {
}
}
I'm pretty sure the problem is not in the TextView as all the Activity UI has this problem but i just posted an example.
Do not directly set values in a Activity from another Activity. If you want to pass data to Another activity always use Intents. check the below link
pass data from intent to an other intent
If you want to start another activity and get result back check the below link
http://developer.android.com/training/basics/intents/result.html
I have an android (4.1) application which reportedly (can't recreate) chrashes with the message "app as stopped". The problem, however, is that the user has to press "OK" in the alert that pops up. The chrash only occur when the app is not active (on screen). This indicates that Android kills of my app because of memory or naughtiness. I'f been investigating for memory leaks, because i handle bitmaps in the app, that did not pay off.
I have a catch and log all default handler like this:
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
public void uncaughtException(Thread thread, Throwable ex) {
Log.e(StaticData.LogTag, "Unhandled exception app", ex);
}
});
To log all exceptions. Afterwards i call original exceptionhandler. This handler is put on the Apps main activity. The method is never called when the "stopped" chrash happens, but is in other cases.
My app uses IntentService to send data to a server in background. This is not a long running service, 1-10s. I will try to put a default exception handler on the service as well. I mention the service because the app is killed when "off screen", so I thought that might have a connection to the problem, but the cause evades me.
Furthermore I use BroadcastReceiver to notify the apps main activity about network connection changes, because the app is used in turbulent network conditions. This is relevant because I'f seen BroadcastReceiver mentioned when people talk about possible memory leak issues. My implementation of BradcastReceiver goes like this:
Serivce side:
sendOrderedBroadcast(uploadedIntent, null);
Activity side:
public static class NetworkStateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent in) {
// super.onReceive(context, intent);
Log.d(StaticData.LogTag, "Network connectivity change");
if (in.getExtras() != null) {
NetworkInfo ni = (NetworkInfo) in.getExtras().get(ConnectivityManager.EXTRA_NETWORK_INFO);
if (ni != null && ni.getState() == NetworkInfo.State.CONNECTED) {
Log.i(StaticData.LogTag, "Network " + ni.getTypeName() + " connected");
...
}
}
if (in.getExtras().getBoolean(ConnectivityManager.EXTRA_NO_CONNECTIVITY, Boolean.FALSE)) {
Log.d(StaticData.LogTag, "There's no network connectivity");
}
}
}
As i mentioned in the beginning, the problem is mainly an annoyance for the user because he has to press ok on a popup when looking at mails or taking a call. The app is robust enough to handle that it gets killed from time to time, however, I would like to figure out why my app is knocked out.
PS. I have tried to get the users to send be bug reports via mx log logcollector, but no cigar.
I seem to have solved this problem. I think the culprit was a static reference to the main activity in the application. I was using this static to get a reference to the applications Context. This however this is unnecessary in Service and BroadcastReceiver, because they have their own ref to a "Context".
Why the long face?
A static reference to a Android view, like Activity, is kept in memory and can't be freed by the garbage collector. This was the idea behind making it static. I wanted to have a future reference to the object, but is the wrong approach.
When changing orientation (eg.), Android recreates the current activity (and children views), and the old is freed for GC. When you have a static ref to a view, its not collected, and now you have 2 instances of the Activity. Do the math and realize that this obviously fills memory over time (leak) and Android will nuke the app at some point.
When facing this problem you have to realize that you have to carry your data/states over to the new Activity, for example by using shared memory, a local database or a savedInstanceState:
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
int value = savedInstanceState.getInteger("key");
}
}
#Override
protected void onSaveInstanceState(final Bundle outState) {
outState.putInteger("key", value);
}
I'm trying to clear some views from memory.
Here's the situation.
I have an Activity that I'll call it A and another B.
Now I press a button in Activity A that calls Activity B that creates a lot of views dynamically
After this, I press back button to return to Activity A
Repeat theses 2 steps a lot of times.
The result is, in DDMS, the number of objects and memory Allocated stills growing ( the number of objects is increased by 88 and Allocated by 0,002MB )
That means the views dont be removed from memory !
How do can I clear the views COMPLETELY from memory ?
Thx !
Update-
Here you go some new information
Basically, on my "real world" I have only one Activity that is created a lot of times. This occurs because I it have to communicate to a webservice and all the responses are created in that new instance of this Activity.
I tried to resolve this issue with the code below
#Override
protected void onDestroy() {
super.onDestroy();
nullViewDrawablesRecursive(mRootView);
mRootView = null;
System.gc();
}
and that is my nullViewDrawablesRecursive
private void nullViewDrawablesRecursive(View view) {
if (view != null) {
try {
ViewGroup viewGroup = (ViewGroup) view;
int childCount = viewGroup.getChildCount();
for (int index = 0; index < childCount; index++) {
View child = viewGroup.getChildAt(index);
nullViewDrawablesRecursive(child);
}
} catch (Exception e) {
}
nullViewDrawable(view);
}
}
And that is my nullViewDrawable
private void nullViewDrawable(View view) {
try {
view.setBackgroundDrawable(null);
} catch (Exception e) {
}
try {
ImageView imageView = (ImageView) view;
imageView.setImageDrawable(null);
imageView.setBackgroundDrawable(null);
} catch (Exception e) {
}
}
Basically I'm trying to remove all the views and childs from their parent (mRootView) before destroying the activity. It works pretty well, if I don't do this, the objects and memory usage increase more and more.
The point is, it's not perfect, apparently some type of views doesn't be destroyed. And I think I'm "reinventing the wheel", it seems to damn hard for a simple thing !
Again, thanks a lot for trying to help me!
Typically, you don't need to worry about clearing views from memory. You would let the virtual machine and Android framework handle this when it is necessary. However, you do need to be concerned with memory leaks. If your Activities are sharing/holding onto references to views, and they cannot be garbage collected, then that is a problem. You can start by reading about that here: http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html
Its hard to provide some more specific advice without seeing you code though...
In onDestroy() set the views to null and call the garbage collector.
#Override
public void onDestroy() {
super.onDestroy();
myView = null;
System.gc();
}
This can help the garbage collector by calling System.gc() but it isn't guaranteed that the memory is cleared. However as long as you don't have a leak, there shouldn't be a problem.
I am making an android game using the SurfaceView/Thread model seen in many of the examples. I am trying to split the components into multiple activities. Right now I have a menu activity and a game activity. For some reason when I attempt to finish the game activity to return to the menu activity my app will become unresponsive. It seems to work fine on the emulator but on my device (Samsung Mesmerize) it will become unresponsive. I have a feeling this is because a thread is still busy in the game activity but I have no idea how to kill the thread. I tried breaking the game loop as well and that did not seem to help.
My SurfaceView has an inner thread class, here is the implementation of run()
public void run()
{
_isRunning = true;
Canvas c = null;
while(_isRunning)
{
try
{
c = _surfaceHolder.lockCanvas();
synchronized(_surfaceHolder)
{
if(_engine != null)
{
_engine.gameLogic();
if(c != null)
_engine.draw(c);
}
}
}
finally
{
if(c != null)
_surfaceHolder.unlockCanvasAndPost(c);
}
}
}
I found the solution to my problem after an hour or two of debugging. I had to keep track of whether the surface was alive before calling lockCanvas(). I used this same loop in both activities and calling lockCanvas() after the surface from the game activity was destroyed was causing problems.