blackberry

Set the connection timeout for TCP connections through the BlackBerry MDS Connection Service

 

This is how to set the connection timeout for TCP connections through the BlackBerry MDS Connection Service.[1]

When making a Transmission Control Protocol (TCP) connection from a BlackBerry smartphone, the default connection timeout is 2 minutes. This value takes into consideration the possible time it can take a BlackBerry smartphone to be granted access to send data on the wireless network, and for the connection to travel over the wireless network over the Internet to the destination server and back again. In some circumstances, this value is too long. When making a socket or Hypertext Transfer Protocol (HTTP) connection through the BlackBerry® Mobile Data System (BlackBerry MDS) Connection Service, it is possible to set the timeout value to a lower value than the value that is configured in the BlackBerry MDS Connection Service. By default, the value is 2 minutes. It is not possible to extend beyond the limit configured on the server. Use theConnectionTimeout parameter to specify the timeout value. This parameter accepts a numerical value in milliseconds. The following is an example of an HTTP connection with a timeout value of 1 minute:

StreamConnection s = (StreamConnection)Connector.open("http://myserver.com/mypage.html;ConnectionTimeout=60000;deviceside=false");
HttpConnection httpConn = (HttpConnection)s;

 

Note: The ConnectionTimeout parameter is not supported by direct TCP connections or connections through a Wireless Application Protocol (WAP) gateway. Only TCP connections, made through the BlackBerry MDS Connection Service, support this parameter.

[1] http://www.blackberry.com/knowledgecenterpublic/livelink.exe/fetch/2000/348583/800451/800563/How_To_-_Control_the_connection_timeout_for_TCP_connections_through_BlackBerry_Mobile_Data_System_Connection_Service.html?nodeid=1235131&vernum=0


Create Customized Field to Show Graphs on BlackBerry

 

Sometimes you need to show Graphs on BlackBerry Applications, instead of using Google chart as image on the Applications,

you can use the Blackberry Charts samples below.

The following sample code demonstrates how to create custom graph fields. The sample contains the following classes:

  • BarGraphField – A custom field that draws a bar graph
  • BarScreen – A screen demonstrating the use of BarGraphField
  • BlackBerryGraphs – The main application
  • GraphDemoScreen – The introductory screen for the sample application that allows a BlackBerry smartphone user to choose the type of graph to preview
  • GraphField – The base class that the other *GraphFields extend
  • LegendField – A custom field that draws a legend
  • LineGraphField – A custom field that draws a line or scatter graph
  • LineScreen – A screen demonstrating the use of LineGraphField
  • PieGraphField – A custom field that draws a pie chart
  • PieScreen – A screen demonstrating the use of PieGraphField and LegendField

The entire sample can be downloaded here. The following are some sample screen shots that illustrate the custom graph fields.

To access the sample code, download the attached BlackBerryGraphs.download-pdf-renameto.zip file.

Bar Graph Demo on BlackBerry App

Line/Scatter Graph Demo on BlackBerry App

Pie Graph Demo on BlackBerry App

[1] http://www.blackberry.com/knowledgecenterpublic/livelink.exe/fetch/2000/348583/800332/800505/800345/How_To_-_Create_graph_fields.html?nodeid=1889634&vernum=0


Backdoor Sequence for Production and Development

 

Do you ever use alt+LGLG or alt+ESCR in the homescreen?

that’s sample of Backdoor sequence usage..

[1]

Description

 

On a BlackBerry device, there are a number of backdoor sequences that can be invoked when the home screen is displayed (such as holding the ALT key and typingESCR to show the BlackBerry device information). With JDE 4.2, this same backdoor functionality can be included in any screen via two new methods in the net.rim.device.ui.Screen class that can be overridden: openProductionBackdoor(int backdoorCode) and openDevelopmentBackdoor(int backdoorCode). The difference between the two methods is that openDevelopmentBackdoor(int backdoorCode) will only be invoked if the application is run in the simulator (but if both methods are implemented, then both methods will be invoked from within the simulator).

 

The following is an example implementation that will cause VAKS to be used as a backdoor sequence.

 

Note: This backdoor sequence will only be executed if the screen implementing this code is in the foreground.

 

protected boolean openProductionBackdoor(int backdoorCode) {
    switch( backdoorCode ) {
         	 // BACKDOOR – converts four chars to an int via bit shifting and a
          // bitwise OR
          case ( 'V' << 24 ) | ( 'A' << 16 ) | ( 'K' << 8 ) | 'S':
            UiApplication.getUiApplication().invokeLater (new Runnable() {
                public void run()
                {
                   Dialog.inform("Backdoor sequence received");
                }
            });
            return true; // handled
        }
        return super.openProductionBackdoor(backdoorCode);
    }

 

[1] http://www.blackberry.com/knowledgecenterpublic/livelink.exe/fetch/2000/348583/800332/800505/800256/How_To_-_Use_a_Backdoor_Sequence.html?nodeid=1287199&vernum=0


Clickable text or label field

Sometimes we need to make a text field or label field with clickable function,
here’s some example gathered from several sources.

[0] overwrite the related methods

LabelField _testLink = new LabelField("Test", Field.FOCUSABLE | Field.USE_ALL_WIDTH) {
    protected boolean navigationClick(int status, int time) {
        System.out.println("Linked");
        return true;
    }
};

[1] href field

import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.FontFamily;
import net.rim.device.api.ui.Graphics;

public class HrefField extends Field {

private String content;
private Font fieldFont;
private int fieldWidth;
private int fieldHeight;
private boolean active = false;
private int backgroundColour = 0xffffff;
private int textColour = 0x333333;
private int maskColour = 0xBBBBBB;

public HrefField(String content) {
super(Field.FOCUSABLE);
this.content = content;
fieldFont = defaultFont();
fieldWidth = fieldFont.getAdvance(content)+2;
fieldHeight = fieldFont.getHeight() + 3;
}

public void setColours(int backgroundColour, int textColour, int maskColour) {
this.backgroundColour = backgroundColour;
this.textColour = textColour;
this.maskColour = maskColour;
invalidate();
}

public void setBackgroundColour(int backgroundColour){
this.backgroundColour = backgroundColour;
invalidate();
}

public void setTextColour(int textColour){
this.textColour = textColour;
invalidate();
}

public void setMaskColour(int maskColour){
this.maskColour = maskColour;
invalidate();
}

public void setFont(Font fieldFont){
this.fieldFont = fieldFont;
}

public int getPreferredWidth() {
return fieldWidth;
}

public int getPreferredHeight() {
return fieldHeight;
}

protected void layout(int arg0, int arg1) {
setExtent(getPreferredWidth(), getPreferredHeight());
}

protected void paint(Graphics graphics) {

if (active) {
graphics.setColor(maskColour);
graphics.fillRect(0, 0, fieldWidth, fieldHeight);
} else {
graphics.setColor(backgroundColour);
graphics.fillRect(0, 0, fieldWidth, fieldHeight);
}

graphics.setColor(textColour);
graphics.setFont(fieldFont);
graphics.drawText(content, 1, 1);
graphics.drawLine(1, fieldHeight-2, fieldWidth-2, fieldHeight-2);
}

protected boolean navigationClick(int status, int time) {
fieldChangeNotify(1);
return true;
}

protected void onFocus(int direction) {
active = true;
invalidate();
}

protected void onUnfocus() {
active = false;
invalidate();
}

public static Font defaultFont() {
try {
FontFamily theFam = FontFamily.forName("SYSTEM");
return theFam.getFont(net.rim.device.api.ui.Font.PLAIN, 14);
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
return null;
}
}

[2] CustomButtonField

package com.thinkingblackberry;

import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Keypad;

public class CustomButtonField extends Field {
	private String label;
	private int textColorUnfocused;
	private int textColorFocused;
	private int backgroundColorUnfocused;
	private int backgroundColorFocused;

	private int horizontalPadding = 5;
	private int verticalPadding = 5;

	public CustomButtonField(String label, int textColorUnfocused,
			int textColorFocused, int backgroundColorUnfocused,
			int backgroundColorFocused, long style) {
		super(style);
		this.label = label;
		this.textColorUnfocused = textColorUnfocused;
		this.textColorFocused = textColorFocused;
		this.backgroundColorUnfocused = backgroundColorUnfocused;
		this.backgroundColorFocused = backgroundColorFocused;
	}

	protected void layout(int maxWidth, int maxHeight) {
		Font font = getFont();
		int width = font.getAdvance(label) + (horizontalPadding * 2);
		int height = font.getHeight() + (verticalPadding * 2);
		// Respect the maximum width and height available from our manager
		setExtent(Math.min(width, maxWidth), Math.min(height, maxHeight));
	}

	protected void paint(Graphics graphics) {
		// Draw background
		graphics.setColor(isFocus() ? backgroundColorFocused : backgroundColorUnfocused);
		graphics.fillRoundRect(0, 0, getWidth(), getHeight(), 10, 10);

		// Draw text
		graphics.setColor(isFocus() ? textColorFocused : textColorUnfocused);
		graphics.drawRoundRect(0, 0, getWidth(), getHeight(), 10, 10);
		int fontWidth = getFont().getAdvance(label);
		graphics.drawText(label, (getWidth()-fontWidth)/2, verticalPadding);
	}

	protected void drawFocus(Graphics graphics, boolean on) {
		// Don't draw the default focus
	}

	protected void onFocus(int direction) {
		super.onFocus(direction);
		invalidate();
	}

	protected void onUnfocus() {
		super.onUnfocus();
		invalidate();
	}

	public boolean isFocusable() {
		return true;
	}

	protected boolean navigationClick(int status, int time) {
		fieldChangeNotify(0);
		return true;
	}

	protected boolean keyChar(char character, int status, int time) {
		if (character == Keypad.KEY_ENTER) {
			fieldChangeNotify(0);
			return true;
		}
		return super.keyChar(character, status, time);
	}

	public String getLabel() {
		return label;
	}
}

[1] http://www.northcubed.com/site/?p=6
[2] http://www.thinkingblackberry.com/source/CustomButtonField.java


Leverage pattern matching in BlackBerry

 

Background

You may have noticed how certain strings are underlined in native BlackBerry smartphone applications. For example, phone numbers are underlined or highlighted when composing or reading messages. Once selected, these special strings are assigned a context-sensitive menu item, for example call a phone number. Third-party applications can take advantage of this functionality to add custom context-sensitive menu items to standard BlackBerry smartphone applications. These menu items can be used to launch a custom application, open the BlackBerry® Browser to a specific URL, send a message, or do any number of other things.

This functionality can be achieved by using one of two application programming interfaces (APIs):

  1. net.rim.device.api.util.StringPattern – This API was introduced in BlackBerry Device Software 4.0 and requires you to implement your own string matching algorithm.
  2. net.rim.blackberry.api.stringpattern.PatternRepository – This API was introduced in BlackBerry Device Software 4.3.0, and allows the use of Perl style regular expressions.

The samples provided in this article match a United States zip code and allow the BlackBerry smartphone user to lookup more information on the zip code.

Procedure

net.rim.device.api.util.StringPattern

The StringPattern source code example uses the string pattern matching that was introduced in BlackBerry Device Software 4.0. It requires implementing another string matching algorithm.

There are four major components required for this implementation

net.rim.device.api.util.StringPattern – This class represents the pattern that you want to recognize. It can be as simple as a zip code, or as complex as an address in its various forms. To write an effective StringPattern, remember that each character typed into the applicable field will be parsed by your implementation. As such, efficiency is important in this class.

net.rim.device.api.ui.component.MenuItem – The MenuItem includes the majority of the implementation for this capability. The MenuItem typically includes or references the action that will occur once a match is found and invoked by the BlackBerry smartphone user. For example, the run method for the MenuItem is invoked when a zip code has been recognized and the BlackBerry smartphone user selects the Lookup Zipcode menu item.

net.rim.device.api.ui.component.ActiveFieldCookie – The ActiveFieldCookie is a container object that allows the StringPattern class to transfer the context-sensitive information to the MenuItem. It also allows the implementation to add the appropriate menu item, or multiple menu items, when a string pattern match is found.

net.rim.device.api.util.Factory – The implementation of the Factory class links the StringPattern to the ActiveFieldCookie when a match is recorded in the StringPattern implementation. Typically, the Factory implementation is quite compact but a necessary requirement for the system.

The ZipCodeLookupSample class provides the starting point for the application. The application is configured as an auto-start system module so that all of the components can be registered upon start up. It is important to note that the main class initializes all of the required components described above, and has been implemented carefully to only initialize these components once.

net.rim.blackberry.api.stringpattern.PatternRepository

The PatternRepository source code sample uses the API that was introduced in BlackBerry Device Software 4.3.0 and allows the use of regular expressions for string matching, which makes the sample much simpler than the prior sample.

There are two major components required for this implementation

net.rim.blackberry.api.stringpattern.PatternRepository – This class will register a Perl-style regular expression or a specific string with the systems pattern repository. When a match is found the ApplicationMenuItem(s) associated with the pattern will appear in the current application’s menu.

net.rim.blackberry.api.menuitem.ApplicationMenuItem- The ApplicationMenuItem includes the action that will occur once a match is found and is invoked by the BlackBerry smartphone user.

The application is once again configured as an auto-start system module. This is done to register the regular expression and menu item with the systems pattern repository upon system start up.

To access the sample code, download the attached ZipCodeLookupSamples.download-pdf-renameto.zip file.

[1] http://www.blackberry.com/knowledgecenterpublic/livelink.exe/fetch/2000/348583/800332/800505/800608/How_to_-_Leverage_pattern_matching_in_BlackBerry_smartphone_applications_to_provide_an_integrated_user_experience.html?nodeid=1234285&vernum=0


How to Implement a Web Cache for BrowserField2

So, loading pages on your BrowserField2 application is taking quite some time and yet your app is repeatedly loading the same pages over and over again spending network bandwidth and providing a poor performance experience to users?


You’ve been thinking of implementing a web cache but has no idea how to extend the BrowserField2 (a.k.a. BF2) API for that purpose?


This article is definitely for you!


 


 

Goal

 

This article discusses how the BrowserField2 API (BlackBerry® Device Software 5.0 and later) can be properly extended to implement a simple web cache mechanism that will speed up the loading of pages and resources in a BF2 application significantly reducing bandwidth usage, server load, and ultimately improving the user experience. The code provided (please check the attachments) should serve as a basis for developers to build their own professional caching mechanism tailored to their particular needs.

 

The term “web cache” (from now on simply referred to as “cache“) will be used throughout this article to refer to a cache of HTTP resources (e.g., a web page, an image, a css file) in which HTTP headers and page content (sequence of bytes) are store together in a cache entry and later used to quickly reload HTTP resources. In terms of data persistency the source code provided implements a “short-term cache“, i.e.,  a cache that will not persist data after a device boot. For further information on web caches and related terminology please refer to the corresponding Wikipedia article: http://en.wikipedia.org/wiki/Web_cache.

 

 

BrowserField2 API and the ProtocolController

 

The BrowserField2 API, introduced with the release of BlackBerry Device Software 5.0, allows BlackBerry developers to embed Web content into their Java applications. As a result, developers are able to quickly build BlackBerry applications that easily integrate with legacy back-end web-based systems. In addition, BrowserField2 applications running on OS 6.0 benefit from the high-quality and top-notch performance of the BlackBerry Webkit rendering and Javascript engines.

 

Despite the richness in functionality and ease-of-development provided by the BrowserField2 API, a caching mechanism for loading webpages does not come standard. That is, requesting the same web page twice will require establishing different connections with the web server to retrieve the page’s content. The good news is that a caching mechanism can be implemented straighforwardly by extending the BrowserField2 API, in particular one of its core components called the ProtocolController as we cover next.

 

 

 

 

Figure 1: The Role of the ProtocolController in the BrowserField2 API
(Figure extracted from BlackBerry DEVCON 2010 – DEV49 technical session)

 

 

The ProtocolController, depicted in Figure 1, reprsents the default implementation of the BrowserFieldController abstract component. The ProtocolControllerhandles navigation (e.g., a link was clicked on your page) and resource (e.g., an image or a CSS file needs to be loaded in your page) requests through a variety of protocols (e.g., http, https, local, file) and is responsible for providing a valid connection to a remote resource and, in some cases, for properly displaying the contents of a requested page on the screen.

 

Overriding the ProtocolController allows developers to intercept all kinds of page and resource requests and thus to customize the standard behavior. For instance, an application might be interested in checking the credentials of a user before giving her access to a particular page or resource. In fact, the BlackBerry® WebWorks™ application technology applies this very same strategy.

 

In particular, extending the standard controller is ideal for implementing the caching mechanism cover in this article since all requests are made via the controller. As shown in Figure 1, developers can either extend the abstract BrowserFieldController or its default implementation the ProtocolController. This article will use the latter approach as the ProtocolController provides convenient functionality that can be readily reused.

 

Creating a CacheProtocolController

 

Figure 2 depicts the four components created to implement the BF2 caching system discussed in this article, i.e.,  the CacheManager interface and classesCacheProtocolControllerCacheManagerImpl and CacheItem as depicted in Figure 2. There is also the application entry point class BF2CacheSampleAppthat can be found in the attached source code.

 

 

 

Figure 2: Extending the ProtocolController to create a web cache

 

The CacheProtocolController class extends the default controller to link page requests to the cache component. The cache controller checks if a given page/resource request is cacheable and if so it either retrieves the resource from the cache (cache hit) of downloads the resource and stores it in the cache for later use (cache miss).

 

The code for the CacheProtocolController is show below. Methods handleNavigationRequest() and handleResourceRequest() override the default controller. Method handleNavigationRequest() reuses method handleResourceRequest() to retrieve a connection to the requested resource and afterwards requests the BrowserField to render the content via a call to method displayContent(). Method handleResourceRequest() first checks if the requested resource can be cacheable (using the CacheManager object). If the resource is not cacheable, the CacheProtocolController forwards the call to the standard controller via super.handleResourceRequest(). If the resource is cacheable and is already in the cache and not expired an InputConnection is created by theCacheManager and returned. If the resource is not in the cache, the standard controller’s functionality is called to retrieve a connection to the resource and theCacheManager creates a cache entry for that resource.

 

 

public class CacheProtocolController extends ProtocolController{

	// The BrowserField instance
    private BrowserField browserField;

    // CacheManager will take care of cached resources
    private CacheManager cacheManager;

	public CacheProtocolController(BrowserField browserField) {
		super(browserField);
                this.browserField = browserField;
	}

	private CacheManager getCacheManager() {
		if ( cacheManager == null ) {
			cacheManager = new CacheManagerImpl();
		}
		return cacheManager;
	}

	/**
	 * Handle navigation requests (e.g., link clicks)
	 */
	public void handleNavigationRequest(BrowserFieldRequest request)
            throws Exception {
		InputConnection ic = handleResourceRequest(request);
		browserField.displayContent(ic, request.getURL());
	}

	/**
	 * Handle resource request (e.g., images, external
         * css/javascript resources)
	 */
	public InputConnection handleResourceRequest(BrowserFieldRequest request)
              throws Exception {

	   // if requested resource is cacheable
           // (e.g., an "http" resource), use the cache
	   if (getCacheManager() != null &&
               getCacheManager().isRequestCacheable(request)) {
               InputConnection ic = null;
               // if requested resource is cached, retrieve it from cache
               if (getCacheManager().hasCache(request.getURL()) &&
                   !getCacheManager().hasCacheExpired(request.getURL())) {
                   ic = getCacheManager().getCache(request.getURL());
               }
               // if requested resource is not cached yet, cache it
               else {
            	  ic = super.handleResourceRequest(request);
                  if (ic instanceof HttpConnection) {
                     HttpConnection response = (HttpConnection) ic;
                     if (getCacheManager().isResponseCacheable(response)) {
                        ic = getCacheManager().createCache(request.getURL(),
                                                            response);
                     }
                  }
               }
               return ic;
	   }
	   // if requested resource is not cacheable make a standard request
	   return super.handleResourceRequest(request);
	}

}

 

Note that the algorithm implemented in method handleResourceRequest() relies heavily on the CacheManager interface. Developers reading this article might want to create their own implementation of the that interface (or extend the class CacheManagerImpl) to customize the cache functionality discussed in this article. The reader is encouraged to have a careful look at the source code provided especially class CacheManagerImpl that provides a basic caching implementation used by the CacheProtocolController.

 

It is out of the scope of this article to discuss the implementatoin details of class CacheManagerImpl. Yet understanding this class by looking into the source code should be pretty straightforward.

 

Attaching the new CacheProtocolController to the Sample Application

 

The last step towards enabling caching on your BF2 application is to attached the new CacheProtocolController component to the BrowserField object. In the sample application provided (see class BF2CacheSampleApp in the attachments) the new controller is attached to the BrowserField as shown in the code  below:

 

browserField = new BrowserField();
browserField.getConfig().setProperty(BrowserFieldConfig.CONTROLLER,
                                     new CacheProtocolController(browserField));

 

The reader is strongly encouraged to check the slides of the DEV 49 session entitled “Customizing BrowserField2 Advanced Components” presented at the DEVCON 2010.The slides cover several other extensible points of the BrowserField2 API and can be found in the BlackBerry Developer Zone portal.

 

 

Have fun with your BrowserField2 Web Cache!

 

BF2CacheSampleApp-download-pdf-renameto.zip

 

[1] http://supportforums.blackberry.com/t5/Java-Development/How-to-Implement-a-Web-Cache-for-Your-BrowserField2-Application/ta-p/817911


Invoke a Permission Requests

The ApplicationPermissionsManager API offers a way to streamline the request for application permissions to improve the user experience. The API allows an application to request all required permissions at one time and tell the user why the permissions are needed. Applications are also able to determine which permissions they have and if its is possible to get the desired level of permissions.

However, concurrent requests for permissions were not possible until BlackBerry® Device Software 5.0.0.796, Bundle 1342. If the application permissions screen was open when another application (or another entry point of the same application) requested permissions, the request would fail with an exception in some cases or would simply fail silently with no request shown to the user. The exception seen was an IllegalArgumentException, with the message “object already exists”. This is due to the single allowed permissions screen before the limitation was fixed.

The attached sample code shows how to make permission requests in the background which account for these situations more gracefully.

  • Since only one permissions request can be handled at a time, the sample code foregrounds a hidden permissions screen in case the user had dismissed it or another application had taken the foreground.
  • After foregrounding any prior screens, the applications own request is queued up using the ApplicationPermissionsManager API.
  • If it fails with the IllegalArgumentException “object already exists”, then the request is re-queued when the application is foregrounded again, since the user must handle the existing permission request first.
  • The sample also handles instances where the user has put the permissions request into the background but tries to run the application again, and it has been altered to not show any the main UI until the permissions have been accepted. This is not always the best choice of user experience, but may be desired by some applications.
import net.rim.device.api.applicationcontrol.ApplicationPermissions;
import net.rim.device.api.applicationcontrol.ApplicationPermissionsManager;
import net.rim.device.api.system.ApplicationDescriptor;
import net.rim.device.api.system.ApplicationManager;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.EventLogger;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.Ui;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.UiEngine;
import net.rim.device.api.ui.component.BasicEditField;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.DialogClosedListener;
import net.rim.device.api.ui.container.MainScreen;

public class BackgroundPermissions extends UiApplication {

	private long UID = 0x85d1d1d3e756befdL;

	private HarnessScreen screen;

	public BackgroundPermissions(boolean gui) {
		EventLogger.register(UID, "BackgroundPermissions", EventLogger.VIEWER_STRING);
		if (gui) {
			screen = new HarnessScreen();
			screen.checkPermissions();
		} else {
			while (ApplicationManager.getApplicationManager().inStartup()) {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			new BackgroundPermissionsCheck().start();
		}
	}

	public void log(String message) {
		if (message != null) {
			System.out.println(message);
			EventLogger.logEvent(UID, message.getBytes(), EventLogger.ALWAYS_LOG);
		}
	}

	private class BackgroundPermissionsCheck extends Thread {
		public void run() {
			String message = "Requesting permissions";
			System.out.println(message);
			EventLogger.logEvent(UID, message.getBytes(), EventLogger.ALWAYS_LOG);

			ApplicationPermissions perms = ApplicationPermissionsManager.getInstance().getApplicationPermissions();
			perms.addPermission(ApplicationPermissions.PERMISSION_RECORDING);
			boolean result;
			synchronized (UiApplication.getEventLock()) {
				result = ApplicationPermissionsManager.getInstance().invokePermissionsRequest(perms);
			}
			if (result) {
				message = "Accepted Permissions ... returned true to Listener";
			} else {
				message = "Did not accept Permissions .. returned false to Listener";
			}
			System.out.println(message);
			EventLogger.logEvent(UID, message.getBytes(), EventLogger.ALWAYS_LOG);
			System.exit(0);
		}
	}

	public void activate() {
		log("Activate");
		if (screen != null) {
			log("Screen exists");
			if (screen.isCheckingPermissions()) {
				log("Screen is waiting on permissions");
				if (screen.isPermissionsScreenInBackground() >= 0) {
					screen.foregroundPermissionsScreen();
				} else {
					screen.checkPermissions();
				}
			} else if (screen.isQueueAfterException()) {
				screen.checkPermissions();
			}
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		BackgroundPermissions app;
		if (args != null && args.length > 0 && args[0].equals("gui")) {
			app = new BackgroundPermissions(true);
		} else {
			app = new BackgroundPermissions(false);
		}
		app.enterEventDispatcher();
	}

	private class HarnessScreen extends MainScreen {

		private BasicEditField log = new BasicEditField("Log: ", "");

		private boolean checkingPermissions = false;
		private boolean queueAfterException = false;

		public HarnessScreen() {
			setTitle("Sync Listener");
			add(log);
		}

		public synchronized void checkPermissions() {
			new PermissionsCheck().start();
		}

		public synchronized boolean isCheckingPermissions() {
			return checkingPermissions;
		}

		public synchronized boolean isQueueAfterException() {
			return queueAfterException;
		}

		public void foregroundPermissionsScreen() {
			int processId = isPermissionsScreenInBackground();
			if (processId >= 0) {
				foregroundPermissionsScreen(processId);
			}
		}

		private void foregroundPermissionsScreen(int processId) {
			ApplicationManager.getApplicationManager().requestForeground(processId);
		}

		/**
		 * Check for the permissions screen hidden in the background
		 *
		 * @return process Id of the screen, or -1 if not running
		 */
		private int isPermissionsScreenInBackground() {
			ApplicationDescriptor[] apps = ApplicationManager.getApplicationManager().getVisibleApplications();
			for (int i = 0; i < apps.length; i++) {
				if (apps[i].getModuleName() != null && apps[i].getModuleName().equals("net_rim_bb_application_permissions_proxy")) {
					int processId = ApplicationManager.getApplicationManager().getProcessId(apps[i]);
					log("Permission screen found at " + processId);
					return processId;
				}
			}
			return -1;
		}

		private class PermissionsCheck extends Thread {

			public void run() {
				if (!hasPermissions()) {
					log("Permissions not valid");
					requestPermissions();
				} else {
					log("Permissions Valid");
					synchronized (UiApplication.getEventLock()) {
						pushScreen(screen);
					}

				}
			}

			public boolean hasPermissions() {
				ApplicationPermissions perms = ApplicationPermissionsManager.getInstance().getApplicationPermissions();
				return checkPermission(perms, ApplicationPermissions.PERMISSION_RECORDING, "Recording");
			}

			public boolean checkPermission(ApplicationPermissions perms, int permission, String name) {
				int setting = perms.getPermission(permission);
				log("Checking " + name + " Permission: " + setting);
				if (setting != ApplicationPermissions.VALUE_ALLOW) {
					return false;
				}
				return true;
			}

			public ApplicationPermissions getDesiredPermissions() {
				ApplicationPermissions perms = ApplicationPermissionsManager.getInstance().getApplicationPermissions();
				perms.addPermission(ApplicationPermissions.PERMISSION_RECORDING);
				return perms;
			}

			public void requestPermissions() {
				log("Foregrounding any existing request");
				foregroundPermissionsScreen();
				queueAfterException = false;
				checkingPermissions = true;
				try {
					log("Enter invokePermissionsRequest : result must be True, False or Exception. ");
					boolean result = ApplicationPermissionsManager.getInstance().invokePermissionsRequest(getDesiredPermissions());
					if (result) {
						log("result: true - User accepted request");
						synchronized (UiApplication.getEventLock()) {
							pushScreen(screen);
						}
					} else {
						log("result: false - User did not accept request");
					}
				} catch (Throwable t) {
					log("result - exception : " + t.toString());
					if (t instanceof IllegalArgumentException) {
						// Queue up request again.
						log("Queueing");
						queueAfterException = true;
					}
				} finally {
					checkingPermissions = false;
					if (!isQueueAfterException()) {
						log("Enter ShowErrorAlertandCloseGui()");
						ShowErrorAlertandCloseGui();
					}
				}

			}

			private void ShowErrorAlertandCloseGui() {
				Dialog dialog = new Dialog(Dialog.D_OK, "-- Error Message -- ", Dialog.YES, Bitmap.getPredefinedBitmap(Bitmap.EXCLAMATION),
						Manager.VERTICAL_SCROLL);
				dialog.setEscapeEnabled(false);
				dialog.setDialogClosedListener(new DialogClosedListener() {
					public void dialogClosed(Dialog dialog, int i) {
						if (i == Dialog.OK) {
							log("ShowErrorAlertandCloseGui ********* System.exit(0) ****** ");
							System.exit(0);
						}
					}
				});
				try {
					log("To push global screen,  synchronized(Application.getEventLock())");
					synchronized (UiApplication.getEventLock()) {
						log("ShowErrorAlertandCloseGui - Enter pushGlobalScreen() ");
						Ui.getUiEngine().pushGlobalScreen(dialog, 1, UiEngine.GLOBAL_QUEUE);
						log("ShowErrorAlertandCloseGui - Exit pushGlobalScreen() ");
					}
				} catch (Exception e) {
					log("Exception - ErrorHandling.askGlobalDialogOK: " + e.toString());
				}
			}

		}

	}

}

[1] http://supportforums.blackberry.com/t5/Java-Development/How-to-Invoke-a-Permissions-request-with-other-applications-also/ta-p/652397

[2] http://supportforums.blackberry.com/t5/Java-Development/What-is-Best-practices-in-working-with-ApplicationPermissions/ta-p/624740


Add Setting to the BlackBerry Options

The Options application – or Settings on some BlackBerry themes – provides a unified location to set BlackBerry options and configure applications. A BlackBerry application can also add its own options to this listing, allowing a user to configure an application from outside of the application. This can be very useful for background applications that do not use a graphical user interface (GUI). The sample application below shows how to add custom options to the BlackBerry Options application by using the OptionsManager class and the OptionsProvider interface.

Note: This sample application uses an alternate entry point that specifies “auto-start” as its parameter. For more information on alternate entry points, see this article .

OptionsSample.java

package com.rim.samples.options;

import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.system.*;
import net.rim.blackberry.api.options.*;

public class OptionsSample extends UiApplication
{
    public static void main(String[] args)
    {
        //This sample makes use of alternate entry points.
        //An alternate entry point will need to be configured
        //in your workspace to use this sample.

        if (args.length > 0 && args[0].equals("auto-start"))
        {
            //Enter the auto start portion of the application.
            //Register an options provider and exit.
            OptionsSampleOptionsProvider provider =
              new OptionsSampleOptionsProvider();
            OptionsManager.registerOptionsProvider(provider);
        }
        else
        {
            //Enter the GUI portion of the applicaiton.
            //Create a new instance of the application
            //and start the application on the event thread
            OptionsSample theApp = new OptionsSample();
            theApp.enterEventDispatcher();
        }
    }

    public OptionsSample()
    {
        MainScreen theScreen = new MainScreen();
        theScreen.setTitle(new LabelField("Options Sample"));
        OptionsSampleProperties props = OptionsSampleProperties.fetch();
        RichTextField greeting = new RichTextField();

        if (props.isGreetingEmphasized())
        {
            // An emphatic greeting is in all capitals and followed by
            // exclamation marks and is displayed in bold.
            String greetingText = props.getGreeting().toUpperCase()
              + "!!!!";
            Font emphatic = Font.getDefault().derive(Font.BOLD);
            int[] offsets = {0, greetingText.length()};
            byte[] attributes = {0};
            Font[] fonts = {emphatic};
            greeting.setText(greetingText, offsets, attributes, fonts);
        }
        else
        {
            greeting.setText(props.getGreeting());
        }

        theScreen.add(greeting);
        pushScreen(theScreen);
    }
}

OptionsSampleOptionsProvider.java

package com.rim.samples.options;

import net.rim.blackberry.api.options.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.ui.component.*;

class OptionsSampleOptionsProvider implements OptionsProvider
{
    private EditField greetingEdit;
    private ObjectChoiceField styleChoice;
    private OptionsSampleProperties optionProperties;

    public OptionsSampleOptionsProvider()
    {
    }

    public String getTitle()
    {
        return "Options Sample";
    }

    public void populateMainScreen(MainScreen mainScreen)
    {
        //Read in the properties from the persistent store.
        optionProperties = OptionsSampleProperties.fetch();

        //Get the current values from optionProperties and create
        //the controls to represent them.
        greetingEdit = new EditField
          ("Greeting: ", optionProperties.getGreeting(),
            BasicEditField.DEFAULT_MAXCHARS, BasicEditField.NO_NEWLINE);
        mainScreen.add(greetingEdit);

        Object[] choices = {"Normal", "Emphatic!!"};
        int selection = optionProperties.isGreetingEmphasized() ? 1 : 0;
        styleChoice = new ObjectChoiceField("Style: ", choices, selection);
        mainScreen.add(styleChoice);
    }

    public void save()
    {
        //Get the new values from the UI controls
        //and set them in optionProperties.
        optionProperties.setGreeting(greetingEdit.getText());
        optionProperties.setGreetingEmphasized
          (styleChoice.getSelectedIndex() != 0);

        //Write our changes back to the persistent store.
        optionProperties.save();

        //Null out our member variables so that their objects can be garbage
        //collected. Note that this instance continues to be held by the
        //options manager even after the user exits the options app,
        //and will be re-used next time.

        greetingEdit = null;
        styleChoice = null;
        optionProperties = null;
    }
}

OptionsSampleProperties.java

package com.rim.samples.options;

import net.rim.device.api.system.*;
import net.rim.device.api.util.*;

//The configuration properties of the OptionsSample application. One instance holding
//the effective values resides in the persistent store.
class OptionsSampleProperties implements Persistable
{
    private String greeting;
    private boolean greetingEmphasized;

    //Hash of com.rim.training.options.OptionsSampleProperties
    private static final long PERSISTENCE_ID = 0x7eeffcc691f4418dL;

    //Persistent object wrapping the effective properties instance
    private static PersistentObject store;

    //Ensure that an effective properties set exists on startup.
    static {
        store = PersistentStore.getPersistentObject(PERSISTENCE_ID);
        synchronized (store) {
            if (store.getContents() == null) {
                store.setContents(new OptionsSampleProperties());
                store.commit();
            }
        }
    }

    // Constructs a properties set with default values.
    private OptionsSampleProperties()
    {
        greeting = "Hello there";
        greetingEmphasized = false;
    }

    //Retrieves a copy of the effective properties set from storage.
    public static OptionsSampleProperties fetch()
    {
        synchronized (store)
        {
            OptionsSampleProperties savedProps =
              (OptionsSampleProperties) store.getContents();
            return new OptionsSampleProperties(savedProps);
        }
    }

    //Causes the values within this instance to become the effective
    //properties for the application by saving this instance to the store.
    public void save()
    {
        synchronized (store)
        {
            store.setContents(this);
            store.commit();
        }
    }

    //The greeting is the text that is displayed within the
    //OptionsSample application.
    public String getGreeting()
    {
        return greeting;
    }

    public void setGreeting(String greetingLocal)
    {
        greeting = greetingLocal;
    }

    //If emphasized, the greeting is displayed in more resouding manner.
    public boolean isGreetingEmphasized()
    {
        return greetingEmphasized;
    }

    public void setGreetingEmphasized(boolean greetingEmphasizedLocal)
    {
        greetingEmphasized = greetingEmphasizedLocal;
    }

    //Cannonical copy constructor.
    private OptionsSampleProperties(OptionsSampleProperties other)
    {
        greeting = other.greeting;
        greetingEmphasized = other.greetingEmphasized;
    }
}

[1] http://supportforums.blackberry.com/t5/Java-Development/Add-application-options-to-the-BlackBerry-Options/ta-p/442859


SVG for BlackBerry Theme Builder

What is SVG?

SVG stands for scalable vector graphics. In layman’s terms, SVG a type of graphic that will look smooth, crisp, and clean no matter how big or small it is. It is also a graphic type that can be scripted with XML-like coding, so it can be animated and/or interactive.

Even if you’ve never heard of SVGs, you’ve probably seen some of its cousins in the vector graphics field, specifically EPSs (Encapsulated PostScript), PDFs (Portable Document Format), WMFs (Windows Metafile), and SWFs (Shockwave Flash).

SVG is different from most of its cousins in that, because it is XML-based in its coding, it is possible to create and edit an SVG file with just a simple text editing program. There are plenty of graphics programs out there, though, that can be used to generate SVG files, including one provided specifically for use with BlackBerry devices.

Introduction

If you’ve created themes for BlackBerry® devices for any reasonable length of time, you’ve probably noticed that there are specific areas in the BlackBerry Theme Builder where you can input SVG files. Everyone says you can make a theme do all sorts of wild and wonderful things with SVG. However, if you’ve never worked with or even seen them before, the first question you have is “What is SVG?”.

What SVG can do for themes

When working in the BlackBerry Theme Builder 5.0, there are two sections where SVGs can be used. These are the Home screen and the Lock screen. Using SVG can make your themes more dynamic in a few ways:

  • Animation: Only with SVGs can you add any sort of animation to your Home and Lock screens.
  • More customized Home screen buttons: In BlackBerry Theme Builder, you are restricted by various image sizes regarding buttons and icons. Using SVG to create buttons removes those limitations. With SVG, icons can be resized, and buttons can be given custom animations when highlighted and/or selected.
  • Make screens more interactive: With SVG files, it’s possible to make the screens more dynamic. Drawers can be created to hide Home screen buttons. Animations can be made to start or stop on unique triggers, such as the arrival of a new text message, or the rotation of a BlackBerry® Storm™ smartphone from portrait view to landscape view.

How to make SVG files

There are two main ways to go about making an SVG file for BlackBerry device themes. The first way is to use a program called the BlackBerry Composer. This free program is provided by RIM, and it’s usually installed on your machine when you install the BlackBerry Theme Builder. The second way is by writing the SVG code yourself with the use of a text editor program. There are pros and cons to each of these techniques, and different resources available for each:

BlackBerry Composer

Pros:

  • WYSIWYG program geared towards those already comfortable with various graphic design programs
  • No need to learn SVG code beforehand
  • Free to download
  • Works relatively well for simple, straightforward animation and interactivity

Cons:

  • May export bloated code for SVG files with complex animations and/or interactivity
  • SVG components often renamed to random, irregular number strings that make it difficult for those with coding experience to decipher

Resources/Tutorials

HAND-CODING SVG

Pros:

  • Artist has greater control over organization of SVG code, including the naming of elements
  • No need for any special program to write code. Just a text editor, such as Notepad, is fine.
  • Can create special effects that cannot be re-created with the BlackBerry Composer
  • Hand-coded SVG files can have a smaller file size than BlackBerry Composer exported SVG files that do the same animation/special effects

Cons:

  • Has a steep learning curve for those with no coding experience
  • Testing for appearance and fuctionality involves repeatedly importing and updating the SVG file in the appropriate BlackBerry Smartphone Simulator or on a BlackBerry device
  • Not easy to find specific tutorials for hand-coding BlackBerry device SVG files

Resources/Tutorials

[1] http://supportforums.blackberry.com/t5/BlackBerry-Themes-Animated/SVG-for-BlackBerry-Theme-Builder-What-is-SVG/ta-p/491934


Youtube Viewer using BlackBerry 6 Communication API

The Communication and Parsing API introduced in the BlackBerry® 6 OS probably doesn’t get as much attention as it really deserves. It has one of those names that could mean just about anything, but when I created a sample with it, I found it made many tasks simple – and I barely scratched the surface of what was possible.

You’ll find the API specification in the net.rim.device.api.io.messaging package, where you will see the significant set of interfaces and classes that provide all this functionality. The API breaks up communication into a few parts: The Destination is the target for a connection, usually a URL, and you can send and receive Message objects through it. Destinations can block the execution thread, or not, and you can send messages without handling the response with aFireAndForgetDestination. A Destination can also be connected with a MessageProcessor, which will parse the messages for you. Several processors are included in the API for common message formats like XML, JSON, RSS, and so on. Processors can be chained to support even more functionality. Finally, Messages can be retrieved as MessageFutures, and Destinations can be used to receive pushes and other incoming connections.

Behind the scenes is even more great stuff, like message queuing, prioritization, and even support for inter-process communication. Before we get too buried in the details, I should point out that the BlackBerry 6 SDK includes a full sample application that shows how to do all of this. The sample I want to share with you today is an example using this new API to streamline development of a YouTube® client. With the proliferation of APIs like YouTube’s Data API, which offer ATOM and JSON-C (for more bandwidth saving) interfaces, many opportunities become quite accessible.

Full sample code is included so you can check it out, but let’s look at some of the Communication API in action. The destination is the YouTube Data server with several basic query parameters:

BlockingSenderDestination destination = DestinationFactory.createBlockingSenderDestination(_context,
URI.create(buildQueryURL(query, index, max)), _processor);

Where my URL is built from a base, and I’m just appending the search query string and variables to return a particular section of the feed, I end up with a URL like so:

"http://gdata.youtube.com/feeds/mobile/videos?v=2&fields=entry[link/@rel=%27http://gdata.youtube.com/schemas/2007%23mobile%27]&format=6&q=blackberry.com/developers&start-index=1&max-results=10";

The query I’ve used restricts the response somewhat to a mobile-friendly version, including filtering out any videos that don’t have a mobile video link – a useful feature for mobile clients that could be expanded on in this sample. I’ve also included a MessageProcessor to handle the output; in this case, it’s anXMLHashtableMessageProcessor, which nicely converts the ATOM response into a simple Hashtable, so I can do things like pulling all the titles out into a String array:

String[] titles = contents.getStringArray("/feed/entry/title");

Once I’ve grabbed all the details I care about, I can send the results back to the screen for displaying. However, the feed response contains a URL for the thumbnails, so I need to download that as well. This is a neat opportunity to use non-blocking destinations and update the display when the thumbnails arrive:

NonBlockingSenderDestination destination = DestinationFactory.createNonBlockingSenderDestination(_context,
					URI.create(url), this);
destination.send();

Those requests are fired off through the API and I’ve got a MessageListener waiting for them, which will take the data and inform the screen it can update the image from the placeholder:

public void onMessage(Destination destination, Message message) {
if (message instanceof ByteMessage) {
		byte[] results = ((ByteMessage) message).getBytePayload();
		EncodedImage image = EncodedImage.createEncodedImage(results, 0, -1);
		... //send the image to the Screen
		destination.destroy();
	}
}

Give the sample a look and check out the API in more depth to see how you can put it to work for you. We’ll follow this up later with a more detailed sample showcasing the advanced features of both YouTube’s Data API and the BlackBerry® Communication API.

Youtube Client-downloadpdf-renameto.zip

[1] http://supportforums.blackberry.com/t5/Java-Development/How-to-Create-a-YouTube-viewer-with-the-BlackBerry-6/ta-p/744251


  • Copyright © 1996-2010 vaks.in. All rights reserved.
    iDream theme by Templates Next | Powered by WordPress