1

I want quite simple thing - to know when is my activity completely loaded and presenting itself on the screen - that is when I want a piece of code to run. That piece of code starts by taking a screenshot and running some animations on it. I wrote that code in onResume() and everything is fine during normal start up, but when I rotate the device the screenshot is taken from the previous orientation, although all the display parameter dumps show that the orientation is already changed. It seems like the system re-creates, re-runs and re-draws my Activity still physically showing the previous state and then it runs the system rotation animation between 2 states and finally shows my Activity. This also implies that any android app starting any animation in onResume will lose the first X milliseconds of it because of the system rotation animation (X can be of 3 different values depending on rotation). I tried over 40 on...() functions like onAttachedToWindow() but they are all called too early. Waiting some time before starting is not good since I will have latency during normal start up and the waiting time is not well defined.

Since I am part of the system I have one solution by adding some codes deep in the window manager which I can ask to know if system rotation animation is running, but it is not elegant and is not a solution for any "normal" app. I also want to keep the rotation animation. Just wondering if there is an event or function in the public API to use.

frangulyan
  • 3,580
  • 4
  • 36
  • 64

1 Answers1

2

I would try a ViewTreeObserver with OnGlobalLayoutListener as described here: How can you tell when a layout has been drawn?

EDIT: I created a sample working implementation. It is capturing the screen after the orientation change as you asked for.

Not possible to get the status bar without root: (android development)how to implement screen grab with status bar in code

However, is possible to remove the blank space where the status bar goes: Android screenshot of activity with actionbar

public class MainActivity extends Activity
{
    private static int counter = 1;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final View root = getWindow().getDecorView();
        ViewTreeObserver vto = root.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

            @Override
            public void onGlobalLayout()
            {
                root
                .getViewTreeObserver()
                .removeOnGlobalLayoutListener(this);

                takeScreenShot(root);
                ++counter;
            }

        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    private void takeScreenShot(View view)
    {
        String mPath = Environment.getExternalStorageDirectory().toString() 
                + "/" + "rotation" + String.valueOf(counter);   

        // create bitmap screen capture
        Bitmap bitmap;

        view.setDrawingCacheEnabled(true);
        bitmap = Bitmap.createBitmap(view.getDrawingCache());
        view.setDrawingCacheEnabled(false);

        OutputStream fout = null;
        File imageFile = new File(mPath);

        try {
            fout = new FileOutputStream(imageFile);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout);
            fout.flush();
            fout.close();

        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }   
}
Community
  • 1
  • 1
Steve M
  • 9,296
  • 11
  • 49
  • 98
  • I will try this soon, but something is telling me that it will not work. What I noticed is that on rotation the window system lays everything out in new orientation, draws the view to some bitmap and uses that bitmap for rotation animation as something to bring the screen to. The activity doesn't know why exactly it was created, laid out and drawn - either to show on screen or to put it on a temporary bitmap and use in some system animation. But at least this is another direction in which I can experiment, thanks. – frangulyan Dec 24 '13 at 17:16
  • Hey are you taking the screenshot shot with View.getDrawingCache()? If so I really think the ViewTreeObserver should work. Once the view is completely drawn, the drawing cache should have the new view regardless of if the animation has completed or not. – Steve M Dec 24 '13 at 18:46
  • No, I'm taking a screenshot of the whole screen, using the frame buffer. I need to screenshot any other app that is in the background - what user sees currently. – frangulyan Dec 28 '13 at 16:49