java - screenshot taken, but permission not granted? - java

I am writing an application that needs to take screenshots of the users screen.
I am using the Robot class and the createScreenCapture method to achieve this.
As the Javadoc states, the readDisplayPixels permission is needed to take a screenshot.
I then went ahead and tried to check the permission before attempting to take a screenshot.
I prepared some code to show what I did:
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.");
}
}
}
The console printout is:
Permission not granted!
Screenshot taken!
I am confused right now, because I did not expect that to happen. Shouldn't the createScreenCapture method throw an exception because the permission is not granted?

You are creating some new SecurityManager instead of talking to the (maybe) existing one, so try this:
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new AWTPermission("readDisplayPixels"));
}
That is, if the VM has an instance of SecurityManager, you can communicate with it to check for the restriction, and if such an instance is absent - just perform any action you want to perform. Good luck with that!
P.S. You should never shadow stacktraces with your own messages unless they carry some useful information. In your case, you just hid some impotrtant info in favour of senseless messages. Don't do that.
And just in case I didn't make it clear - the exception in second try-catch block isn't thrown because internals of Robot do communicate with system's SecurityManager, while you were talking to some new instance, which hadn't had any useful payload. Here is the actual code from 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);
}
}

You need to restructure your code, just a little:). You are close.
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.");
}
When the first security exception is thrown, they will never get to the screen capture statements.
Hope that helps:)

Related

FirebaseVisionImage: variable 'image' might not have been initialized

I'm trying to use the example for Google Firebase (machine learning kit) in Android Studio. I'm getting an error when passing the image variable into the detector.processImage method (error shown below).
How can I get past this error? I have to use the FirebaseVisionImage.fromFilePath within a try-catch block, but the error message is telling me that the image variable may not be initialized.
error: variable image might not have been initialized
FirebaseVisionImage image;
try {
image = FirebaseVisionImage.fromFilePath(MainMenuActivity.this,
Uri.fromFile(new File("/sdcard/Download/test.jpg")));
} catch (IOException e) {
e.printStackTrace();
}
FirebaseVisionTextRecognizer detector = FirebaseVision.getInstance().getOnDeviceTextRecognizer();
Task<FirebaseVisionText> result = detector.processImage(image)
.addOnSuccessListener(new OnSuccessListener<FirebaseVisionText>() {
#Override
public void onSuccess(FirebaseVisionText firebaseVisionText) {
// Task completed successfully
mainText.setText("Hello!");
}
})
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// Task failed with an exception
}
}
);
That error emerges because of this piece of code
FirebaseVisionImage image;
try {
image = FirebaseVisionImage.fromFilePath(
MainMenuActivity.this,
Uri.fromFile(new File("/sdcard/Download/test.jpg"))
);
} catch (IOException e) {
e.printStackTrace();
}
Now, ask yourself, what happens to image if an Exception is thrown inside the try block?
The variable might have been assigned a valid value, or it might have not.
Because you're letting the execution flow to continue (you aren't throwing the Exception to the upper level), the compiler cannot know that for sure, since the exception is thrown at run-time.
And because in Java a local variable must be initialized before usage (even with = null), the compiler is telling you to do so.
error: variable image might not have been initialized
The solution might be to initialize it with null
FirebaseVisionImage image = null;
Or, a better one, to let escape the Exception. That will signal there is a bug.
You'll also be able to completely unwrap your code from the try - catch block.
All code that needs the image should be inside the try block:
try {
FirebaseVisionImage image = FirebaseVisionImage.fromFilePath(MainMenuActivity.this,
Uri.fromFile(new File("/sdcard/Download/test.jpg")));
Task<FirebaseVisionText> result = detector.processImage(image)
.addOnSuccessListener(new OnSuccessListener<FirebaseVisionText>() {
#Override
public void onSuccess(FirebaseVisionText firebaseVisionText) {
// Task completed successfully
mainText.setText("Hello!");
}
})
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// Task failed with an exception
}
}
);
} catch (IOException e) {
e.printStackTrace();
}
FirebaseVisionTextRecognizer detector = FirebaseVision.getInstance().getOnDeviceTextRecognizer();
Note that a catch statement that just prints the runtime exception like yours does, should usually be as high as possible in the callstack. So I'd recommend moving it to the code that alls this code, or even higher up. And keep in mind: if you don't catch that error at all, Android will print it too. So consider what you're trying to accomplish with this catch and implement it accordingly.

Exceptions in Swing from helper classes

I am working on a homework assignment to convert this Java Tutorial of the Knock Knock application to a Swing GUI application and use multithreading.
I have helper classes that are throwing Exceptions. These classes do not extend JFrame and I can't create new JOptionPane to show the exception. How would you show that Exception to the user?
For example: I have a class that loads the jokes from two text files (one for the clues and one for the answers). If the text files cannot be found in the location I expect, I am throwing a NullPointerException. Because this is a helper class it is not extending JFrame. How would I relate that message to the user? Do I just reference the javax.swing.JOptionPane showMessageDialog method like I have it in my code below or I can have another proxy class that catches exceptions and shows them?
private final void getFilePath(ResponseFiles fileToGet) {
String packagePath = "/com/knockknock/message";
try {
if (fileToGet == ResponseFiles.CLUES)
file = new File(getClass().getResource(String.format("%s/clues.txt", packagePath)).getPath());
else if (fileToGet == ResponseFiles.ANSWERS)
file = new File(getClass().getResource(String.format("%s/answers.txt", packagePath)).getPath());
} catch (NullPointerException e) {
javax.swing.JOptionPane.showMessageDialog(null, "Jokes Files Missing", "File Missing", JOptionPane.ERROR_MESSAGE);
}
What do you think?
Instead of using Swing components in business layer you can pass on the exceptions and handle it separately.
Have some custom Exception handler class where you can handle Runtime/Checked/Custom exceptions.
public class ExceptionHandler {
public void handleException(Exception exp) {
if (exp instanceof NullPointerException) {
javax.swing.JOptionPane.showMessageDialog(null,
"Jokes Files Missing", "File Missing",
JOptionPane.ERROR_MESSAGE);
} else if (exp instanceof IOException) {
javax.swing.JOptionPane.showMessageDialog(null, "Test", "Test",
JOptionPane.ERROR_MESSAGE);
}
//Handle other exceptions
}
}
Change your method like
private final void getFilePath(ResponseFiles fileToGet) {
String packagePath = "/com/knockknock/message";
if (fileToGet == ResponseFiles.CLUES)
file = new File(getClass().getResource(
String.format("%s/clues.txt", packagePath)).getPath());
else if (fileToGet == ResponseFiles.ANSWERS)
file = new File(getClass().getResource(
String.format("%s/answers.txt", packagePath)).getPath());
}
In your business layer where GUI interaction is done you can handle exception like this. In your case since it is Runtime exception no explicit throwing is required.
try {
getFilePath(ResponseFiles.CLUES);
} catch (Exception e) {
new ExceptionHandler().handleException(e);
}

Jumping to another class using a JButton

I have the below code where I made a simple GUI. I would like Button2 to navigate to class 'Project2', which should start another piece of code. Just to note, in its current state, 'Project2' has no GUI, though I intend to add one soon. Anyway, this 'code jump' which I used by adding: String[] args = {};
Project2.main(args);
is not working, as the IDE says 'IOException must be caught or thrown'. I know how this works, though I am not sure how to implement it in the program.
Thanks in advance!
You can try to use dynamic class loading for your program. Below you can find lambda, which calls main method from com.stackoverflow.ExternalCaller class.
If you do not like to use lambda, you can create a simple anonymous class.
button.addActionListener(s -> {
try {
Class<?> externalCaller = Class.forName("com.stackoverflow.ExternalCaller");
Method main = externalCaller.getDeclaredMethod("main", new Class[]{String[].class});
main.invoke(null, new Object[]{new String[0]});
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
});
ExternalCaller class in its turn looks something like that:
package com.stackoverflow;
public class ExternalCaller {
public static void main(String args[]) {
System.out.println("Hello World");
}
}
In result once you click on the button you will get Hello World output in console.
If you would like to work with external jars etc. please look on Process class. Quick example:
Process proc = Runtime.getRuntime().exec("java -jar External.jar");
Or even more on fork/exec. You can read From Runtime.exec() to ProcessBuilder for more details.
Hope this will help. Good luck.
In most of the IDE's, when you right-click on the Button2 in the Design(GUI) pane, you can travel through:
Events -> Actions -> actionPerformed().
And write this code in the selected method to switch classes:
this.setVisible(false); //turns off the visibility of the current class
outputClass out = new outputClass(); //creating the object of the class you want to redirect to
out.setVisible(true);//turns on the visibility of the class you want to redirect to

errors when using the bluetooth sample code on android developer site

I am working to add Bluetooth capabilities to my app and ultimately the device that I want to use is a headset/earpiece. I have begun assembling the code and I partial functionality with it. When I got to the code for setting up a bluetooth connection by server, I got errors when adding the code. I have tried solving the problems through the hover over the error and autocorrect but every time I fix one problem a different on arises. This leads me to believe that I am missing something that autocorrect doesn't know about. I need some help fixing the errors. Useful suggestions for setting a bluetooth codin for the first time would also be appreciated. Errors are surrounded with ||#| xxx |||. Error 1:cannot be resolved. Error 2:cannot be resolved to a variable. Error 3:undefined for the type AcceptSocket.
import java.io.IOException;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
public class AcceptSocket extends Thread {
private static final String MY_UUID = null;
BluetoothServerSocket mmServerSocket;
public void AcceptThread() {
// Use a temporary object that is later asssigned to mmServerSocket,
// because mmServerSocket is final
BluetoothServerSocket tmp = null;
try {
// MY_UUID is the app's UUID string, also used by the client code
tmp = ||1|mBluetoothAdapter|||.listenUsingRfcommWithServiceRecord(||2|NAME|||,
MY_UUID);
} catch (IOException e) {
}
mmServerSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
// Keep listening until exception occurs or a socket is returned
while (true) {
try {
socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
// Do work to manage the connection (in a separate thread)
||3|manageConnectedSocket|||(socket);
mmServerSocket.close();
break;
}
}
}
/** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
try {
mmServerSocket.close();
} catch (IOException e) {
}
}
}
Error 1,2: There is no constant called NAME anywhere in the class.
Error 3: There is no method called manageConnectedSocket() in the class.
You can't just copy and paste something from the developer's page and expect it to work. It leads you in the correct direction and you have to fill in the missing pieces.

Music in Java (start/stop)

Ok, so I am making a game and the music changes when you are in different regions or if there is an interruption, like with an AI.
So I have JUST learned how to make music showup in my program, and now I am trying to make it stop, but I am unsure how to, below is a snippet of code where the music plays and then I try to overwite it with new music when an action occurs.
public static void songs(String word) {
String temp = word;
if (temp.equals("start")) {
try {
try {
blah = new FileInputStream("C:/Users/Austin/Desktop/Storage/programimages/game/battle.wav");
} catch (Throwable e) {
e.printStackTrace();
}
AudioStream as = new AudioStream(blah);
AudioPlayer.player.start(as);
System.out.println("going");
} catch (IOException e) {
System.err.println(e);
}
}
if (temp.equals("stop")) {
try {
try {
blah = new FileInputStream("C:/Users/Austin/Desktop/Storage/programimages/game/silence.wav");
} catch (Throwable e) {
e.printStackTrace();
}
AudioStream as = new AudioStream(blah);
AudioPlayer.player.stop(as);
System.out.println("stopping");
} catch (IOException e) {
System.err.println(e);
}
}
}
This is the only method I have been able to find that has the music play, but if you guys have any other suggestions please let me know.
Again, I want to have sound affects and music going, and right now all that happens is one song will play, and it will not stop under any circumstance until it hits the very end of its length. I want to be able to stop songs whenever a new one should come on, and also allow sound affects to pop up.
Thanks!
(since I am stuck on this and need an answer now I will probably repost on one or two more java sites so I can get a response ASAP, thank you though!!!!)
EDITED CODE: (still does not stop the current stream, any more suggestions appreciated)
public static void songs(String word) throws IOException {
String temp = word;
if (temp.equals("go")) {
try {
blah = new FileInputStream("C:/Users/Austin/Desktop/Storage/programimages/game/battle.wav");
} catch (Throwable e) {
e.printStackTrace();
}
AudioStream as = new AudioStream(blah);
AudioPlayer.player.start(as);
System.out.println("going");
}
if (temp.equals("stop")) {
//don't try and do things with a null object!
if (as != null) {
AudioPlayer.player.stop(as);
System.out.println("stopping1");
}
System.out.println("stopping2");
AudioPlayer.player.stop(as);
}
}
Currently you're creating a new AudioStream in your stop branch and calling the stop method using this. This is a different object to the one that is currently playing. Try making the AudioStream a class variable, and calling stop on that instead.
EDIT: at the top of the class containing your code...
class YourClass {
//the class member variable
private AudioStream as;
//[etc...]
In your start branch:
// 'as' has already been defined above
as = new AudioStream(blah);
AudioPlayer.player.start(as);
System.out.println("going");
In your stop branch:
try
{
//don't try and do things with a null object!
if (as != null)
{
AudioPlayer.player.stop(as);
}
System.out.println("stopping");
}
catch (IOException e)
{
System.err.println(e);
}
You may have trouble with the static identifier on your method - if you're calling this from within an instantiated class you don't need this.
I can't even access these sun.audio Objects on my Eclipse IDE--I know they are in rt.jar, but there is header info about them being proprietary and such.
Can the Java Sound library (javax.sound.sampled) handle what you want to do? Both Clip and SourceDataLine allow one to stop playback. That is a more usual way of playing sound, if you want to use native Java.
Playback into is here:
http://docs.oracle.com/javase/tutorial/sound/playing.html
But the documentation, overall, is not exactly rich with examples. There's example code at this site
http://www.jsresources.org/
and plenty of people here who could help if you run into problems with the native Java approach.

Categories

Resources