2014-02-22 61 views
0

我正在編寫一個需要截取用戶屏幕截圖的應用程序。 我正在使用Robot類和createScreenCapture方法來實現此目的。java - 已截圖,但未授予權限?

正如Javadoc所述,需要readDisplayPixels權限才能截取屏幕截圖。

然後我繼續嘗試在嘗試截取屏幕之前檢查權限。 我準備了一些代碼來顯示我所做的:

import java.awt.AWTPermission; 
import java.awt.Rectangle; 
import java.awt.Robot; 
import java.awt.Toolkit; 
import java.awt.image.BufferedImage; 

public class ScreenshotTest { 
    public static void main(String[] args) { 
     try { 
      new SecurityManager().checkPermission(new AWTPermission("readDisplayPixels")); 
     } catch (SecurityException e) { 
      System.out.println("Permission not granted!"); 
     } 

     try { 
      Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()); 
      BufferedImage capture = new Robot().createScreenCapture(screenRect); 
      System.out.println("Screenshot taken!"); 
     } catch (Exception e) { 
      System.out.println("Taking screenshot failed."); 
     } 
    } 
} 

控制檯打印輸出:

Permission not granted! 
Screenshot taken! 

我很困惑,現在,因爲我沒想到這樣的事情發生。 createScreenCapture方法不應該拋出異常,因爲未授予權限?

+0

什麼是第一個try/catch塊中'SecurityException e'的堆棧跟蹤? – Mateusz

+0

@Mateusz堆棧跟蹤:java.security.AccessControlException:訪問被拒絕( 「java.awt.AWTPermission」 「readDisplayPixels」) \t在java.security.AccessControlContext.checkPermission(來源不明) \t在java.security.AccessController.checkPermission (Unknown Source) \t at java.lang.SecurityManager.checkPermission(Unknown Source) \t at exp.ScreenshotTest.main(ScreenshotTest.java:12) – quantumbyte

回答

1

你正在創建一些新SecurityManager而不是談話的(也許)現有的,所以試試這個:

SecurityManager sm = System.getSecurityManager(); 
if (sm != null) { 
    sm.checkPermission(new AWTPermission("readDisplayPixels")); 
} 

也就是說,如果虛擬機有一個實例SecurityManager,你可以與它通信來檢查限制,如果這樣的實例不存在 - 只需執行你想要執行的任何操作。祝你好運!

P.S.除非它們攜帶一些有用的信息,否則你絕不應該用自己的消息來影響堆棧跟蹤。在你的情況下,你只是隱藏了一些重要的信息,而不喜歡毫無意義的信息。不要這樣做。

而且萬一我沒講清楚 - 在第二try-catch塊中沒有拋出異常,因爲Robot內部確實與系統的SecurityManager溝通,當你在談論一些新的實例,其中有沒有任何有用的負載。以下是Robot.java的實際代碼:

public synchronized BufferedImage createScreenCapture(Rectangle screenRect) { 
    checkScreenCaptureAllowed(); 
    //... proceed 
} 

private static void checkScreenCaptureAllowed() { 
    SecurityManager security = System.getSecurityManager(); 
    if (security != null) { 
     security.checkPermission(
      SecurityConstants.AWT.READ_DISPLAY_PIXELS_PERMISSION); 
    } 
} 
+0

謝謝,我想這是解決方案!我現在試過System.getSecurityManager(),它返回null,所以我只是不檢查權限。我最初的想法是,這些權限是由操作系統或JVM授予的,我可以檢查它們。 P.S .:通常我不會像在上面的代碼中那樣處理異常,這只是一個SSCCE來解決我的問題。編輯:感謝來自Robot.java的代碼。 – quantumbyte

+0

@greenkeeper,歡迎您。順便說一句,通過捕獲相應的'SecurityException'作爲截取屏幕截圖的'try'塊的一部分,您可能完全消除第一次檢查。 – tkroman

+0

嗯,我的實際代碼比我發佈的要複雜一點。在我的應用程序中,我開始一個新的線程,我在循環中截取屏幕截圖,這就是爲什麼我想在開始線程之前檢查權限的原因。 – quantumbyte

0

你需要重構你的代碼,只是一點點:)。你很近。

try { 
    new SecurityManager().checkPermission(new AWTPermission("readDisplayPixels")); 
    Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()); 
    BufferedImage capture = new Robot().createScreenCapture(screenRect); 
    System.out.println("Screenshot taken!"); 
} catch (SecurityException e) { 
    System.out.println("Permission not granted!"); 
} catch (Exception e) { 
    System.out.println("Taking screenshot failed."); 
} 

當第一個安全異常,他們將永遠不會在屏幕捕獲語句。

希望幫助:)

+0

在問題中,它們是單獨的try-catch塊。問題是爲什麼不是從第二次嘗試捕獲拋出異常? – aldrin

+0

對不起,我可能一直不夠清楚。在第一個代碼段中,我明確檢查是否授予'readDisplayPixels'權限。在第二部分,我只是截圖。如果未在第一個塊中授予權限,則第二個塊也應該引發異常,因爲createScreenCapture的javadoc指出:拋出SecurityException - 如果readDisplayPixels權限未被授予。 – quantumbyte