hie i am using jde 4.5 want to use camera through my app.
i write the code and getting runtime excepetion Pushmodelscreen caaled by non event thread
tell me what the problem in it?
public void start Camera()
{
try {
// Create a player for the Blackberry's camera
Player player= Manager.createPlayer( "capture://video" );
// Set the player to the REALIZED state (see Player javadoc)
player.realize();
// Grab the video control and set it to the current display
_videoControl = (VideoControl)player.getControl( "VideoControl" );
if (_videoControl != null)
{
// Create the video field as a GUI primitive (as opposed to a
// direct video, which can only be used on platforms with
// LCDUI support.)
_videoField = (Field) _videoControl.initDisplayMode (VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field");
_videoControl.setDisplayFullScreen(true);
_videoControl.setVisible(true);
}
player.start();
if(_videoField!=null)
{
add(_videoField);
}
} catch (Exception e) {
// TODO: handle exception
Dialog.alert(e.getMessage());
}
}
`
thnaks alot
Amit
The code that involved in UI changes should be called from within the UI thread. So most likely some part of your code should be called in a way:
UIApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
// do your UI related staff here
// e.g. push a Screen or call Dialog.alert(), etc.
}
});
Also, you may find this info interesting.
Related
I'm working on a project using Sceneform from ARCore. I develop it base on HelloSceneform example provided by ARCore.
What I wanna do is adding a renderable object by a hit and then delete it when I click on the specific renderable on the screen.
I've tried method AnchorNode.setOnTapListener as following, but it didn't work(no response):
anchorNode.setOnTapListener(new Node.OnTapListener() {
#Override
public void onTap(HitTestResult hitTestResult, MotionEvent motionEvent) {
if(anchorNode.getAnchor()!=null){
arFragment.getArSceneView().getScene().removeChild(anchorNode);
anchorNode.getAnchor().detach();
anchorNode.setParent(null);
}
}
});
I also tried the following method, which causes unexpected close:
Scene scene = arFragment.getArSceneView().getScene();
scene.addOnPeekTouchListener(new Scene.OnPeekTouchListener() {
#Override
public void onPeekTouch(HitTestResult hitTestResult, MotionEvent motionEvent) {
Node node = hitTestResult.getNode();
node.setParent(null);
}
});
Is there any method could achieve this feature?
The code below should detect the touch and delete the node.
If you want to have a separate button to delete a selected node you can add a regular button and listener and just use the 'touch' event to select the node you want to delete.
private void handleOnTouch(HitTestResult hitTestResult, MotionEvent motionEvent) {
Log.d(TAG,"handleOnTouch");
// First call ArFragment's listener to handle TransformableNodes.
arFragment.onPeekTouch(hitTestResult, motionEvent);
//We are only interested in the ACTION_UP events - anything else just return
if (motionEvent.getAction() != MotionEvent.ACTION_UP) {
return;
}
// Check for touching a Sceneform node
if (hitTestResult.getNode() != null) {
Log.d(TAG,"handleOnTouch hitTestResult.getNode() != null");
Node hitNode = hitTestResult.getNode();
if (hitNode.getRenderable() == andyRenderable) {
Toast.makeText(LineViewMainActivity.this, "We've hit Andy!!", Toast.LENGTH_SHORT).show();
arFragment.getArSceneView().getScene().removeChild(hitNode);
AnchorNode hitNodeAnchor = (AnchorNode) hitNode;
if (hitNodeAnchor != null) {
hitNode.getAnchor().detach();
}
hitNode.setParent(null);
hitNode = null;
}
}
}
The above is extracted from various parts of a VR test application and combined here for a concise example - the full working application source is available here: https://github.com/mickod/LineView
Update - Kotlin version (tested April 2020):
private fun removeAnchorNode(nodeToRemove: AnchorNode) {
//Remove an Anchor node
arFragment.getArSceneView().getScene().removeChild(nodeToRemove);
nodeToRemove.getAnchor()?.detach();
nodeToRemove.setParent(null);
nodeToRemove.renderable = null
}
I know i am late but it may be helpful for someone.
Node you want to remove, first of you have to select that Transferable node by click or touch that node.
TransfarableNode.setOnTapListener this bulit in method serve purpose for us.
After that get node from HitTestResult and than detach node.
Here is the code you can use for selecting and removing node.
transformableNode.setParent(anchorNode );
transformableNode.setRenderable(model_nodeRenderable);
transformableNode.select();
transformableNode.setOnTapListener((HitTestResult hitTestResult, MotionEvent Event) ->
{
Node nodeToRemove = hitTestResult.getNode();
anchorNode.removeChild(nodeToRemove );
});
I have read the knowledgebase article "Streaming media - Start to finish" It is working fine. When I click the open video, the player screen is open. When I click the back button before the player is realized, it does not come to back to the right screen.
when sp.realize(); method executing user can't come to back screen.
after loading player. it close.
How to go back a screen if sp.realize() method is still executing?
new Thread(new Runnable()
{
public void run()
{
try
{
if(sp==null)
{
sp = new StreamingPlayer(url, contentType);
sp.setBufferCapacity(bufferCapacity);
sp.setInitialBuffer(initBuffer);
sp.setRestartThreshold(restartThreshold);
sp.setBufferLeakSize(bufferLeakSize);
sp.setConnectionTimeout(connectionTimeout);
sp.setLogLevel(logLevel);
sp.enableLogging(eventLogEnabled, sdLogEnabled);
sp.addStreamingPlayerListener(playerScreen);
sp.realize();
volC = (VolumeControl)sp.getControl("VolumeControl");
if(contentType.toLowerCase().indexOf("video")!=-1)
{
vidC = (VideoControl)sp.getControl("VideoControl");
videoField = (Field)vidC.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field");
vidC.setDisplaySize(Display.getWidth(), Display.getHeight()-timeSeeker.getHeight()-byteSeeker.getHeight());
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
replace(getField(0), videoField);
}
});
vidC.setVisible(true);
}
if(contentType.toLowerCase().indexOf("audio")!=-1)
{
audioIcon = true;
if(!(getField(0)==albumArt))
{
UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run()
{
replace(videoField, (Field)albumArt);
}
});
}
}
sp.start();
}
else
{
sp.stop();
sp.close();
sp = null;
run();
}
} catch(Throwable t)
{
//log(t.toString());
}
}
}).start();
I'm not sure exactly what you mean by this. However, have you tried running the audio stuff in a separate thread? That should reduce the likelihood of it interfering with anything else.
I am working on an application for blackberry that will be downloading a file. I would like to show a progress bar during this download. I have tried every combination of GaugeField and ProgressIndicatorView that I can come up with but I am getting nothing. My download is going but the progress bar is never getting updated on the screen. In fact before I started trying for the progress bar I was trying to simply use a TextField and update it with the current percentage completed of the download, and I had no luck that way either.
This is inside my Screen:
view = new ProgressIndicatorView(0);
model = new ProgressIndicatorModel(0, 100, 0);
controller = new ProgressIndicatorController();
model.setController(controller);
view.setModel(model);
view.setController(controller);
controller.setModel(model);
controller.setView(view);
view.setLabel("Percent completion");
view.createProgressBar(Field.FIELD_HCENTER);
add(view);
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
downloadVideo();
initializeMedia();
// If initialization was successful...
if(_videoField != null)
{
createUI();
updateVideoSize();
try {
_player.start();
} catch (MediaException e) {
// TODO Auto-generated catch block
e.printStackTrace();
ScreenSaverActivity.errorDialog("MEDIA EXCEPTION: "+e.toString());
}
}
else
{
_statusField.setText("Error: Could not load media");
}
}
});
downloadVideo() method:
private void downloadVideo(){
DownloadThread _dlThread = new DownloadThread();
_dlThread.start();
}
DownloadThread class:
class DownloadThread extends Thread {
public void run(){
try {
HttpConnection httpConn;
httpConn = (HttpConnection)Connector.open("http://url/to/myMovie.mp4");
InputStream is = httpConn.openInputStream();
String fName = "file:///store/BlackBerry/videos/myMovie.mp4";
FileConnection fconn = (FileConnection) Connector.open(fName, Connector.READ_WRITE);
if (!fconn.exists())
fconn.create();
OutputStream os = fconn.openOutputStream();
long lengthOfFile = httpConn.getLength();
int total = 0;
int count;
byte data[] = new byte[1024];
while ((count = is.read(data)) != -1) {
//I have tried this line outside of synchronized too, with no luck
synchronized(Application.getEventLock()) {
EmbeddedMediaScreen.this.model.setValue((int)(total*100/lengthOfFile));
}
total += count;
//write this chunk
os.write(data, 0, count);
}
os.flush();
os.close();
} catch (IOException e) {
ScreenSaverActivity.errorDialog(e.toString());
e.printStackTrace();
}
}
}
While my application is doing the download the device becomes unresponsive, so I am guess that my trouble is the download work is happing on the main(UI) thread for some reason and that this has something to do with why I can't get the screen to update with the progress. Any help would be greatly appreciated.
P.S. Android is generally my home, not blackberry, sorry if I have overlooked something that should be obvious =/
I see a few issues. It looks like the code after 'downloadVideo()' assumes the download happened synchronously. Since you want the download to happen in the background, you need to setup a separate method to handle the completion of the download. Right now your video playback code executes just after the download thread is started.
Also, you are acquiring the UI event lock every 1k of download. Since this is a video, I'm assuming a multi-megabyte download, meaning you are acquiring and releasing that lock thousands of times. This doesn't make much sense, in part because the download meter only has 100 different values, so you are mostly updating it with the same value. The easiest fix is to keep track of the last value sent to the model. if it is unchanged, then don't acquire or update the value.
In general, I don't like to acquire the UI lock directly, because there is no queue management. So I use invokeLater for all code that needs to update the UI. This has the nice property that the invokeLater code happens sequentially. You can overrun the queue, as this code would do if you directly change it to invokeLater. To avoid that problem, you have to setup another variable to track whether you've got a progress meter update queued. If so, don't queue any more work.
I am new to BlackBerry application development and trying to make a simple application to turn my flash light on as a torch. I know there are several applications that do this already, but I would like to try do it on my own.
I have installed eclipse and all the necesary add on to get my development environment running. I have also successfully create the stock standard hello world application.
I am however struggling to find out how to do this. I have been reading through the API documentation and started playing with FlashControl, VideoControl and SnapshotControl.
These however don't seem to expose methods to do this.
I know through the video camera I am able to go to options and turn the flash light on and this is exactly what i'm trying to mimic.
The code i have used so far which seems to just set the camera flash to force on is:
Player p = javax.microedition.media.Manager.createPlayer("capture://video");
p.realize();
p.start();
FlashControl flashControl = (FlashControl) p.getControl("javax.microedition.amms.control.camera.FlashControl");
flashControl.setMode(FlashControl.FORCE);
the problem relevant to the flash control has been resolved by me
as per i am using the flash control on my recent application on
camera.
Here is the code which i used :
public Camera(int j)
{
k = j;
try
{
Player player = Manager.createPlayer("capture://video");
player.realize();
_videoControl = (VideoControl) player.getControl("VideoControl");
flashControl = new FlashControl()
{
public void setMode(int mode)
{
// TODO Auto-generated method stub
}
public boolean isFlashReady()
{
// TODO Auto-generated method stub
return false;
}
public int[] getSupportedModes()
{
// TODO Auto-generated method stub
return null;
}
public int getMode()
{
// TODO Auto-generated method stub
return 0;
}
};
flashControl = (FlashControl) player
.getControl("javax.microedition.amms.control.camera.FlashControl");
try {
if (k == 1)
{
flashControl.setMode(FlashControl.AUTO);
Dialog.alert("slect Auto");
}
else if (k == 2)
{
flashControl.setMode(FlashControl.OFF);
Dialog.alert("slect No");
}
}
catch (Exception e)
{
System.out.println(e);
}
if (_videoControl != null)
{
_videoField = (Field) _videoControl.initDisplayMode(
VideoControl.USE_GUI_PRIMITIVE,
"net.rim.device.api.ui.Field");
// _videoControl.setDisplaySize(330, 420);
// _videoControl.setDisplayLocation(getContentWidth(),
// getContentHeight());
_videoControl.setVisible(true);
add(_videoField);
capture = new ButtonField("Capture", Field.FIELD_HCENTER);
capture.setChangeListener(this);
add(capture);
player.start();
}
}
catch (Exception e)
{
System.out.println(e);
}
}
this logic has been implemented simultaneously with Pinkesh as my colleage
in the comapny
The FlashControl class, available from OS 5.0 allows you to turn the flash on. Just set a flash control on your player with the FORCE flag:
FlashControl flash = (FlashControl)player.getControl("javax.microedition.amms.control.camera.FlashControl");
if(flash!=null) {
try {
flash.setMode(FlashControl.FORCE);
} catch(IllegalArgumentException iae){}
}
For this to work, you'll probably need to open a player to record video or take a picture. I'm not showing that in my code for the sake of brevity, but here you can read a tutorial. If your app is only about turning on the flash, you'd probably like to have the video field hidden.
Try something like this
LED.setState(LED.STATE_ON); // for LED
Backlight.enable(true); // for Screen
this.setMode(FlashControl.ON); // for flash light.
or else import this package
package lsphone.flash.microfireps;
I have a BlackBerry application that needs to take pictures from the camera and send them to a server. In order to do this i invoke the native camera application and listen to the filesystem. Once an image is captured and saved as a new jpeg file i get notified, resume foreground control and go about my business. The problem starts occurring after the first time this cycle is completed because now when i decide to call the camera application again it is already opened, and now the user is seeing a thumbnail of the last picture that was taken and several buttons allowing him to manipulate/manage it. naturally what i want the user to see is a preview of what the camera is "seeing" before he snaps another photo as he did before.
I have thought of various ways to solve this including killing the camera app each time (I understand this cannot be done programatically?), sending CameraArguments when invoking the app (which appears to be useless), and now i was thinking a solution could be as simple generating a "Back" key event before switching back to my app which would theoretically dismiss the annoying edit screen. Could this really be done? and if not is there any other possible solution you may think of?
A kind of hack...
start Camera App
in TimerTask check if Camera App started and if it need to be closed (some flag)
if yes, invoke it(so it will became active) and push ESC keypress event injection to close it
Take a look at this:
class Scr extends MainScreen {
boolean killCameraApp = false;
final String mCameraModuleName = "net_rim_bb_camera";
final CameraArguments args = new CameraArguments();
public Scr() {
super();
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
if (isCameraRunning() && killCameraApp) {
getApplication().invokeAndWait(callCamera);
getApplication().invokeAndWait(killCamera);
}
}
}, 0, 100);
}
Runnable callCamera = new Runnable() {
public void run() {
callCamera();
}
};
Runnable killCamera = new Runnable() {
public void run() {
injectKey(Characters.ESCAPE);
killCameraApp = false;
}
};
private boolean isCameraRunning() {
boolean result = false;
ApplicationManager appMan =
ApplicationManager.getApplicationManager();
ApplicationDescriptor[] appDes = appMan.getVisibleApplications();
for (int i = 0; i < appDes.length; i++) {
result = mCameraModuleName.equalsIgnoreCase(appDes[i]
.getModuleName());
if (result)
break;
}
return result;
}
private void callCamera() {
Invoke.invokeApplication(Invoke.APP_TYPE_CAMERA,
new CameraArguments());
}
private void injectKey(char key) {
KeyEvent inject = new KeyEvent(KeyEvent.KEY_DOWN, key, 0);
inject.post();
}
protected void makeMenu(Menu menu, int instance) {
menu.add(new MenuItem("start camera", 0, 0) {
public void run() {
callCamera();
killCameraApp = false;
}
});
menu.add(new MenuItem("kill app", 0, 0) {
public void run() {
killCameraApp = true;
}
});
super.makeMenu(menu, instance);
}
}
EDIT: Don't forget to set permissions for device release:
Options => Advanced Options => Applications => [Your Application] =>Edit Default permissions =>Interactions =>key stroke Injection