2014-02-22 62 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