Alternate entry point run 2 times when acces my app on Blackberry? - blackberry

I have an alternate entry point set to auto-run to push a dialog with a particular time;
It runs successfully. The alternate entry point will auto-run when the device is on, as expected. However, when I run my app interactively, the dialog shows twice. How can I prevent this?
public static void main(String[] args) {
if ( args != null && args.length > 0 && args[0].equals("autorun")) {
MyApp theApp = new MyApp();
theApp.enterEventDispatcher();
} else {
MyApp theApp = new MyApp();
theApp.pushScreen(new MyScreen());
theApp.enterEventDispatcher();
}
}
public MyApp() {
this.addRealtimeClockListener(this);
}
public void clockUpdated() {
checkTimetoPushDialog();
}

So, if I understand this correctly, clockUpdated is invoked as part of the Realtime Clock listener. The listener is added when MyApp is constructed, and MyApp is constructed for both the foreground and background app.
So it's not so surprising that the dialog is pushed for both the foreground and background app.
If you don't want to see the dialog when the user starts the app, avoid adding the listener when you are not an auto-start process.

Related

BlackBerry App: Screen Not Showing Up In Auto Run Mode

I am trying to create a background app which will run at system startup. When I run it manually (from the ribbon), the screen appears but when I run the app after making it a startup app (Auto-run on startup option in descriptor), nothing appears on screen. I am trying the following code;
public class AppClass extends UiApplication {
public static void main(String[] args) {
AppClass theApp = new AppClass();
theApp.enterEventDispatcher();
}
public AppClass() {
pushScreen(new AppScreen());
}
}
And this is the screen class;
public final class AppScreen extends MainScreen {
private LabelField label;
public AppScreen() {
setTitle("AppTitle");
label = new LabelField();
label.setText("Ready.");
add(label);
}
}
I am expecting that its a UI app so its screen should be visible no matter if is auto-run at startup or run manually. If I need to do something to make it work as expected, please guide me about it, I am new to BlackBerry development.
I am developing in the following environment;
BlackBerry JDE Eclipse Plugin 1.5.0
BlackBerry OS 4.5
Auto start applications are run before the OS has completed booting so there isn't any support for the user interface. I suspect your application is being launched but failing on some UI call. The documented way to write an application that is to auto run and run from the home screen is to provide an alternated entry point for the auto run with arguments that tell the program it has been auto run. Then use the API to wait until the OS is ready for UI applications.
public class AppClass extends UiApplication {
public static void main(String[] args) {
if (args.length > 0 && args[0].equals("auto-run")) {
// auto start, wait for OS
while (ApplicationManager.getApplicationManager().inStartup()) {
Thread.sleep(10000);
}
/*
** Do auto-run UI stuff here
*/
} else {
AppClass theApp = new AppClass();
theApp.enterEventDispatcher();
}
}
public AppClass() {
pushScreen(new AppScreen());
}
}
Call getApplication().requestForeground(); from the constructor of your AppScreen class so that your screen will be visible.
public final class AppScreen extends MainScreen {
private LabelField label;
public AppScreen() {
setTitle("AppTitle");
label = new LabelField();
label.setText("Ready.");
add(label);
getApplication().requestForeground();
}
}
Once the app is running in background, we have to bring it to foreground explicitly to show UI element and that is what we are doing here.

BlackBerry - Can't foreground a running application

I have a UI application that is set to autorun on startup which spawns a few threads doing some work in the background. It has one screen that displays information about the work the background threads are doing.
class AppName extends UiApplication implements SystemListener2 {
private static AppName app;
public static void main(String[] args) {
app = new AppName();
if (ApplicationManager.getApplicationManager().inStartup()) {
app.addSystemListener(app);
} else {
app.initializeLater();
}
app.enterEventDispatcher();
}
public AppName() {
pushScreen(new InfoScreen());
requestBackground();
}
private void initialize() {
// Spawns some threads doing work in the background
}
private void initializeLater() {
invokeLater(new Runnable() {
public void run() {
initialize();
}
});
}
public void powerUp() {
removeSystemListener(this);
initialize();
}
}
When I run the app in the simulator it works fine. Upon startup everything runs and then when I click the icon the screen is foregrounded and displayed. This is the output from the simulator:
3:20:26.612: AM: Starting AppName
3:20:26.612: AM: AppName already running
3:20:26.612: AM: Foreground is requested: AppName(304)
3:20:26.628: AM: Foreground is set: AppName(304)
However, on the device the screen never displays. This is the device debugger output:
[0.0] Starting AppName
[0.0] AppName already running
As you can see the foreground request is never made. I confirmed this by overriding the UiApplication.activate() method and putting in a System.out message to see if it was being called but it's not getting called.
Does anyone have any idea why this is happening?
try using this
UiApplication.getUiApplication().invokeAndWait(new Runnable() {
public void run() {
UiApplication.getUiApplication().requestForeground();
});
}

How to always check the time on Blackberry?

I make a alternate entry point that display a dialog " Hello new week " on the first day of each week.
My code :
public static void main(String[] args)
{
if ( args != null && args.length > 0 && args[0].equals("autorun") ){
MyApp theApp = new MyApp();
theApp.pushThread.start();
theApp.enterEventDispatcher();
}
else {
MyApp theApp = new MyApp();
theApp.pushScreen(new MyScreen());
theApp.enterEventDispatcher();
}
}
Thread pushThread = new Thread(){
public void run() {
if(get_DayOfWeek().startsWith("Mon"))
showMessage("Hello New Week ");
}
};
private void showMessage(String data) {
UiEngine ui = Ui.getUiEngine();
Screen screen = new Dialog(Dialog.D_OK, data, Dialog.OK,
Bitmap.getPredefinedBitmap(Bitmap.EXCLAMATION),
Manager.VERTICAL_SCROLL);
ui.queueStatus(screen, 1, true);
}
If today is Mon, it will display Dialog. But if today is Sunday, it will not display tomorrow. I want to always check the time but my code only check one time.
I repalce
public void run() {
if(get_DayOfWeek().startsWith("Mon"))
showMessage("Hello New Week ");
}
by
public void run() {
while (get_DayOfWeek() != null){
if(get_DayOfWeek().startsWith("Sun"))
showMessage("Hello New Day ");
}
}
but it said "Uncaught Exception, My notifacations is not responding, the process terminated "
Can anyone help me get way to always check the time ?
It is quite simple.
Implement RealtimeClockListener and use it in your application. In your implementation there will be method clockUpdated(). The BlackBerry Operating System will invoke this method every minute.
Use System.currentTimeMillis() in this method to get the current time and use Calendar class to calculate current weekday.
That's it.

Switch from one screen to another on BlackBerry

I want to switch from one screen to another - from a category screen to a detail screen - in my BlackBerry app. I don't know how to switch from one screen to another.
If you are in the event thread (the default thread your program runs on if it's a UI application and you haven't started any other threads), then opening up another screen can be done by calling the pushScreen() method of the UiApplication class.
Since, in a typical case, your application derives from UiApplication, you would take a reference to your application object and call pushScreen() on it with the parameter of your new screen:
myApp.pushScreen(new MyNewScreen());
If you're running in a worker thread, or in any context where you either don't have access to a UiApplication or pushing a screen would not be allowed (you're only allowed to work with UI components on the original UI thread), then pushing a screen onto the screen stack is a bit different -- you need to switch to the UI thread, and then push the new screen onto the screen stack:
Application.getApplication().invokeLater(
new Runnable() {
public void run() {
Ui.getUiEngine().pushScreen(new MyNewScreen());
}
}
);
At Antair, we have a simple ScreenChanger class that’s part of a larger internal library that we use for all of our projects. Here’s a stripped-down version of the ScreenChanger class for you to use.
// -----------------------------------------------------------------------------
//
// Antair Library for BlackBerry Devices
// ScreenChanger.java
//
// -----------------------------------------------------------------------------
package com.antair.blackberrylib.ui;
import net.rim.device.api.system.Application;
import net.rim.device.api.ui.Screen;
import net.rim.device.api.ui.Ui;
interface ScreenChangerListener
{
void onScreenChangeComplete(Screen openedScreen, Screen closedScreen);
}
final class ScreenChanger
{
static void change ( Screen screenToOpen, ScreenChangerListener listener )
{
ScreenChanger.change(screenToOpen, null, listener);
}
static void change ( Screen screenToOpen, Screen screenToClose,
ScreenChangerListener listener )
{
Application.getApplication().invokeLater(
new EventThreadScreenChanger(screenToOpen, screenToClose, listener));
}
static void close ( Screen screenToClose, ScreenChangerListener listener )
{
Application.getApplication().invokeLater(
new EventThreadScreenChanger(null, screenToClose, listener));
}
}
final class EventThreadScreenChanger extends Thread
{
Screen _screenToOpen;
Screen _screenToClose;
ScreenChangerListener _listener;
EventThreadScreenChanger ( Screen screenToOpen, Screen screenToClose,
ScreenChangerListener listener )
{
_screenToOpen = screenToOpen;
_screenToClose = screenToClose;
_listener = listener;
}
public void run()
{
if ( _screenToOpen != null )
{
try
{
Ui.getUiEngine().pushScreen(_screenToOpen);
}
catch ( Exception e )
{
// Your error handler
}
}
if ( _screenToClose != null )
{
try
{
Ui.getUiEngine().popScreen(_screenToClose);
}
catch ( Exception e )
{
// Your error handler
}
}
if ( _listener != null )
{
_listener.onScreenChangeComplete(_screenToOpen, _screenToClose);
}
}
}

BlackBerry - Simulate a KeyPress event

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

Resources