Opening an URL from default browser crashes the application - java

I have a GUI application written in JavaFX 14 (not the XML one). I currently have three lists that are connected each to a different custom class, in whom exists an ObservableList which updates the ListViews. I have three. Upon doubleclicking on an element of the first ListView, which also contains URLs, I want to open said URL inside the default browser, no matter the OS (I'm programming on Ubuntu 20.04, and this app will be used on W10 too).
listSquads.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if(event.getClickCount()==2) {
try {
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
Desktop.getDesktop().browse(new URI(bot.getSquadHandler().extractURL(listSquads.getSelectionModel().getSelectedItem())));
}
} catch (IOException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}
});
This is the code. The bot is a custom TwitchBot object, based on pIRCbot libraries. The squadHandler mentioned in the getter method is said custom class. Extract URL is a method that, as the name would suggest, extracts the exact URL given a string as input - this part works, as it's called upon in other parts of the code and works correctly, and I've also tested it.
However, upon double clicking on any given element of the ViewList, the app freezes to then crash a few seconds later. Why could that be? Is there a way to open the browser no matter the OS?
Thanks in advance! :)

Related

When reading an external PDF with an Android App it always shows the same version, even after updating the PDF

Please donĀ“t be too harsh to me concerning any mistakes with this question since thats my first one here.
So basically what i want to do is reading/showing a PDF document in my Android App after pressing a button. The PDF is located on a Raspberry Pi 3 and i found a code example on this thread how to read it.
Before accessing it however, i call a python script on the Raspi which is (re)creating the PDF based on a database.
So the user presses the button in the App and sees a PDF which presents the current state of a database table.
Now i got the following code in my Activity to call the script and read the PDF:
new AsyncTask<Integer, Void, Void>(){
#Override
protected Void doInBackground(Integer... params) {
try {
executeRemoteCommand("user","pw","ip", port, "command to execute the python script");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}.execute(1);
//waiting for the PDF to be created
handler.postDelayed(new Runnable() {
#Override
public void run() {
String url = "http://IP/path/file.pdf";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
}
}, 5000);
With this code connecting to the Raspberry, executing the python script, thus updating the database and reading the PDF file works just fine.
But i have the following problem:
When i close the PDF view in my App, add something to the database and press the executing button again the PDF file itself is being updated (i checked that on the Raspberry) but then the App still shows the old version of it. Even when i restart the App and execute this again it still shows the first version of the PDF...
Does anyone have an idea why and how to fix this?
Is there any kind of cache which stores the PDF and just shows the same every time i read from the Raspberry?

Android4OpenCV: setting resolution at startup

I'm using Android4OpenCV to do some live image processing, and I'd like to use the smallest resolution the camera can offer. The default resolution is the largest the camera can offer.
I'm looking at the 3rd example, which allows the user to change resolutions via a menu. I'd like to modify that example to change the resolution at startup instead of requiring the user go through the menu. To do that, I simply add two lines to the otherwise empty onCameraViewStarted() function:
public void onCameraViewStarted(int width, int height) {
android.hardware.Camera.Size res = mOpenCvCameraView.getResolutionList().get(mOpenCvCameraView.getResolutionList().size()-1);
mOpenCvCameraView.setResolution(res);
}
And the thing is, this works perfectly fine on my Galaxy Nexus, running Android 4.2.2. The app starts up, and the resolution is set correctly.
However, when I run the exact same app on a Nexus 7 tablet, running Android 5.1, the app hangs on the call to setResolution(). Actually it works okay one time, but then hangs the second time you try to run it- even if you completely exit the app, remove it from the running apps, or restart the device. Other users are reporting the same error as well, so it's not just the Nexus 7 device- in fact, my Galaxy Nexus seems to be the only device where this works.
Specifically, the application goes into the setResolution() function, which then calls org.opencv.android.JavaCameraView.disconnectCamera(), which looks like this:
(Note: this code is internal to the OpenCV4Android library, this is not my code)
protected void disconnectCamera() {
/* 1. We need to stop thread which updating the frames
* 2. Stop camera and release it
*/
Log.d(TAG, "Disconnecting from camera");
try {
mStopThread = true;
Log.d(TAG, "Notify thread");
synchronized (this) {
this.notify();
}
Log.d(TAG, "Wating for thread");
if (mThread != null)
mThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
mThread = null;
}
/* Now release camera */
releaseCamera();
}
Looking at the logs, I can see that the thread gets stuck on the synchronized(this) line. The only other thing that synchronizes on that Object is the inner JavaCameraView.CameraWorker class, which is the mThread variable in the above code, started by the JavaCameraView class:
(Note: this code is internal to the OpenCV4Android library, this is not my code)
private class CameraWorker implements Runnable {
public void run() {
do {
synchronized (JavaCameraView.this) {
try {
JavaCameraView.this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (!mStopThread) {
if (!mFrameChain[mChainIdx].empty())
deliverAndDrawFrame(mCameraFrame[mChainIdx]);
mChainIdx = 1 - mChainIdx;
}
} while (!mStopThread);
Log.d(TAG, "Finish processing thread");
}
}
I've tried futzing with that code, changing the notify() to notifyAll(), and maintaining a List of CameraWorker threads and joining each one. But no matter what, the app still hangs at the disconnectCamera() call.
My questions are:
How can I modify the third OpenCV4Android example so that its resolution is set at startup?
What is causing the app to hang?
Why does this work on some devices but not others?
Edit: I haven't received any comments or answers, so I've crossposted to the OpenCV forums here.
Edit 2: As per cyriel's suggestion, I've tried setting the resolution after several frames have gone by:
int frames = 0;
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
frames++;
if(frames == 6){
android.hardware.Camera.Size res = mOpenCvCameraView.getResolutionList().get(mOpenCvCameraView.getResolutionList().size()-1);
mOpenCvCameraView.setResolution(res);
}
return inputFrame.rgba();
}
However, now this gets stuck in the same exact place, even on my Galaxy Nexus, which works if I set the resolution in the onCameraViewStarted() function. I've tried increasing the frame count to 7 and even 100, but I always get stuck in the same place.
The most important question in your situation is whether it's working if you don't modify the code at all - are you able to change the resolution (via menu) without crashing the app?
If yes than the answer most likely is simple - it's the same bug in OpenCV as in Windows version: before changing camera resolution or fps (and most likely any property) you need to grab at least one (use 3-5 to be sure) frame before changing this property.
If no than most likely there is nothing you can do on your own - fill the bug report and wait for comments. The only alternative is to use other library to grab frames from camera and than convert it to OpenCV object.

Substance Look and Feel Applet alert during startup

recently I have discovered substance. When i try to load it in my java program (not applet!) I get errors during startup.
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
try
{
UIManager.setLookAndFeel(new SubstanceGraphiteAquaLookAndFeel());
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
And those are the errors (Note: Those are pop ups, where --message-- is the title, and {name} are buttons):
--APPLET ALERT-- The applet is attempting to connect to jar: [...]/substance-6.0/org/pushingpixel/substance/api/skin/graphite.colorschemes. {Allow} {Disallow} {Stop Applet}
--APPLET ALERT-- The applet is attempting to invoke the java/lang/System.getenv() operatoin on KDE_FULL_SESSION {Allow} {Disallow} {Stop Applet}
The last message appears 5 times whilst writing the following into stderr
-->> returning Frame NULL
BaseDialog: owner frame is a java.awt.Frame
Also my first window will be loaded with the default swing ui.
After closing this and opening a new one (programmatically) the ui will be initialized.
Is there any way I can bypass the error?
Edit: I use the following libraries: laf-plugin-7.2; laf-widget-7.0; substance-6.0
I downloaded a fork from: https://github.com/Insubstantial/insubstantial/downloads
The other one was not signed because i compiled it myself.

Using Browserfield.displayContent with <frame> that has an external url

I am trying to create a screen for a blackberry 5.0+ app that has a banner at the top and then a Browserfield underneath that views an external site. The banner is hosted on one site and the content for the BrowserField is hosted on another.
Originally I tried using 2 BrowserFields but had issues when several devices did not display the banner and only showed the content underneath. Furthermore when another screen with the same setup was displayed the app would crash with an IllegalStateException. I did a bit of research and it seems that BrowserField seems to have some trouble when several instances of it exist at once.
So in order to get around this issue I have combined both BrowserFields into one, using the frame tag in html, with the hopes of displaying the Banner ad in the first frame and the content underneath in the second frame.
The html I made works in a normal browser:
<!DOCTYPE html>
<html>
<frameset rows="10%,90%">
<frame scrolling="no" src="http://4.bp.blogspot.com/_CZ1HhhanNgc/TI0xscVLW8I/AAAAAAAABps/sfeO4E3234k/s1600/head-mp-700x88.jpg" noresize="noresize" frameborder="0">
<frame src="http://www.penny-arcade.com" frameborder="0">
</frameset>
</html>
What I am doing is reading the html in as text, removing the \n and \rs and then putting it in the following method: browserField.displayContent(html,"http://localhost");
This method is supposed to display the html in the browser, but instead on the simulator I get this:
On the device I get a blank screen. I don't know whats going on with the displayContent() method, so I would assume that it doesn't allow external sites? I don't really know what my options are from this point on. Is there some kind of fix for this, some library that I can use or some other way to implement this?
Edit:
So #Nate suggested a change to the DOCTYPE tag, and posted a screenshot of the html working. However I did this and I still get the same results, so I am going to post the code I'm using to make the screen. Here it is:
public final class MyScreen extends MainScreen
{
/**
* Creates a new MyScreen object
*/
private BrowserField browserField;
public MyScreen()
{
// Set the displayed title of the screen
setTitle("MyTitle");
BrowserFieldConfig config = new BrowserFieldConfig();
config.setProperty(BrowserFieldConfig.VIEWPORT_WIDTH, new Integer(Display.getWidth()));
config.setProperty(BrowserFieldConfig.NAVIGATION_MODE,
BrowserFieldConfig.NAVIGATION_MODE_POINTER);
config.setProperty(BrowserFieldConfig.INITIAL_SCALE, new Float(1.0));
config.setProperty(BrowserFieldConfig.USER_SCALABLE, Boolean.FALSE);
//supposed to prevent InvalidStateException from refreshing sometimes
ProtocolController eventsProtocolController = new ProtocolController(browserField)
{
public void handleNavigationRequest(BrowserFieldRequest request) throws Exception
{
browserField.setFocus();
super.handleNavigationRequest(request);
}
};
config.setProperty(BrowserFieldConfig.CONTROLLER, eventsProtocolController);
browserField = new BrowserField(config);
try
{
String embeddedLinkFrame = readTextFile("frame.html");
browserField.displayContent(embeddedLinkFrame, "http://localhost");
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
add(browserField);
}
public String readTextFile(String fName)
{
String result = null;
DataInputStream is = null;
try
{
is = new DataInputStream(getClass().getResourceAsStream("/" + fName));
byte[] data = IOUtilities.streamToBytes(is);
result = new String(data);
}
catch (IOException e)
{
System.out.println(e.getMessage());
}
finally
{
try
{
if (null != is)
is.close();
}
catch (IOException e)
{
System.out.println(e.getMessage());
}
}
return result;
}
}
Ok, my apologies for the first answer. I think DOCTYPE was a red herring (but I didn't have your Java code at the time).
I see a few potential problems:
Network Connectivity
First, as is always the case, make sure you have network connectivity for your device, or simulator. That may include the MDS simulator running. You can always test connectivity with the normal Browser app, checking a website you know to be running. I believe that if you have a total lack of connectivity (i.e. network disabled), then you will get your frames showing just the text / URLs. However, I believe it will also have something like this:
Could not select proper Transport Descriptor for: http://www.penny-arcade.com
instead of showing null, as you show.
Adding BrowserField
Next, I think there is a problem with you asking the browser field to display content before you've added the field. Simply switch the order of those two lines of code to this:
add(browserField);
try
{
String embeddedLinkFrame = readTextFile("frame.html");
browserField.displayContent(embeddedLinkFrame, "http://localhost");
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
I believe the behaviour if you have these lines out of order, however, is just to get a blank browser field.
Viewport Properties
Lastly, I would not recommend setting page properties programmatically, as you've done. Although this is not going to keep your page from displaying, I'd recommend putting those properties in HTML meta elements:
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
</head>
Source: BlackBerry.com
Update: Protocol Controller
Unfortunately, my simulator is acting up, and declining to support hot-swap right now. So, it's hard for me to run many times, and collect decisive results. But, it looks to me like removing your ProtocolController object prevents this problem from happening for me. (maybe you can clarify why you're using the protocol controller in this situation?). If this answer was a motivation, you might look carefully at the poster's full comments about it's usefulness.

keyReleases are simulating keyPresses in Linux (java Swing GUI)

I have a kiosk GUI application I'm working on and it requires me to block users from being able to Alt-Tab out of the fullscreen window. I posted a question about this a while back and a member helped me with some code, which worked perfectly under a Windows environment.
Here it is:
public class TabStopper implements Runnable {
private boolean isWorking = false;
private MenuFrame parent;
public TabStopper(MenuFrame parent) {
this.parent = parent;
new Thread(this, "TabStopper").start();
}
public void run() {
this.isWorking = true;
Robot robot;
try {
robot = new Robot();
while (isWorking) {
robot.keyRelease(KeyEvent.VK_ALT);
robot.keyRelease(KeyEvent.VK_TAB);
parent.requestFocus();
Thread.sleep(10);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void stop() {
this.isWorking = false;
}
public boolean isWorking() {
return this.isWorking;
}
}
However, I need this to be able to work in Linux as well. I made an executable jar from the source and brought it into Linux. Everything worked except the Alt and Tab keys were being constantly pressed. The buttons on my GUI were constantly being cycled and I was able to open a terminal (I set a backdoor in the application during testing in case something like this happens) which wouldn't let me type anything because Tab lists all the files in the current directory.
Could anyone tell me if there would be a fix that would work in both Linux and Windows environments. However, if I had to choose, I would go for Linux.
EDIT: I can also confirm that the Alt key is being "pressed". What's with this weird behaviour?
Forget grabbing Alt+Tab with hacks like this. It is a bad hack and it is error-prone. There are also so many other hotkey combinations.
For linux you have two options:
Use a minimal window manager or no window manager at all. For example, with fluxbox you can remove all key bindings alltogether and you can also make your application maximise by default, etc. You can empty the desktop menus such that the user gains no control even when your application crashes. This is a clean solution that really solves your problem instead of some parts of it. There are many ways to fiddle with the system other than Alt+Tab.
Grab input controls completely. This is what games do. For example libSDL does it for you and there are java wrappers for the functionality as well. This should also work as expected, except you use a window manager that does not allow input control grabbing per default (I don't know of any).

Categories