In the blackberry, I need the ability to start and close applications at certain times of the day. Say start at 8:00am and then close the app at 5:00pm. Is it possible to schedule applications this way in blackberry?
The functionality I am looking for would be similar to say cron in Unix or Windows scheduler.
I am not a developer. Is there an app which provides functionality similar to cron or windows scheduler?
You can use ApplicationManager's functionality to schedule the application launch:
ApplicationDescriptor descriptor = ApplicationDescriptor.getCurrentApplicationDescriptor();
ApplicationManager manager = ApplicationManager.getApplicationManager();
// Compute the time when it need to be scheduled
long toberuntime;
manager.scheduleApplication(descriptor ,toberuntime,true);
Also make note of date and timezone changes, as mentioned here
This is another example where a runnable is called to every minute.
Please note that you have to setup an alternate entry for the task and make sure it starts when the device starts. Application Manager is responsible for scheduling the job.
in this example, the device vibrates every time the background aep is called.
public static void main(String[] args)
{
// Create a new instance of the application and make the currently
// running thread the application's event dispatch thread.
if(args != null && args.length > 0 && "ticker".equals(args[0])){
scheduleUpdate();
}else{
UIapp theApp = new UIapp ();
theApp.enterEventDispatcher();
}
}
private static void scheduleUpdate() {
// TODO Auto-generated method stub
Alert.startVibrate(2550);
ApplicationDescriptor current = ApplicationDescriptor.currentApplicationDescriptor();
current.setPowerOnBehavior(ApplicationDescriptor.DO_NOT_POWER_ON);
ApplicationManager manager = ApplicationManager.getApplicationManager();
//check if device has booted and is ready..
if(!manager.inStartup()){
try{
TickerUpdateService tickerUpdater = new TickerUpdateService(endpointURL);
tickerUpdater.start();
}catch(Exception Ex){
System.out.println(Ex.getMessage());
}
}
manager.scheduleApplication(current, System.currentTimeMillis() + 60000, true);
}
Related
I am testing a .NET Core 2.0 app which uses the Service Bus SDK to retrieve messages from an Event Hub. I setup a console app to do that, and intend to run the app as a Docker container.
This method creates the Event Host Processor which will read the messages:
private static async Task MainAsync(string[] args)
{
Console.WriteLine("Registering EventProcessor...");
var eventProcessorHost = new EventProcessorHost(
EhEntityPath,
PartitionReceiver.DefaultConsumerGroupName,
EhConnectionString,
StorageConnectionString,
StorageContainerName);
// Registers the Event Processor Host and starts receiving messages
Console.WriteLine("Retrieving messages");
await eventProcessorHost.RegisterEventProcessorAsync<EventProcessor>();
Console.WriteLine("Sleeping");
Thread.Sleep(Timeout.Infinite);
}
As the event processor implemented in class EventProcessor will be the one handling the events, I am trying to prevent the console app to exit when the registration of the Processor is finished.
However, I can't find a reliable way to keep the app alive. If I run this container as-is, all I see in the output window is:
Registering EventProcessor...
Retrieving messages
Sleeping
and no messages are ever received.
Thanks all for the suggestions.
I followed those articles but eventually ended up with this, which applies specifically to .NET Core apps:
https://github.com/aspnet/Hosting/issues/870
I've tested it and the app can shutdown gracefully when it receives a termination signal from the Docker runtime.
UPDATE: this is the relevant sample from the GH issue link above:
public class Program
{
public static void Main(string[] args)
{
var ended = new ManualResetEventSlim();
var starting = new ManualResetEventSlim();
AssemblyLoadContext.Default.Unloading += ctx =>
{
System.Console.WriteLine("Unloding fired");
starting.Set();
System.Console.WriteLine("Waiting for completion");
ended.Wait();
};
System.Console.WriteLine("Waiting for signals");
starting.Wait();
System.Console.WriteLine("Received signal gracefully shutting down");
Thread.Sleep(5000);
ended.Set();
}
}
I am making an application that auto starts when the phone restarts. I want to run some events when the phone complets its restart. The UiApp is running even before the device finishes his reset cause I configured the app as an auto start app.
What event should I listen too and that starts when the phone completes the reboot, not in between?
Thanks
It is possible to know if the system is in startup by using :
ApplicationManager.isStartup()
You will need to poll this using a timer till it returns false. However it must be borne in mind that this means that the OS has booted and the system is able to run the application. It does not mean that the entire environment for your application to run is set up completely. For example (as noted by Michael) microSD card might not have been mounted, network connectivity might not been established, or some other service on which your application might depend is not yet available. It's up to you to verify they are available before you begin working of your application.
The approach you need to take is:
Poll if isStartup returns false (System is not in startup phase)
Implement FileSystemListener to check if microSD card is mounted.
Note that mount name for a microSD card is "SDCard".
class FileSystemListenerImpl implements FileSystemListener
{
final static String SDCARD_NAME ="SDCard/";
public FileSystemListenerImpl( )
{
}
public void rootChanged( int state, String rootName )
{
if( state == FileSystemListener.ROOT_ADDED)
{
if( SDCARD_NAME.equals(rootName))
{
_isMicroSDReady=true;
scheduleApplicationStart();
removeFileSystemListener(this);
}
}
else if( state == FileSystemListener.ROOT_REMOVED)
{
}
}
}
EDIT: Using simpler code.
I have a blackberry app that until recently (I upgraded to 6.0.0.600 on my torch) could be deleted. Now I can't even if I use javaloader -u erase (module in use) and the UI context menu or physical menu has no option for delete. The code below just requires an app descriptor with an alternate entry point on startup with parameters "startVibrate". The entry points code is below.
package mypackage;
import net.rim.device.api.system.Alert;
import net.rim.device.api.system.ApplicationDescriptor;
import net.rim.device.api.system.ApplicationManager;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.UiApplication;
/**
* This class extends the UiApplication class, providing a
* graphical user interface.
*/
public class ScheduleAppDemo extends UiApplication
{
public static void main(String[] args)
{
if (args != null && args.length > 0 && "startVibrate".equals(args[0]))
{
scheduleVibrate();
}
else
{
ScheduleAppDemo app = new ScheduleAppDemo();
app.enterEventDispatcher();
}
}
public ScheduleAppDemo()
{
ScheduleAppDemoScreen screen = new ScheduleAppDemoScreen();
pushScreen(screen);
}
public class ScheduleAppDemoScreen extends MainScreen
{
public ScheduleAppDemoScreen()
{
setTitle("Schedule app demo");
}
}
private static void scheduleVibrate()
{
Alert.startVibrate(2550);
ApplicationDescriptor current = ApplicationDescriptor.
currentApplicationDescriptor();
current.setPowerOnBehavior(ApplicationDescriptor.DO_NOT_POWER_ON);
ApplicationManager manager = ApplicationManager.getApplicationManager();
manager.scheduleApplication(current, System.currentTimeMillis()
+ 60000, true);
}
}
Basically what this shows you is that it vibrates every minute. Unfortunately evidence says it appears the Application Manager keeps the background process running during the time and then just calls it again when it's time to run occurs again. This is the sample app from RIM. Deleting all Alternate Entry Points in the Application descriptor.xml allows the app to be deleted. Other than modifying that, reloading the cods, and then deleting it; how can I delete the app.
The behavior is 'correct', in as far as this is exactly how an application with an alternate entry point would behave in the field.
When an application has an alternate entry point, deleting it only marks it for deletion. The actual deletion occurs when the device is restarted and the .cods are reloaded.
This is why, when a user tries to delete an application that has an alternate entry point with a running process in the background, a dialog box always pops up letting the user know that the application will be removed on restart, and asking whether they would like to reboot now.
Until the device is rebooted, the background process will continue to run.
I am trying to push the screen on may main UiApplication (MyApp) based on the either database is created or not and if its created than is it emapty or is it having some data..
but when i run this code my balckberry application jsts hangs ..
any help is appreciated :)
i have checked that the virtual SDCard is there in simulator and i have even code to check at runtime whether SDCard is avialable or not.
JDE Version 6.0 with Eclipse Helios
plug in BlackBerry Simulator : 9800
Os : windows 7 32 bit ultimate edition
below is my code that i am using in my app
public MyApp()
{
try {
MyAppURI = URI.create("file:///SDCard/BlackBerry/Database/"
+ "MyApp.db");
this.setMyURI(MyAppURI);
boolean flag = false;
flag = DatabaseFactory.exists(getMyURI());
if ( flag == false){
db = DatabaseFactory.create(getMyURI());
db.close();
new DatabaseSchema(); // this will simpaly create setting table in databse MyApp.db i am closing the database there
pushScreen(new Settings());
}else{
db = DatabaseFactory.open(getMyURI());
Statement st = db.createStatement("select count(*) from Setting");
Cursor cursor = st.getCursor();
if (cursor.isEmpty() == true){
pushScreen(new Settings());
}else{
pushScreen(new Reports());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
Ideally you should be running these database operations in their own Thread, as they are blocking operations. One thing that I've found helpful is to put my pushScreen()s in invokeLater() calls when I'm pushing them from a constructor if they aren't displaying properly. This allows the system to finish anything that needs to be done prior to displaying a Screen, and then it will be able to push.
I'm writing a stopwatch application for BlackBerry (which is similar to the BlackBerry built-in StopWatch). There is a timer label displaying current time in the format MM:SS:T (minutes, seconds, tenth of second). The label is refresh each 100 millisecond with TimerTask.
The application works well and the time is display correctly, however, there are some moments the timer label is not updated at the predetermined interval (each 100 milliseconds). The timer label pauses (not counting) for a while and continues counting (while still displays the time correctly)
My thought is the TimerTask is not executed to update the timer label during this pause. Do you know why the app act this way, and how to fix it?
Below are the Thread to update the timer label:
public class ThreadUpdateTime extends Thread
{
private MyMainScreen myMainScreen;
private Timer updateTimerLabelTimer = new Timer();
public ThreadUpdateTime(MyMainScreen parent)
{
myMainScreen=parent;
}
public void run()
{
try {
updateTimerLabelTimer.schedule(new RecordTimer(myMainScreen), TIMER_DELAY, TIMER_INTERVAL);
} catch (Exception e) {
//put alert here
}
}
public void iStop()
{
updateTimerLabelTimer.cancel();
}
}
the timerTask:
public class RecordTimer extends TimerTask
{
private MyMainScreen myMainScreen;
public RecordTimer(MyMainScreen parent)
{
myMainScreen=parent;
}
public void run()
{
myMainScreen.iUpdateTimerLabel();
}
}
and the iUpdateTimerLabel method:
public void iUpdateTimerLabel()
{
//calculate : sign, sMin, sSec, sTenth
synchronized(Application.getEventLock())
{
lblSpotTime.setText(sign+sMin+":"+sSec+"."+sTenth+" ");
}
}
First is to measure it... log the timestamps when your timertask begins and ends, and see if it's really the TimerTask that's really the problem. With that in hand, a couple of things that occur to me are,
Is your task blocking (maybe on
some UI thing)?
Are there other tasks in the same
Timer instance? I don't know if it's specified as such, but tasks probably all run on a single thread, so if another task is getting in the way, your tasks may not run at the exact specified interval.
Is your TimerTask properly synchronized with the UI event loop (i.e., is it updating the label in the correct runLater() or whatever method provided by the blackberry UI)? If you aren't doing this, the UI event loop may not notice that you've changed the label. I think on the Blackberry, the right thing is invokeLater() or maybe invokeAndWait(), depending on what you're trying to accomplish.
Edited after code posted:
A couple of useful and relevant resources are here.
OK, I'd still say to instrument your code with some logging or println calls to output
timestamps when it runs.
Not sure why the schedule() call is inside its own Runnable... you don't need that, but maybe your application is doing that for some reason I can't see. If you think you're creating an explicit thread for the timer, you're not. You can probably just create the Timer and call schedule() from whatever application thread is setting this up. Timer contains a captive thread that will do this work, and introducing Yet Another Thread is probably redundant and confusing.
I still think you may want to do something like:
Another reminder to actually MEASURE what the timer is doing rather than relying on my speculation...
code inside the TimerTask:
public void iUpdateTimerLabel()
{
//calculate : sign, sMin, sSec, sTenth
// synchronized(Application.getEventLock())
UiApplication.getUiApplication().invokeLater(
new Runnable() {
#Override
public void run() {
lblSpotTime.setText(sign+sMin+":"+sSec+"."+sTenth+" ");
}
});
}
Your synchronized call may be enough to keep things from blowing up, but it's not really the preferred means. If the Timer thread is dedicated to this single purpose, as it appears, you can probably replace invokeLater() with invokeAndWait() if you like.
Someone else may be able to elucidate the difference between just holding the UI lock and actually running on the UI thread, but my guess is that the latter forces an invalidate(), and the former does not. This would explain why your label changes are only showing up sporadically.