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.
Related
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! :)
I need to finish an application when it goes to the background, I'm using method finishAffinity() but it seems it does not work, someone can tell me another alternative
#Override
protected void onPause() {
finishAffinity()
super.onPause();
}
Here's answer
finishAffinity() is not used to "shutdown an application". It is used to remove a number of Activitys belonging to a specific application from the current task (which may contain Activitys belonging to multiple applications).
Even if you finish all of the Activitys in your application, the OS process hosting your app does not automatically go away (as it does when you call System.exit()). Android will eventually kill your process when it gets around to it. You have no control over this (and that is intentional).
you can use this
public void endTask() {
// Is the user running Lollipop or above?
if (Build.VERSION.SDK_INT >= 21) {
// If yes, run the fancy new function to end the app and
// remove it from the task list.
finishAndRemoveTask();
} else {
// If not, then just end the app without removing it from
// the task list.
finish();
}
}
Source and read more
I'm working on a simple to-do list app, and I'm trying to read/write data from/to internal storage. I'm trying to understand when exactly those read/write methods should be called.
I know that the activity class has an onCreate() method which will be a reasonable location for my read method, but where should I call my write method?
I want to call it when the app closes/ends, so I'd assume onDestory() is a good location, but i heard that onDestroy() may not be a good location for data storage operations and i should use onStop().
Any help or ideas?
It depends on Application Lifecycle.
And see This.
onStop() invokes when user press home button(Hard Key).
And then, if memory insufficient or another reason, Android Memory Manager will kill your app instant and onDestory() will never called.
The best thing you have to is make a button to save datas. Of course, Include onStop() save routine.
Following the table in the Android Developers Guide on the Activity Lifecycle, your app may be killed by the system any time without warning after either onPause() (for Pre-HONEYCOMB devices) or after onStop(). So you probably want to write your data in these methods to make sure nothing gets lost. So for newer devices (API level 11 and up), onStop() should be fine. If your app should run on older devices as well, onPause() would be the best place.
This is Just sample code. But you get the idea. Create a custom method implementing the code below and call it on some events like "onClick" or any other.
File file;
FileOutputStream strem = null;
String line = "Hey this is my name";
try {
file = new File("sdcard/newFile.txt");
strem = new FileOutputStream(file);
byte[] bytes = line.getBytes();
strem.write(bytes);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
strem.close();
} catch (IOException e) {
e.printStackTrace();
}
}
I have a simple java application that uses JOGL. When I run it from eclipse, and then close the application window, javaw.exe remains running. Here is the the relevant code:
public class App {
private Display mDisplay;
private Shell mShell;
private GL4 mGl;
private int mProgramId;
private int mVsId;
private int mFsId;
// ...
public void start() {
if (!initialize()) {
return;
}
while (!mShell.isDisposed()) {
if (!mDisplay.readAndDispatch()) {
mDisplay.sleep();
}
}
destroy();
}
private void initialize() {
mDisplay = new Display();
mShell = new Shell(mDisplay);
// some SWT and opengl initialization code, which is irrelevant for this issue
// (at least I think so)
// getting GLProfile, GLContext, GL4 etc.
final String vsText = ResourceManager.getShaderText(vsPath);
final String fsText = ResourceManager.getShaderText(fsPath);
mVsId = mGl.glCreateShader(GL4.GL_VERTEX_SHADER);
mFsId = mGl.glCreateShader(GL4.GL_FRAGMENT_SHADER);
mGl.glShaderSource(mVsId, 1, new String[] { vsText }, null, 0);
mGl.glCompileShader(mVsId);
mGl.glShaderSource(mFsId, 1, new String[] { fsText }, null, 0);
mGl.glCompileShader(mFsId);
mProgramId = mGl.glCreateProgram();
mGl.glAttachShader(mProgramId, mFsId);
mGl.glAttachShader(mProgramId, mVsId);
// bind a constant attribute location for positions of vertices
mGl.glBindAttribLocation(mProgramId, 0, "in_Position");
// bind another constant attribute location, this time for color
mGl.glBindAttribLocation(mProgramId, 1, "in_Color");
mGl.glLinkProgram(mProgramId);
// here error code is 0x0 (no error)
int error = mGl.glGetError();
mShell.open();
return true;
}
private void destroy() {
// here error code is 0x502 (GL_INVALID_OPERATION)
int error = mGl.glGetError();
mGl.glDetachShader(mProgramId, mFsId);
mGl.glDetachShader(mProgramId, mVsId);
mGl.glDeleteShader(mFsId);
mGl.glDeleteShader(mVsId);
mGl.glDeleteProgram(mProgramId);
mDisplay.dispose();
}
}
I commented out all rendering code and most other opengl/JOGL related calls (besides getting GLProfile, GLContext, GL4 and everything listed in this sample) and this problem persists.
Generally, the application works fine, shaders compile and link without problem (I used validation which I didn't display in this sample) and it displays what it needs to. The only problem is that javaw.exe remains running after I close the application window (by pressing the x in the corner of the window).
This issue is removed only if I comment out mGl.glCompileShader(mVsId); and subsequent lines. If I leave this line, javaw.exe will remain running, so I guess the problem is related to shader initialization/destruction code.
Also, glGetError() returns 0 (no error) at the end of initialize() and 0x502 (GL_INVALID_OPERATION) at the beginning of destroy(). There is only the main loop in between and no opengl calls that I know of, since, for testing, I commented out all rendering code.
Any ideas?
Edit 2012-10-03:
I still don't know what the problem is, but since I updated my graphic card drivers, 'javaw.exe' terminates as it should after application is closed. I have AMD Radeon HD 6870. My current driver version is 8.982 from 2012-07-27, and I can't remember what the last version was, but I believe it was from january 2011 or so.
However, glGetError() still returns 0x502 at the beginning of destroy, so I guess there is still something wrong.
Assuming you use JOGL from jogamp.org, pls use either our SWT GLCanvas
or our NEWTCanvasSWT.
The latter is preferred due to custom GLCapabilities, pls check API doc.
This given plus you are doing everything SWT related on the SWT thread (read
linked unit tests), IMHO it should work - at least our unit tests.
Since you mentioned after an update (GPU/driver) your troubles ceased to exist,
it might have been a driver problem.
Now to your GL error. Trace GL errors can be simply done by setting the system property 'jogl.debug.DebugGL', i.e. on the commandline "-Djogl.debug.DebugGL".
This will install the debug pipeline for your GL object automatically and checks for GL error, which will throw an GLException if appear.
You can also trace via the property 'jogl.debug.TraceGL'.
I don't know if this is relevant or not, but may help someone I guess so I'm gonna share it here. Keep in mind I'm just a hobbyist getting started in Java SWT.
I made a simple application in Eclipse IDE using the Java SWT library. I made a ''Quit'' button in my main Window shell that when pushed calls this :
quitBtn.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
shell.getDisplay().dispose();
System.exit(0);
}
});
After exporting the .jar file to Desktop, I converted it to a .exe file with LaunchJ4 wrapper and check the "Allow only a single instance of the application" in the Single instance tab using the singleR3XPlayer mutex.
When I would close the .exe file with the "Quit" button, everything was fine and the javaw.exe would terminates. But when I closed the shell with the X button on the top-right window, javaw.exe would remains running. I figured that out when I tried to delete the .exe file (Windows "Used file, still open in Java(TM) Platform SE binary, close the file and retry" type of error pop-up) and as I couldn't open another instance of the file after closing it with the X button (because of the Single instance mutex). Also, multiple instances of javaw.exe would remains running if I would execute a few of the .jar file (even after closing them, but only with the X and not the "Quit" button).
I figured out closing the window with the X button would only dispose of the shell and not exit the program. But pressing the "Quit" button would because it called System.exit(0). So I did this :
// SWT Event Loop
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
// To make sure javaw.exe terminates when Window is closed
if (shell.isDisposed()) {
System.exit(0);
}
Hence, after my SWT Event loop is done (shell.isDisposed() == true), I made sure System.exit(0) would be called. This way, javaw.exe is terminated either way.
I don't know how SWT works and I don't know if that's the proper way to do it but it ensures javaw.exe is terminated once the application closes.
Hope that helps.
In my j2me application i have to play a small sound file each times user click on an item. But the issues is when i play sound file multiple times like after 10-14 times it gives me
out of memory exception. Although i release the player each time i play the file but still it
gives out of memory exception : Here is the code snippet,
public void playSound(String soundFile) {
try{
if (player!=null) {
try {
player.deallocate(); //deallocate the unnecessary memory.
} catch (Exception ex) {
player=null;
System.gc();
}
}
player = Manager.createPlayer(getClass().getResourceAsStream(musicFolder + soundFile), "audio/mpeg");
// player = Manager.createPlayer(is, "audio/mpeg");
player.realize();
// get volume control for player and set volume to max
VolumeControl vc = (VolumeControl) player.getControl("VolumeControl");
if (vc != null) {
vc.setLevel(100);
}
player.prefetch();
player.start();
isException=false;
} catch (Exception e) {
isException=true;
}
}
Can someone tell me what is going wrong?
3 things to keep in mind
If you are going to play the same sound several times, you might want to keep one Player prefetched and simply start it multiple times.
When you want to properly cleanup a player, you should call Player.close()
You may want to use a media event listener to close and/or restart a player independently of user input.
I think you should also call
player.close()
right after after
player.deallocate();
According to documentation "When deallocate returns, the Player is in the UNREALIZED or REALIZED state." but close goes further... "When the method returns, the Player is in the CLOSED state and can no longer be used."
I'm not sure why the de-allocation isn't working. I guess it either takes longer to de-allocated than to create a new one, or the de-allocation fails for some reason. Is there a player.stop() to match the player.start()?
Another thing to try (if nothing else, for good form :) is not to create new player unless you need to/should. I.e. move the
if(player!=null){
So it also covers
player = Manager.createPlayer(getClass().getResourceAsStream(musicFolder + soundFile), "audio/mpeg");
HTH!