android taking screenshot of offscreen page

2019-01-06 11:47发布

问题:

I am working on an android application. I have an activity, say A, which fills the entire screen with views..On a button click in A I want to start another activity, say B, which also has some views and controls. I want activity B to be offscreen , and want to take the screenshot of B from A . Is it possible?

Note: I am successful in taking the screenshot of page A by saving the drawing cache in to a bitmap, but struggling to take the offscreen page's screenshot.

回答1:

Yes it is possible...You should extend ActivityGroup in Activity 'A'. Then do this in your button click event...

 View view =getLocalActivityManager().startActivity("B",new Intent(this,B.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)).getDecorView();

then convert that view as bitmap...

I think this is helpful for you...



回答2:

Well I have achieved what I want. These are the steps I used.

  1. Start activity B with startActivityForResult() instead of startActivity().

    Intent bIntent = new Intent(A.this,B.class);
    startActivityForResult(bIntent,B_REQUEST_CODE);
    
  2. In onCreate of activity B take mainLayout of B and enable its drawing cache

    final LinearLayout layout = (LinearLayout)
                         findViewById(R.id.app_parent_layout);
    layout.setDrawingCacheEnabled(true);
    layout.setDrawingCacheQuality(LinearLayout.DRAWING_CACHE_QUALITY_HIGH);
    
  3. In activity B wait till its layout is drawn completely(This is very important). For that in onCreate() of activity B, get mainLayout of B, use ViewTreeObserver to get a call back when its layout is drawn completely.

    ViewTreeObserver vto = layout.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
     @Override
     public void onGlobalLayout() {
      layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
      getDrawingBitmap();
     }
    });
    
  4. Now getDrawingBitmap() gets called when layout is drawn completely. There take your screenshot.

    public void getDrawingBitmap(){
        LinearLayout mainLayout = (LinearLayout)
                            findViewById(R.id.app_parent_layout);
        Bitmap b = mainLayout.getDrawingCache();
    
        File file = saveBitmapAsFile(b);
    
        Intent resultIntent = new Intent();
        resultIntent.putExtra("FullFileName",file.getAbsolutePath());
        setResult(Activity.RESULT_OK,resultIntent);
        finish();
    }
    

    Here I am taking bitmap and saving it as a file and returning the filename as a result code. I am sure there are better method to send the bitmap to parent activity than saving as a file and sending filename. But I have a requirement anyway to save bitmap for sometime. So For me this is the easier method. After setting result finish activity.

  5. Now on Activity A onActivityResult() retrieve the filename.

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
      super.onActivityResult(requestCode, resultCode, data);
      if(requestCode == B_REQUEST_CODE){
        if (resultCode == Activity.RESULT_OK) { 
          String newText = data.getStringExtra("FullFileName");
         File dir = new File (newText);
        } 
      }
    }
    


回答3:

I think it would be very hard to do so, as I know no way to get in control of the drawing methods of those views, and the android OS won't draw them either unless visible.

However it may be possible to foreground the other View for only a short time to fill its drawing cache. Maybe it can be put background again before it even becomes visible, as for smooth experience the OS seems to draw views offscreen before they are actually composed to foreground.

Another trick could be to attach your foreground View as an child View onto the background, and give it a very slight alpha transparency. The WebView for example can be superimposed this way very well, actually forcing both the WebView and its background to be drawn. Maybe this works with other Views too.



回答4:

i m using this way its working great but there is an issue i m just taking snapshots of one layout first time when i take the snapshoot it gives me right pic but after some changes i take it again it gives me previous snapshoot.

RelativeLayout layout = (RelativeLayout)findViewById(R.id.mainview);
    layout.setDrawingCacheEnabled(true);
    layout.setDrawingCacheQuality(LinearLayout.DRAWING_CACHE_QUALITY_HIGH);
    layout.buildDrawingCache();
    Bitmap bitmap = layout.getDrawingCache();

          File file =  new File(Environment.getExternalStorageDirectory().toString() + "/sPenimg.png");
          FileOutputStream ostream;
          try {
              ostream = new FileOutputStream(file);
              bitmap.compress(CompressFormat.PNG, 100, ostream);
              ostream.flush();
              ostream.close();      
          } catch (FileNotFoundException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          } catch (IOException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }

This issue is solved to add ((RelativeLayout)findViewById(R.id.mainview)).destroyDrawingCache();