0

Im having a bug on some devices that sometimes give an ANR when starting a new activity. I have a small degree of lag on my device (Samsung Galaxy S2) but I never get an ANR. The other devices that sometimes gets an ANR is: HTC Desire HD and Xperia(That I know of). Im thinking that it could be somekind of cpu intensive thing I do that makes older phones lag more than newer ones, but I dont know. Im using an Asynctask to load all the heavy stuff and the ui thread doesnt really do much.

Heres the code

I create a separate thread here to access the shared preferences.

  @Override
    protected void onResume() {
        super.onResume();
        sound = false;
        Thread prefThread = new Thread(new Runnable(){
            public void run(){
                SharedPreferences prefs = getSharedPreferences(SharedPrefValues.OPTION_PREF, Context.MODE_PRIVATE);
                sound = prefs.getBoolean("sound", true);
                String difficulty = prefs.getString(SharedPrefValues.DIFFICULTY, SharedPrefValues.DIF_MEDIUM);
                prefs = getSharedPreferences(SharedPrefValues.HIGHSCORE_PREF, Context.MODE_PRIVATE);
                for(int i = 0; i < mapPnl.buttons.size(); i++)
                    mapPnl.SetRank(mapPnl.buttons.get(i), prefs.getString(SharedPrefValues.HIGHSCORE_RANK_NAME + difficulty + mapPnl.buttons.get(i).getName(), SharedPrefValues.RANK_NOT_OK));

            }
        });
        prefThread.start();
        mapPnl.speedX = 0;
    }

bgTask is an AsyncTask.

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
                WindowManager.LayoutParams.FLAG_FULLSCREEN); 


        Display display = getWindowManager().getDefaultDisplay();
        screenSize = new Point();
        screenSize.x = display.getWidth();
        screenSize.y = display.getHeight();


        mapPnl = new MapPnl(this);

        LoadBitmapsStuff bgTask = new LoadBitmapsStuff(this);
        bgTask.execute();

        addContentView(mapPnl, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
    }

This is the Surfaceview that draws everything and takes care of onTouchEvents

private class MapPnl extends SurfaceView implements SurfaceHolder.Callback{
...
public MapPnl(Context context) {
            super(context);
            getHolder().addCallback(this);

            buttons = new ArrayList<ButtonMap>();

            posX = 0;
            speedX = 0;
            maxX = 0;

            drawThread = new DrawThread(getHolder());
            drawThread.setRunning(true);
        }
....
}

I start the drawThread in surfaceCreated

    public void surfaceCreated(SurfaceHolder arg0) {
        if(drawThread.getState() == Thread.State.NEW)
            drawThread.start();
        else if(drawThread.getState() == Thread.State.TERMINATED){
            drawThread = new DrawThread(getHolder());
            drawThread.setRunning(true);
            drawThread.start();
        }
    }

Surfacedestroyed from guide on the web

    public void surfaceDestroyed(SurfaceHolder arg0) {
        boolean retry = true;
        drawThread.setRunning(false);
        while (retry) {
            try {
                drawThread.join();
                retry = false;
            } catch (InterruptedException e) {
                // we will try it again and again...
            }
        }

    }

I think that is the important code. As far as I know the UIthread only runs trough these parts Ive shown (maybe not the ondestroy but i read that someone had a problem with that one in another thread.). And that should run pretty fast on most systems.

The drawthread only displays a text that says "loading" until the asyncTask is done running. So when everything is loaded and drawn the user starts touching the screen and thats when the ANR comes up. Any tips?

Update (12-05-18): I managed to get a logcat from the emulator. I used a slow computor, when I used a fast computor the ANR didnt show up.

PID 860 is the activity

03-31 01:41:03.453: I/Process(71): Sending signal. PID: 860 SIG: 3
03-31 01:41:03.453: I/dalvikvm(860): threadid=3: reacting to signal 3
03-31 01:41:03.672: I/dalvikvm(860): Wrote stack traces to '/data/anr/traces.txt'
03-31 01:41:03.672: I/Process(71): Sending signal. PID: 71 SIG: 3
03-31 01:41:03.682: I/dalvikvm(71): threadid=3: reacting to signal 3
03-31 01:41:03.992: I/dalvikvm(71): Wrote stack traces to '/data/anr/traces.txt'
03-31 01:41:03.992: I/Process(71): Sending signal. PID: 381 SIG: 3
03-31 01:41:03.992: I/dalvikvm(381): threadid=3: reacting to signal 3
03-31 01:41:04.212: I/Process(71): Sending signal. PID: 349 SIG: 3
03-31 01:41:04.212: I/dalvikvm(349): threadid=3: reacting to signal 3
03-31 01:41:04.322: I/dalvikvm(349): Wrote stack traces to '/data/anr/traces.txt'
03-31 01:41:04.332: I/Process(71): Sending signal. PID: 664 SIG: 3
03-31 01:41:04.364: I/dalvikvm(664): threadid=3: reacting to signal 3
03-31 01:41:04.542: I/Process(71): Sending signal. PID: 364 SIG: 3
03-31 01:41:04.612: I/dalvikvm(364): threadid=3: reacting to signal 3
03-31 01:41:04.744: I/Process(71): Sending signal. PID: 371 SIG: 3
03-31 01:41:04.953: I/Process(71): Sending signal. PID: 822 SIG: 3
03-31 01:41:05.162: I/Process(71): Sending signal. PID: 139 SIG: 3
03-31 01:41:05.162: I/dalvikvm(139): threadid=3: reacting to signal 3
03-31 01:41:05.221: I/dalvikvm(822): threadid=3: reacting to signal 3
03-31 01:41:05.292: I/dalvikvm(371): threadid=3: reacting to signal 3
03-31 01:41:05.312: I/dalvikvm(139): Wrote stack traces to '/data/anr/traces.txt'
03-31 01:41:05.402: E/ActivityManager(71): ANR in se.blogspot.developingjsa.view (se.blogspot.developingjsa.view/.FirstMenu)
03-31 01:41:05.402: E/ActivityManager(71): Reason: keyDispatchingTimedOut
03-31 01:41:05.402: E/ActivityManager(71): Load: 1.79 / 1.63 / 1.31
03-31 01:41:05.402: E/ActivityManager(71): CPU usage from 5383ms to 64ms ago:
03-31 01:41:05.402: E/ActivityManager(71):   elopingjsa.view: 51% = 49% user + 1% kernel / faults: 36 minor 7 major
03-31 01:41:05.402: E/ActivityManager(71):   system_server: 44% = 41% user + 3% kernel / faults: 133 minor 1 major
03-31 01:41:05.402: E/ActivityManager(71):   adbd: 1% = 0% user + 0% kernel
03-31 01:41:05.402: E/ActivityManager(71):   m.android.phone: 1% = 0% user + 0% kernel / faults: 112 minor
03-31 01:41:05.402: E/ActivityManager(71):   ronsoft.openwnn: 0% = 0% user + 0% kernel / faults: 22 minor
03-31 01:41:05.402: E/ActivityManager(71):   com.svox.pico: 0% = 0% user + 0% kernel / faults: 7 minor
03-31 01:41:05.402: E/ActivityManager(71):   logcat: 0% = 0% user + 0% kernel
03-31 01:41:05.402: E/ActivityManager(71):   qemud: 0% = 0% user + 0% kernel
03-31 01:41:05.402: E/ActivityManager(71):   id.defcontainer: 0% = 0% user + 0% kernel / faults: 6 minor
03-31 01:41:05.402: E/ActivityManager(71):   ackageinstaller: 0% = 0% user + 0% kernel / faults: 5 minor
03-31 01:41:05.402: E/ActivityManager(71): TOTAL: 100% = 91% user + 8% kernel + 0% irq + 0% softirq
Joakim Palmkvist
  • 540
  • 2
  • 11
  • I havent been able to test those devices with adb and logcat enabled :/ – Joakim Palmkvist May 17 '12 at 18:14
  • What? you have logcat from emulator aswell... – Anders Metnik May 17 '12 at 20:25
  • So your surfaceDestroyed method is blocking, waiting for drawThread to finish? That’s at least one problem—the UI thread is not allowed to block for ANY reason. – Lawrence D'Oliveiro May 18 '12 at 02:55
  • @AndersMetnik: The devices that gets an ANR isnt mine, so I havent been able to use the adb on them. I hadnt thought of trying to get the error on the emulator though, and using a slow computor I managed to get a logcat of it. I posted it in the original post. – Joakim Palmkvist May 18 '12 at 08:04
  • @LawrenceD'Oliveiro I thought that the surfaceDestroyed method only was called when the activity is destroyed. In this case the ANR comes when the activity is created. – Joakim Palmkvist May 18 '12 at 08:06

1 Answers1

0

Its solved now.

I was able to get a stack trace from those devices using google play. Turns out it wasnt anything wrong with the code i posted up there.

I was using code from a tutorial ( http://www.droidnova.com/playing-with-graphics-in-android-part-i,147.html ). That code was trying to get the surfaceHolder from the drawThread everytime an onTouchEvent happened.

I guess that sometimes the drawThread was inside its loop and couldnt release the surfaceHolder when the UiTread was trying to grab it, resulting in an ANR.

Joakim Palmkvist
  • 540
  • 2
  • 11