2013-11-22 98 views
14

當我的應用程序每隔200毫秒安裝並在後臺運行並將圖像保存到我的計算機中時,我需要以編程方式以Android設備或模擬器的屏幕截圖。我已經使用下面的代碼實現了此過程,並且僅在我的應用程序處於前景時才起作用。當我的應用程序在後臺時我也想截圖。下面是我的代碼:Android - 如何以編程方式抓取屏幕截圖

public static Bitmap takeScreenshot(Activity activity, int ResourceID) { 
    Random r = new Random(); 
    int iterator=r.nextInt(); 
    String mPath = Environment.getExternalStorageDirectory().toString() + "/screenshots/"; 
    View v1 = activity.getWindow().getDecorView().findViewById(ResourceID); 
    v1.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 
      MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 
    v1.layout(0, 0, v1.getMeasuredWidth(), v1.getMeasuredHeight()); 
    v1.setDrawingCacheEnabled(true); 
    final Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache()); 
    Bitmap resultBitmap = Bitmap.createScaledBitmap(bitmap, 640, 480, false); 
    v1.setDrawingCacheEnabled(false); 
    File imageFile = new File(mPath); 
    imageFile.mkdirs(); 
    imageFile = new File(imageFile+"/"+iterator+"_screenshot.png"); 
    try { 
     ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
     resultBitmap.compress(CompressFormat.PNG, 100, bos); 
     byte[] bitmapdata = bos.toByteArray(); 

     //write the bytes in file 
     FileOutputStream fos = new FileOutputStream(imageFile); 
     fos.write(bitmapdata); 
     fos.flush(); 
     fos.close();  
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    return bitmap; 
    } 

我怎樣才能實現Devices -> DDMS編程的抓屏的刷新和保存按鈕的功能?我可以做到嗎?

+9

這會嚇壞我了,如果這甚至有可能。這樣做的應用程序引起嚴重的安全問題。 –

+1

**除非電話是固定的(* kitkat *)**,否則無法完成此操作。至於「嚴重的安全問題」,我認爲其他地方存在更嚴重的安全問題。如果應用程序可以請求獲取截圖等權限,那不是什麼大問題。 –

+2

這不是一個截圖或其他...這是每200毫秒的截圖。基本上是一個5 FPS的視頻。這可以輕鬆捕獲手機上完成的所有事情。不要爲了我自己的使用而做出反對(製作一個應用程序的視頻),但給第三方應用程序允許截取屏幕截圖會是一個長期的漏洞。 –

回答

15

如果您的手機是植根試試這個

Process sh = Runtime.getRuntime().exec("su", null,null); 

        OutputStream os = sh.getOutputStream(); 
        os.write(("/system/bin/screencap -p " + "/sdcard/img.png").getBytes("ASCII")); 
        os.flush(); 

        os.close(); 
        sh.waitFor(); 

然後讀img.png爲位圖和JPG轉換它如下

Bitmap screen = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+   
File.separator +"img.png"); 

//my code for saving 
    ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 
    screen.compress(Bitmap.CompressFormat.JPEG, 15, bytes); 

//you can create a new file name "test.jpg" in sdcard folder. 

File f = new File(Environment.getExternalStorageDirectory()+ File.separator + "test.jpg"); 
      f.createNewFile(); 
//write the bytes in file 
    FileOutputStream fo = new FileOutputStream(f); 
    fo.write(bytes.toByteArray()); 
// remember close de FileOutput 

    fo.close(); 

,你必須在屏幕用不上,如果你的應用是在背景除非你紮根,否則即使你在後臺,上面的代碼也可以在任何屏幕上最有效地使用屏幕截圖。

UPDATE

谷歌已經與您可以採取截圖不生根圖書館,我試過了,但IAM肯定,它將盡快在外面吃飯的內存。

嘗試http://code.google.com/p/android-screenshot-library/

+0

屏幕捕獲在仿真器中工作,但不在實際設備中plse – Harsha

+0

設備是否已植根? –

+0

不,當用戶清單上的項目計劃顯示detailview與共享選項,我們需要保存該佈局位圖,然後我們需要爲該文件sahre實現它的工作在模擬器捕獲屏幕和sendmail意圖其共享來到真正的設計它不工作 – Harsha

14

這是做到這一點的方法。

Android taking Screen shots through code

結果輸出:

enter image description here

enter image description here

public class CaptureScreenShots extends Activity { 
    LinearLayout L1; 
    ImageView image; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.screen_shots); 
     L1 = (LinearLayout) findViewById(R.id.LinearLayout01); 
      Button but = (Button) findViewById(R.id.munchscreen); 
      but.setOnClickListener(new OnClickListener() { 

       @Override 
       public void onClick(View v) { 
        View v1 = L1.getRootView(); 
        v1.setDrawingCacheEnabled(true); 
        Bitmap bm = v1.getDrawingCache(); 
        BitmapDrawable bitmapDrawable = new BitmapDrawable(bm); 
        image = (ImageView) findViewById(R.id.screenshots); 
        image.setBackgroundDrawable(bitmapDrawable); 
       } 
      }); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     getMenuInflater().inflate(R.menu.screen_shots, menu); 
     return true; 
    } 

} 
+2

如果應用程序處於前臺,這不是唯一的方法嗎? –

+2

'新的BitmapDrawable(位圖)'構造函數已被棄用。而是使用'image.setImageBitmap(bm)' – Darpan

5

以屏幕快照的背景(如ADB)需要組= 1003(圖形)。否則,你只能得到你自己的過程的屏幕截圖。因此,您只能在根設備上執行此操作,或者通過運行ADB本機程序執行此操作。

本地cpp的代碼示例可以在https://android.googlesource.com/platform/frameworks/base/+/android-4.3_r2.3/cmds/screencap/

中找到,如果你想這樣做在Java代碼中,你需要訪問面類的隱藏API:

/** 
* Like {@link #screenshot(int, int, int, int)} but includes all 
* Surfaces in the screenshot. 
* 
* @hide 
*/ 
public static native Bitmap screenshot(int width, int height); 

這兩個應該是自ICS發佈以來,兩者都可以,對於像GB這樣的早期版本,您可以查看本機cpp代碼。

但是,在一些Android設備中,媒體系統和畫布等的執行情況不是很好,因此,在這種情況下,您無法捕獲任何視頻回放或任何表面視圖內容。

+4

應該注意,這個方法在Android 4.3及更高版本中被刪除。 – Tom

0
private void takeScreenshot() throws IOException { 
    Date now = new Date(); 
    android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now); 
    String fileName = now + ".jpg"; 
    try { 
     File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + ""); 
     folder.mkdirs(); //create directory 

     // create bitmap screen capture 
     View v1 = getWindow().getDecorView().getRootView(); 
     v1.setDrawingCacheEnabled(true); 
     Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache()); 
     v1.setDrawingCacheEnabled(false); 

     File imageFile = new File(folder, fileName); 
     imageFile.createNewFile(); 
     FileOutputStream outputStream = new FileOutputStream(imageFile); 
     int quality = 100; 

     bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream); 
     outputStream.flush(); 
     outputStream.close(); 

     Toast.makeText(MainActivity.this, "ScreenShot Captured", Toast.LENGTH_SHORT).show(); 

     MediaScannerConnection.scanFile(this, 
       new String[]{imageFile.toString()}, null, 
       new MediaScannerConnection.OnScanCompletedListener() { 
        public void onScanCompleted(String path, Uri uri) { 
         Log.i("ExternalStorage", "Scanned " + path + ":"); 
         Log.i("ExternalStorage", "-> uri=" + uri); 
        } 
       }); 
    } catch (Throwable e) { 
     // Several error may come out with file handling or OOM 
     e.printStackTrace(); 
    } 
} 

添加此方法按鈕單擊事件或在選項菜單中選擇事件,屏幕快照將在下載文件夾中存儲,因爲在folder可變我已經提供下載路徑,可以更改文件夾path.In清單文件添加權限寫

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

相關問題