2012-02-04 136 views
0

我發現了這段代碼。這應該讀取framebuffer並將其保存爲一個PNG文件。以當前屏幕截圖

它給人的錯誤:

eglCreateWindowSurface() can only be called with an instance 
of SurfaceView or SurfaceHolder at the moment, this will be fixed later. 

代碼:

private EGL10 egl; 
    private EGLDisplay display; 
    private EGLConfig config; 
    private EGLSurface surface; 
    private EGLContext eglContext; 
    private GL11 gl; 
    //private GL10 gl10; 
    protected int width, height; 
    Bitmap mSavedBM; 

    public void Take(Context context) 
    { 
     Display display= ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();   
     int screenWidth = display.getWidth(); 
     int screenHeight = display.getHeight();  
     String SCREENSHOT_DIR = "/sdcard/screenshots"; 
     initGLFr(); //GlView initialized. 
     savePixels(0, 10, screenWidth, screenHeight, gl); //this gets the screen to the mSavedBM. 
     saveBitmap(mSavedBM, SCREENSHOT_DIR, "capturedImage"); 
    } 

    private void initGLFr() 
    { 
     egl = (EGL10) EGLContext.getEGL(); 
     display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 
     int[] ver = new int[2]; 
     egl.eglInitialize(display, ver); 
     int[] configSpec = {EGL10.EGL_NONE}; 
     EGLConfig[] configOut = new EGLConfig[1]; 
     int[] nConfig = new int[1]; 
     egl.eglChooseConfig(display, configSpec, configOut, 1, nConfig); 
     config = configOut[0]; 
     eglContext = egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, null); 
     surface = egl.eglCreateWindowSurface(display, config, SurfaceHolder.SURFACE_TYPE_GPU, null); 
     egl.eglMakeCurrent(display, surface, surface, eglContext); 
     gl = (GL11) eglContext.getGL(); 
    } 

    public void savePixels(int x, int y, int w, int h, GL10 gl) 
    { 
     if (gl == null) 
     { 
      return;   
     } 
     synchronized (this) 
     { 
      if (mSavedBM != null) 
      { 
       mSavedBM.recycle(); 
       mSavedBM = null; 
      } 
     } 
     int b[] = new int[w * (y + h)]; 
     int bt[] = new int[w * h]; 
     IntBuffer ib = IntBuffer.wrap(b); 
     ib.position(0); 
     gl.glReadPixels(x, 0, w, y + h, GL10.GL_RGBA,GL10.GL_UNSIGNED_BYTE,ib); 
     for (int i = 0, k = 0; i < h; i++, k++) 
     { 
      //OpenGLbitmap is incompatible with Android bitmap 
      //and so, some corrections need to be done. 
      for (int j = 0; j < w; j++) 
      { 
       int pix = b[i * w + j]; 
       int pb = (pix >> 16) & 0xff; 
       int pr = (pix << 16) & 0x00ff0000; 
       int pix1 = (pix & 0xff00ff00) | pr | pb; 
       bt[(h - k - 1) * w + j] = pix1; 
      } 
     } 
     Bitmap sb = Bitmap.createBitmap(bt, w, h, Bitmap.Config.ARGB_8888); 
     synchronized (this) 
     { 
      mSavedBM = sb; 
     } 
    } 

    static String saveBitmap(Bitmap bitmap, String dir, String baseName) 
    { 
     try 
     { 
      File sdcard = Environment.getExternalStorageDirectory(); 
      File pictureDir = new File(sdcard, dir); 
      pictureDir.mkdirs(); 
      File f = null; 
      for (int i = 1; i < 200; ++i) 
      { 
       String name = baseName + i + ".png"; 
       f = new File(pictureDir, name); 
       if (!f.exists()) 
       { 
        break; 
       } 
      } 
      if (!f.exists()) 
      { 
       String name = f.getAbsolutePath(); 
       FileOutputStream fos = new FileOutputStream(name); 
       bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); 
       fos.flush(); 
       fos.close(); 
       return name; 
      } 
     } 
     catch (Exception e) {} 
     return null; 
    } 

}

問題:

此代碼是否採取截圖在這個時候我的應用程序是在後臺或者只是製作screensho我的應用程序的ts?

回答

3

你不能截圖(這將是一個安全漏洞),只有系統應用程序可以做到這一點。 此方法很可能會保存黑色PNG。

1

您需要爲您的設備創建根目錄否則它將無法工作。另外你必須讓你的應用程序獲得超級用戶訪問權限。只是實現這個代碼,你會很好去:

public void screenShot() throws InterruptedException 
{ 
    Process sh; 
    try 
    { 
     sh = Runtime.getRuntime().exec("su", null, null); 
     OutputStream os = sh.getOutputStream(); 
     os.write(("/system/bin/screencap -p " + "/sdcard/Image.png").getBytes("ASCII")); 
     os.flush(); 
     os.close(); 
     sh.waitFor(); 
    } 
    catch (IOException e) 
    { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

} 
+1

感謝您的回覆!大約一年前我已經這樣做了。我用完全和你的答案一樣))) – XXX 2014-03-21 13:38:14