Continuos Vibrate and Music Alert until Confirmation : update

I had recently thought I solved my issue with creating a continuous vibrate and music alert for the BlackBerry application that I created for work. Unfortunately, when I put the fix on to the phone, the volume level of the music was very low, even though I had the volume set to 100%. So, it was back to the drawing board to try and figure out how to get this working. The main issue was determining if the music had finished and then starting it again until the user pressed a key.

After messing around with NotificationsEngineListener, Event and the Notifications Demo for what seemed like forever and continuing to get thread errors and other issues, it was a simple step back and regroup that helped me see the light. Instead of trying to kick off an event and a listener for the Notification, all I had to do was immediately kick off the Notification.

NotificationsManager.triggerImmediateEvent(bbhAttribute.NOTIFICATION_MESSAGEPAGE, 0, null, null);

I was already checking to see when the music had finished to determine if I needed to stop or continue. So, the simple step was to put the triggerImmediateEvent in the check.

public void audioDone(int reason)
{
	System.out.println("audioDone function");
	
	switch(reason) {
		case REASON_KEY_PRESSED:
			//System.out.println("Key Pressed.  Stopping Alert");
			stopAlert();
			break;
		case  REASON_COMPLETED:
			//System.out.println("Completed Called.  Stopping Alert");
			NotificationsManager.triggerImmediateEvent(bbhAttribute.NOTIFICATION_MESSAGEPAGE, 0, null, null);
			continueAlert();
			break;
		case REASON_STOP_CALLED:
			//System.out.println("Stop Called.  Do Nothing.");
			// Do nothing
			break;
	}
}

Which basically means, the initial music and vibrate will play and then when they are done and the user hasn’t clicked a button to stop it, the Notification will start before the music and vibrate plays again.

So far, this seems to be the working solution. I hope this is the final solution, because it has been a headache. I hope the BB10 method of notify users has something simple for continuous notification.

BB10 AIR Getting Started Completely

I have been meaning to get started on some BlackBerry 10 development, so I loaded the SDK for AIR and Flash Builder 4.6. With Flash Builder 4.6, you are supposedly able to create an iOS, Android or BlackBerry (tablet and BB10) application all at the same time. However, when you build for the least common denominator, you lose functionality for a specific platform. Because of this (and that I really don’t need to develop for iOS or Android at the moment) I started an application only for the BlackBerry.

While attempting to install VMWare for the virtual machine that allows for running the device simulators, I ran in to an install error. Apparently the key to this was to stop the installation right after you start, before it asks you to begin the final step and the actual install. At this point, the temporary files are extracted, which you should move to a new temporary folder location. When the files are there, stop the first install and then install using the msi file in the new location. I would give a screen shot of the point to stop the install, but I don’t want to uninstall it to get back to that point.

The good news with the BB10 simulators, is that I don’t have to configure a virtual machine, unlike how I had to do with the PlayBook simulator. Instead, I just go to the BlackBerry 10 Simulator program and run it to display the virtual machine simulator. Once it is running, then the Flash Builder can detect it so it can be set as one of options for debugging or playing. My only gripe is, the virtual machine image is much larger than real life and my normal display. I had to turn one of my monitors in a portrait position to run the simulators without the need for scrolling.

If I wanted to create a basic application, then I could have continued on my way with a View Navigator and such. However, I wanted to make sure I was utilizing all the features I could, which means using the native extensions and libraries. In the documentation for Configuring AIR, they show how to add the native extensions and that is pretty straight forward.

AIR setup Native Extensions

I did this and moved on. But, I wasn’t getting anywhere on how to create my screens. So, I imported the Hello World application located in samples directory of the installed SDK. When I did the import, it was full of errors that it couldn’t find qnx libraries. After making sure I did everything in the instructions, I did a search trying to find out why the library was missing. I found something on the support forum about looking for the correct path of the swc files. Not knowing if they libraries were setup correctly, I removed the ones that were there and then added the ones I could find under the frameworks.

AIR_setup_2

That’s all it took…..besides correcting the old library paths with new library paths changed since version 1 of the SDK.  I probably won’t need all the libraries, but it doesn’t hurt to have them available at the start.

And so begins the road of banging my head on my desk trying to figure out what is NOT documented for creating an application.

Continuos Vibrate and Music Alert until Confirmation

The main phone application that I support at work gets data pushed to it. Part of the data is a Message Page to notify the technician that they have a service call assigned or needing attention. Due to the nature of the service calls, the technician needs this alert to continually go off until they acknowledge the alert. A while back I changed the pop up message to a global message, which makes the pop up show on all screens, regardless if the user is in the application.

public static void displayGlobalMessage(final String gMessage)
{
	UiApplication.getUiApplication().invokeLater( new Runnable() {
			public void run() {
				UiEngine uie = Ui.getUiEngine();
				alertDialogListener  closeListener = new alertDialogListener();
				
				Dialog screen = new Dialog(Dialog.D_OK, gMessage, Dialog.OK,
											Bitmap.getPredefinedBitmap(Bitmap.EXCLAMATION),
											Manager.VERTICAL_SCROLL);
				screen.setDialogClosedListener(closeListener);
				uie.pushGlobalScreen(screen, 1, UiEngine.GLOBAL_MODAL);
			}
	});
}

Unfortunately, when I created this option, I some how broke my continuous alert that was previously setup. After many attempts to get it to work again, including using a TimerTask, I finally got the alert to work again.

The first part is creating the AlertListener class that I will use to handled starting the music and vibrate. This was the most important part, because stopping and starting the alert depends on what is to be called. It took a very long time to figure out when to turn off the overall alert (continueAlert) and when to turn on and off the music and vibrate (audioFinished). This is handled in the audioDone function, because the music plays longer than the vibration (which is why nothing is done on vibrateDone and buzzerDone).

public class SDAAlertListener implements AlertListener
{
    private boolean continueAlert;
    private Object continueAlertLock;
    private boolean audioFinished;
    private Object audioFinishedLock;
    
    public SDAAlertListener()
    {
    	//System.out.print("Added Continuos Alert Listener");
        continueAlert = true;
        continueAlertLock = new Object();
        audioFinished = false;
        audioFinishedLock = new Object();
    }
    
    public void startAlert()
    {
    	//System.out.println("Starting Contiuous Alert");
    	SetContinueAlertStatus(true);
    	SetAudioDoneStatus(false); 
    	
    	Alert.startAudio(music.myFogHornTune, 8);
    	Alert.startVibrate(500);
    }
    
    public void continueAlert()
    {
    	//System.out.println("Contiuous Alert to Continue");
    	SetContinueAlertStatus(true);
    	SetAudioDoneStatus(false); 
    	
    	Alert.startAudio(music.myFogHornTune, 8);
    	Alert.startVibrate(500);
    }
    
    public void stopAlert()
    {
    	//System.out.println("Stopping Contiuous Alert");
    	SetAudioDoneStatus(true); 
    	SetContinueAlertStatus(false);
    	
    	Alert.stopAudio();
        Alert.stopBuzzer();
    }
    
    public boolean GetContinueAlertStatus()
    {
        synchronized(continueAlertLock)
        {
            //System.out.println("Getting continueAlertStatus.");
            return continueAlert;
        }
    }
    
    public boolean GetAudioDoneStatus()
    {
        synchronized(audioFinishedLock)
        {
            //System.out.println("Getting buzzerFinished.");
            return audioFinished;
        }
    }
    
    public void SetContinueAlertStatus(boolean value)
    {
    	synchronized(continueAlertLock)
        {
        	//System.out.println("Setting ContinueAlert to " + value);
        	continueAlert = value;
        }
    }
    
    public void SetAudioDoneStatus(boolean value)
    {
        synchronized(audioFinishedLock)
        {
            //System.out.println("Setting audioFinished to " + value);
            audioFinished = value;
        }
    }
    
    public void audioDone(int reason)
    {
    	System.out.println("audioDone function");
    	
    	switch(reason) {
	    	case REASON_KEY_PRESSED:
	    		//System.out.println("Key Pressed.  Stopping Alert");
	    		stopAlert();
	    		break;
	    	case  REASON_COMPLETED:
	    		//System.out.println("Completed Called.  Stopping Alert");
	    		continueAlert();
	    		break;
	    	case REASON_STOP_CALLED:
	    		//System.out.println("Stop Called.  Do Nothing.");
	    		// Do nothing
	    		break;
    	}
    }
    
    public void buzzerDone(int reason)
    {
        // Do nothing.
    }
    
    public void vibrateDone(int reason)
    {
        // Do nothing.
    }
}

The next step is to create an instance of the listener on the main screen, so it is always there. This was one of the issues I was having, because I was adding the listener when the Message Page came in and then removing it after the alert was done. By creating the single listener, I only worry about starting and stopping the music and vibrate.

// Before the main screen is created
public static SDAAlertListener _sdaAlertListener = new SDAAlertListener();
// After the application is created and is only called once
((Application) UiApplication.getUiApplication()).addAlertListener(StartScreen._sdaAlertListener);

Next, I handled the Message Page by sending it to the GlobalMessage display function and creating a loop to check for when the Alert should be played again. The loop checks the Continue Alert Status to see if the button click hasn’t turned it off. Then it checks to see if the audio is done playing. If the Continue Alert is true and the Audio Done is true, then the startAlert function is called again to replay the music and vibration. Otherwise a break stops the loop.

/* Global Dialog display instead of screen pop */
bbhUtil.displayGlobalMessage("New Message Page " + MessagePagingInfo.getCurrentMessage());     
// Start Continuous paging section 
boolean alertStatus = true;
StartScreen._sdaAlertListener.startAlert();
// Start loop 
while (true)
{ 
	alertStatus = StartScreen._sdaAlertListener.GetContinueAlertStatus();
	if(alertStatus)
	{
		if(StartScreen._sdaAlertListener.GetAudioDoneStatus()) {
			//System.out.println("Audio Done Status is True");
			StartScreen._sdaAlertListener.startAlert();
		} else {
			break;
		}
	}
	else
	{ 
		System.out.println("Paging Alert Stop.");
		break;
	}                               
}

Finally, the Global Message display has a close listener attached to it. This listener calls the Alert stop function when the user clicks the “OK” button.

public class alertDialogListener implements DialogClosedListener {
	public void dialogClosed(Dialog dialog, int choice) {
		// Check for OK click and then stop Timer
		//System.out.println("Output Choice: " + choice);
   		 switch (choice) {
   		 	case Dialog.OK : 
   		 		synchronized(UiApplication.getEventLock())
   		 		{
   		 			//System.out.println("Calling Alert Listener Stop");
   		 			StartScreen._sdaAlertListener.stopAlert();
                }
        		break;
            case Dialog.CANCEL : 
            	Status.show("Cancel msg"); 
            	break;
        }
	}
}

This also allows for multiple Message Page alerts, since it turns on and off the same listener. I just wish I hadn’t taken so long in figuring it out.

Using BlackBerry Z10 and your game controller to play games

When I started hearing about QNX and BB10, I have always had the impression that the goal of the BB10 phones is that everything is an accessory to the phone.  Since… forever, there has been talk of wearable computers.  There have been many attempts at doing this, but most are clunky and not very practical.  As cell phones morphed from brinks to smart phones, the capabilities have increased to the point where today’s phones are more powerful than the computers I used in the 90s.  This advancement in technology pushes us closer to the wearable computer.  The main downfall to most wearable computer designs, is that the computer was supposed to control everything that is being worn.  My belief is the central computer is the brains and that any accessory added would expand the capability by telling the central computer what it does, but letting the central computer handle the input data to output as needed and so forth.  So, for example, if you put on a smart watch, it would tell the phone (central computer) what it can do, then the central computer would send the appropriate data to the watch, which would handle that data as it sees fit.

Beyond what you could wear, an accessory could even be your car.  QNX has been doing dashboards for cars as well as OnStar and uConnect.  The video below is a simple example of connecting the phone to the car and interacting between the two items.  The center console screen is actually a PlayBook which was the first BlackBerry device to run QNX.

So, this brings us to the Z10 and game pads.  The Z10 comes with game pad support.  Which means, if you develop a video game and want a real game controller, like the Wii Remote, to be used for playing, then Z10 will let you pair the BlueTooth enabled controller to do just that.  And, because the Z10, like the PlayBook, comes with an HMDI output connection, you can just plugin your phone to the television and sit back and play your games on the couch.

The real take away, is that the phone is now your computer/game console/central controller.  It can display the image onto a larger screen for you or receive information items attached to the phone.  Or, if you need more power, just connect multiple tablets or phones together to collaborate on an item.

Cursing the cursor

It would seem that every step to upgrade to OS 6 and use SQLite for my BlackBerry java application comes with its own little headaches. I’m sure there is some sort of documentation somewhere that would make it a little easier to do this coding. But, until then, I’ll just muddle along.

The key reason for using SQLite is so that I can populate the device-side information easily.  Unfortunately, the data sent to the device is not in the best format at the moment.  So, I have to take sudo HTML tables and parse them out into data to be stored in the SQLite table.  But, before I can do that, I needed to figure out which table is being sent.  When the application initializes the database, it adds values to a configuration table of the table name and the table id.  When the data is loaded, I grab the table name and then look in the configuration table to determine the id.  Then with the id, I can use a switch statement to process the data using the parser associated for that table.  Simple enough.  But, when the code was retrieving the table name, it would error and crash trying to determine the id.  It took a bunch of break points and stepping to finally figure out the issue.

Here is the code to get an Value while passing in an Attribute

       Statement statement = myDataBase.createStatement("SELECT value FROM myTable WHERE attribute = ?");
            statement.prepare();
            statement.bind(1, attribute);
            Cursor cursor = statement.getCursor();
            Row row;
            //Use first cursor spot
            cursor.first();
            // Get the row from the cursor
            row = cursor.getRow();
            thisValue = row.getString(0);

            statement.close();
            cursor.close();

The issue I had was on the getString(0) part. Instead of the first position being at 1, the first position is at 0. Sort of obvious, but I guess I was looking at the bind statement, which has the first position at 1.

Another simple thing I determined today, not being the expert Java developer, is that I can call the static instance of the database connection without having to pass it through to a different class function.  In other words, I created the appDB connection when the application opens up and I initialize the database connection.  I do this on a class called SQLManager.  Therefor, when I want to use the database connection, I can just use SQLManager.appDB anywhere in application.  I wasn’t sure this would work, but after a little test, I found that it did work and will help cut down on code when calling functions to update tables.

Upgrading from 4.5 to 6.0

At work I have been attempting to get our 800+ BlackBerry devices updated. This all began when we provided our service application to a site to use with their own technicians. The devices that we gave them were the BlackBerry Bold 9930. Luckily for me, I also got one of these devices and handed in an old 8800 BlackBerry. The Bold’s came with OS 7.0, but I updated mine to 7.1 in order to take advantage of the Hot Spot feature. Also, in OS 6 and 7, there is a feature for using Near Field Communication NFC tags. While most of the focus on NFC is payment, I see that my company can use the data storage and macros features for use with the service application.

But, the main reason for the upgrade to OS 6 or better, is the availability of SQLite on the phone. Previously, storing data on the BlackBerry devices was a little limited. It was similar to creating a very long text file and finding a particular item at a certain spot in order to get the data. In a word, it was clunky. Even though SQLite isn’t a full featured database, it is enough of a database to make inserting, updating and deleting data on the device much easier. So, I decided to delve in an update the old client application to version 6, which first required changing to Eclipse, more specifically, BlackBerry plugin for Eclipse. And changing to a new IDE and when you do that, you have re-setup your BlackBerry connections on the simulator to get things to work correctly.

With BlackBerry, you have a MDS that routes the pushes from a server to the appropriate device. On a simulator, you modify a rimpublic.properties file to make sure the data is okay to go to the device. An issue I had was that the push was failing. Because the push server had been already setup and I was just trying to get the simulator to receive the pushes, I didn’t have a direct look at the push command. One of the things you have to provide is the port of the application. When you setup up the device side listener to the wrong port, then your pushes never get to the application. D’oh! After I fixed that simple error, the data being pushed wasn’t displaying the entire data stream. The demo had the output example happen before the stream was repackaged back into a database, so only a portion was being shown. Oops. After I figured out to step to the parsing function after the push stream was finished. This was also an issue with opening and closing the database. The demo showed that every time you do a transaction to the database, you should open it and then close it. Well, that worked great in the simulator, but not so on the device. In the end, I found out that the best thing to do was open the database when the application was open and then not close it until I wanted to close the application for good.

The upgrade has been a slow start, but now it is moving along. Hopefully I can get the application converted and work on the new features that I want the application to do without too much more trouble.

PlayBook and Meetup Search so far

I have 1 review from my Meetup Search application for the PlayBook and it points out that Canadian zip codes don’t work :( , so I need to get the search features updated.  I have made some updates, but haven’t uploaded the changes yet, since I wanted to test the changes directly on the PlayBook, which I received last Thursday.  Hopefully I’ll get the search updates soon and improve my ratings on the App World.

I spent the weekend traveling and the PlayBook came in handy while waiting in airports and flying in the plane.  I was able to connect to wi-fi locations at Raleigh-Durham (RDU) and Atlanta without any issues.  At RDU, I used my AT&T DSL wireless account to connect for free, which was very nice.  Most of the time I had an available power outlet, so I didn’t see how far the battery lasted. I tried BlackBerry Bridge using my sister’s BlackBerry Flip to connect to.  Connection was simple, but due to cell coverage, using the browser was not very good.  I tried using Bridge on my wife’s BlackBerry when I got home and the browsing experience was much better, which leaves me to believe it was the network out in Kansas.  Also, I didn’t realize that Bridge does not connect the internet for the applications ; something that should be done using tethering.  However, according to the article, that might change in the future.

I discovered that GMail voice mail will just download the recording to my music list instead of playing the message from the inbox.  I guess that’s helpful if I wanted to store the message and play it back.

After loading music on the PlayBook, I tried to find radio apps, but didn’t find anything that I wanted to use.  I tried the Slacker Radio application, but apparently there is still something wrong with the app or my setup ( cause it costs $3/month ).  I found a couple of streaming servers that I might try to create a PlayBook app for, they are Audio Galaxy and Subsonic. Both take your music files and stream them on the internet, but one does it via a system service and the other as an application.  The APIs for both look fairly straight forward, so if I come up with a good interface, then it might be possible to use it for both options.  So many ideas, so little time to do stuff.

I tried some podcast downloads on the PlayBook to see what that is all about.  I guess it would be good if you don’t have wi-fi and wanted to listen to something besides the music playlist.   I added BlackBerry Today and downloaded their latest episode.  Heard on BlackBerry Today podcast :   There were 3,000 PlayBooks applications available and 40 – 50,000 PlayBooks (corrected on 5/18 podcast) sold on launch day, which was the most for any tablet launch.   The 6,000 participants at BlackBerry World conference all got a free PlayBook.

Here is the download chart for the month of April for Meetup Search.   Not tremendous, but not too bad.  I think improving the UI and adding search options will help with the downloads.  Also, I need to make the description a little prettier.  I think the form allows for HTML, since I’ve seen others use bullet lists.

A message from PlayBook

Last night I received my free BlackBerry PlayBook.  I immediately downloaded the updates and began to familiarize myself with it.  The first thing I need to get used to is using my finger pad instead of my nails. Touch response is different than with my phone.  But, I am getting used to it.  After a little trail and error, I have figured out how to load music, photos and files from my desktop.  I have loaded a few free apps to help with the flight layovers I’ll have this weekend.  Later, I think I will give more of a review.

I can successfully report that Gigya sign in with WordPress works on the PlayBook browser. I typed this post using my PlayBook.

Download graphing

The BlackBerry PlayBook was officially launched on April 19th.  I wasn’t expecting too much from my little Meetup Search application, because I don’t consider it done.  The API wasn’t a full release yet and I sort of rushed to finish it in time for the free PlayBook giveaway.  Now that the API 1.0.1 version has been released, I will go back and clean up my application.  I am still waiting for my free PlayBook, which was supposed to arrive to developers “around the time the device is available in the area”, which was on the 19th.  Rumor has it, we’ll all get them today on the 22nd.

Like I said, I didn’t expect a ton of downloads on the first day, of course analysts didn’t expect 50,000 in sales and pre-orders either.  So, I am glad to see that some people downloaded my free application.  Currently there isn’t a way to get a feed from the download page, so I guess I’ll have to export the graph on a regular basis.

Welcome to the App World

Today I made my Meetup Search available on the BlackBerry App World.  It is really rough right now and I am very eager to try it out on the BlackBerry PlayBook.  And why do I say I am “eager”, well it is because I will be getting a free PlayBook!  After going through the struggles of trying to create an application and getting the software, I got my app in before the deadline and now it is signed and ready for download.  And because it was in before the deadline and accepted, I qualified for the free PlayBook offer.  Rumors has it, that they will be shipping tomorrow, which would be awesome!

Where do I go from here?  Well, I would like to clean up the Meetup Search:

  • Adjust item layouts and fonts to make sure they work well on the device
  • Add GPS location search option : get the GPS latitude and longitude location and use that instead of zip.  “Meetups near me”
  • Add City Upcoming Events : The City Meetup pages is a nice feature that shows upcoming events, this might be useful
  • Add Map of Meetups search option :  show a map and have Meetups pop up on the map based on search options

I will probably try to add as many search possibilities as possible from the Meetup API and try to keep it up to date.  After that, I need to get OAuth working and start developing the Meetup user and Organizer applications.  In the mean time, I still have a movie to finish editing.