Monday, April 27, 2009

General Coding Tips

Avoid the Object.getClass() Method

Avoid using the Object.getClass() method, because it is not efficient and it produces garbage (the Class object) that is never collected. Also avoid using the example.class literal. Behind the scenes, this generates Class.forName(“Example”).

Writing Efficient Loops

You should always factor loop invariant code out of a loop, as in the following example:

    for(int i = 0; i < >
...

}

This code results in vector.size() getting called each time through the loop, which is inefficient. If your container is likely to have more than one element, it is much faster to assign the size to a local variable. In addition, this example using pre-increment (++i) results in smaller code than post-increment (i++). The optimized code appears below:

     int size = vector.size();
for(int i = 0; i < style=""> ...
}

Alternatively, if the order in which you iterate over items is not important, you can iterate backward. Iterating backward avoids the extra local on the stack, and the comparison is also faster, as the following example illustrates:

for(int i = vector.size() - 1; i >= 0; --i) {

...

}



Optimizing Subexpressions

If you ever use the same expression twice, do not rely on the compiler to optimize it for you. Use a local variable, as in the following example:

one(i + 1); two(i + 1); // Avoid
int tmp = i + 1; 
one(tmp); 
two(tmp); // Prefer

Avoid java.util.Enumeration
Avoid using java.util.Enumeration unless you are using it to hide data (in other words, returning an Enumeration of data rather than the data itself). The following example shows a typical use of an Enumeration:

for (Enumeration e = v.elements(); e.hasMoreElements();) {
   o = e.nextElement();
   ...
}

Asking a vector or hash table for an Enumeration object creates unnecessary garbage and is slow. Instead, you can iterate over the elements yourself, as in this example:

for(int i = v.size() - 1; i >=0; --i) {
   o = v.elementAt(i);
   ...
}

If the vector might be modified by another thread, you must synchronize the iteration:

synchronized(v) {
   for(int i = v.size() - 1; i >=0; --i) {
      o = v.elementAt(i);
      ...
   }
}

In Java 2 Platform, Standard Edition (J2SE), you would use an Iterator for this, but Iterators are not available in Java 2 Platform, Micro Edition (J2ME).

Returning null
If you are writing a public method that returns an object, it should never return null unless the following occurs:

  • a null is expected during normal program operation.
  • the javadoc @return parameter states that null is a possible return value.

If a null is not normally expected, then the method should throw an appropriate exception, which forces the caller to deal with the problem explicitly. The caller is not expected to check for a null return value, unless the documentation specifies otherwise.

Passing null into Methods
Do not pass null parameters into an API method unless the API Reference documentation explicitly states that the method supports them.

Passing null into a Constructor
To avoid ambiguity when passing a null into a constructor, you should use this form:

new someObject ((Object)null);

A class can have two or more constructors, such as SomeObject(String) and SomeObject(Object), where passing in a null does not identify which constructor to use. As a result, the compiler reports an error. Not all supported constructors necessarily appear in the API Reference documentation, because some constructors are for internal use only. By casting the null to the appropriate object, you indicate precisely which constructor the compiler should use. This practice also ensures forward compatibility if later releases of the API add new constructors.

Optimizing Division Operations
Division operations are slow on the BlackBerry Wireless Handheld because its processor does not have a hardware divide instruction. When you write code that divides a positive number by two, you should use “shift right by one” instead. The following example illustrates this:

midpoint = width / 2; //avoid this
int = width >> 1; //prefer this

This does not work for negative values. Only use “shift right” (>>) when you know you are dealing with a positive value. It does not work for negative values.

Managing Garbage Collection
Avoid calling System.gc() to perform garbage collection. On a full handheld, this could take two seconds. Let the virtual machine (VM) collect garbage automatically.


Casting Using instanceof
It is more efficient to use instanceof instead of classCastException to evaluate whether a cast succeeds. Here is an example of using a try/catch block to catch the classCastException:

try {
   (String)x.whatever();
} catch(ClassCastException e) {
   // something else
}

Alternatively, you can use instanceof operator:

if(x instanceof String) {
   (String)x.whatever();
} else {
   // something else
}

Using instanceof is faster. The only time you should use the try/catch block is when the failure of the cast is an exceptional circumstance. The BlackBerry Java Development Environment (JDE) compiler and the VM are optimized to perform only one class check in the first block of code. This is true of any code in which the cast is run immediately following a branch determined by an instanceof check. Always perform the cast immediately after the branch so that the optimization can be performed.

Using Longs for Unique Identifiers
You should use longs rather than strings for unique constants, such as globally unique identifiers (GUIDs), hash table keys, and state/context identifiers. So that unique identifiers remain unique across all third-party application developers, you should use randomly generated keys based on a hash of some string. In the input string, you should include enough information to make it unique.

Memory Management tip

Dealing with memory on the iPhone is one of the most difficult
challenges that you will face as a new iPhone developer. Today,
I am going to show you a very simple tip that will help you
debug the memory problems that you are like to face.

One thing that you have to worry about with memory management is
the "retain count" of an object. The retain count is how the
system keeps track of the memory used by an object. If an
object's retain count is zero and your attempt to access it
your app will crash; if you do not make sure the retain
count of your object is 0 when the object goes out of focus you
will have a memory leak.

Clearly, it is important to be able to find out what the current
retain count of an object is. Here is how you can do this:

NSLog([NSString stringWithFormat:@"Retain Count:%i", [someObject retainCount]]);
This writes out the current retain count to the log. The
important function is [someObject retainCount].

Friday, April 24, 2009

Strings in iPhone

The iPhone uses a special class called "NSString" to handle strings. Here is an example of a common use of NSString.
NSString *myString = @"This is my string";
You can use an NSString object in the alert that you learned about last week. Here is how you would use the NSString object "myString" in an alert:
NSString *myString = @"This is my string";

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"UIAlertView"
message:myString
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
Notice that the "message" argument of the alert you created above uses the NSString object as an argument. Another thing you will be doing with strings is combining strings to make new ones.
For instance, if I had two strings - a first and a last name - and I wanted to create a new string for a full name I could do something like this:
NSString *firstName = @"Matt";
NSString *lastName = @"Campbell";
NSString *fullName = [NSString stringWithFormat:@"My name is %@ %@",
firstName, lastName];

If you were to put fullName into an alert it would say "My name is Matt Campbell". How the stringWithFormat function works is that you give it a string with special symbols in it. The function will replace the symbols with the strings in give it as the next arguments to the function.
Note that when you are using the alert object you need to follow the "alloc, use, release" pattern while the NSString only requires you to use the function after which you may safely forget about it.
This has something to do with the memory management features of the iPhone. Essentially, when you use an object's "alloc" you need to "release" at some point in the future. NSString does not use an alloc in this instance so it does not need to be released while UIAlert does. More details about memory management will be discussed in this mailing list in the future.

Alert box in iPhone

An alert box is a quick way to communicate to your users. Alert boxes look like a rounded square with a message and a button on it. You may put this code into your project to get an alert box:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"UIAlertView"
message:@"Hi There!" delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles: nil];

[alert show];
[alert release];

As you can see from the code above, square brackets are the order of the day in Objective-C, the iPhone programming language. For now, note that text that comes right after the word "message:". This is where you control what the alert box presents to the user.
Finally, notice the overall pattern of using objects in Objective-C: alloc, "do stuff", release. This is something that you will be using often in your iPhone programming.

Looping in Objective-C

Looping in Objective-C

Loops are the gears of programming: it is what makes the code take action.  The two loops I use most often is the for loop (to do a predefined number of steps) and what is usually called a foreach loop (to move though a list of objects).

//This loop simply repeats an action
//a set amount of times:
for (int i=0; i<=3; i++)
    NSLog([NSString stringWithFormat:@"i=%i", i]);
  
//Create an array of strings for the next example:
NSMutableArray *bunchOfThings = [[NSMutableArray alloc] init];
[bunchOfThings addObject:@"Zero"];
[bunchOfThings addObject:@"One"];
[bunchOfThings addObject:@"Two"];
[bunchOfThings addObject:@"Three"];
  
//This is sometimes called a "for each" loop
//Using this list will repeat actions for each
//object in a list.
//Hint: you can use this for any type of list of
//objects so if you have list of custom defined
//objects this is an easy way to work with them all
//at one time.
for(NSString *s in bunchOfThings)
    NSLog([NSString stringWithFormat:@"s=%@", s]);
  
//The array must be released since it was alloc/init earlier.
[bunchOfThings release];


That is it!

Wednesday, December 24, 2008

Pushing Web Content to BlackBerry Wireless Devices

            
            Deploying and enabling a web-based application on a BlackBerry wireless device allows for reduced development time by not creating a BlackBerry application. A Browser Push differs from a BlackBerry client push application as there is no requirement to develop a client to reside on the device. There are four types of Browser Push that can be sent to the BlackBerry wireless device.
  1. Browser Channel Push
  2. Browser Channel Delete Push
  3. Browser Content Cache Push
  4. Browser Message Push

Browser Channel Push


A Browser Channel Push sends a web page and two icons to the BlackBerry wireless device. The web page is stored in the cache of the BlackBerry Browser, and an icon is shown on the home screen of the device. An unread icon can be specified so that when a new Browser Channel Push arrives to the device, it will display the unread icon. After the user has opened and visited the page, the read icon is shown. This provides the user with a visual indication as to when a page has been updated. It's useful for a news service so that users are aware of when new data has arrived. The icons can even change with every push allowing an application to continually push different icons. This would be useful for a weather application updating the current weather conditions.

Browser Channel Delete Push


A Browser Channel Delete works in a similar, but opposite fashion of the Browser Channel Push. It will remove an icon on the BlackBerry Home screen that has been sent via a Browser Channel Push. Icons initiating from a Browser Channel Push can also be removed from the device itself.

Browser Content Cache Push


Browser Content Cache Push is the most discreet type of Browser Push. A Browser Content Push will push a web page to the BlackBerry wireless device and store it in the BlackBerry Browser's cache. The user is not informed in any way when this push takes place, or when the page has been updated.

Browser Message Push


Instead of creating an icon on the home screen of the BlackBerry wireless device, a Browser Message Push will arrive in the Inbox on the device. When the user opens the message, the default browser on the device is launched then opens the page. Unlike the Browser Channel Push or Browser Content Push, the web page is stored as a browser message instead of in the BlackBerry Browser's cache. This means that the page will be available until the message is deleted. It will not be removed from the BlackBerry Browser cache when other events (browsing, cache clear) take place. The message created from a Browser Message Push is not sent to, and will not appear in, a user's Inbox on their desktop. It is sent directly to the device.

How to push


Push applications can be created using any development language that is able to initiate a network connection and perform an HTTP post. A post to the BlackBerry MDS Server handles the delivery of the push to a BlackBerry wireless device. The post is made up of the standard html request headers, a few unique Browser Push headers and the web page being pushed (it is not required to send the web page when performing a Browser Channel Delete Push). The following additional http request headers are required for a Browser Push to take place.

 

Required

X-RIM-Push-Title
X-RIM-Push-Type

Optional

X-RIM-Push-Channel-ID
X-RIM-Push-UnRead-Icon-URL
X-RIM-Push-Read-Icon-URL
 
"The X-Rim-Push-Title" header holds the title that will appear on the home screen of the device for a Browser Channel Push, or in the subject of the message of a Browser Message Push. The "X-RIM-Push-Type" header holds the value that represents the type of push being sent. Possible values are:
  • Browser-Channel
  • Browser-Message
  • Browser-Content
  • Browser-Channel-Delete
The "X- RIM-Push-Channel-ID" header contains the URL of the page to be pushed to the device. This is not required when performing a Browser Message or Browser Content push. The "X-RIM-Push-UnRead-Icon-URL" and "X-RIM-Push-Read-Icon-URL" are optional headers that specify the URL of the icons to be used for a Browser Channel Push. If these are not specified then the default Browser Channel Push icons are used. These two headers are not required for Browser Message, Browser Content or Browser Channel Delete Push and may be omitted.
The page that is to be pushed is submitted once the headers are sent. It is recommended that this page resides on a web server, although it is not required. If it is not located on a web server, a user would be unable to refresh the page. If the page has been removed from the BlackBerry Browser cache (if a Browser Channel or Browser Content Push was used) they would be unable to view it. It is not required to send the actual page when performing a Browser Channel Delete.

Sample Java Push Application

           A sample Java based push application is included and documented with the BlackBerry JDE. The BlackBerry JDE is available in the JDE installation path: “$JDE_HOME$\samples\com\rim\samples\server\httppushdemo”

Sample Php Push Application

A sample php push application can be downloaded from this URL http://na.blackberry.com/eng/devjournals/resources/journals/jan_2005/phpPush.zip
 

Signing Your BlackBerry Application Before Deployment

Overview

  • Why the need to sign your BlackBerry code
  • Registering and obtaining signature keys
  • Signing your application

Why You Need to Sign Your Code

The concept of “controlled” API's has existed since BlackBerry 3.6 as a way for Research In Motion (RIM) to track the use of some API's for security and export control reasons. In practical terms, this means that in order to run an application on a handheld, you need to register and sign the application. Signing of applications is not required to run applications using the BlackBerry device simulator.

The BlackBerry API is divided into five groups. The first group includes all standard Java API's from MIDP and CLDC and some BlackBerry-specific API's. This group is open for all developers, and applications that use only these open API's require no signatures. The remaining four groups are all controlled API's: RIM Runtime API's, some BlackBerry API's, RIM Cryptography and Certicom Cryptography.

Registering and Obtaining Signature Keys

The registration process serves to verify the developer's identity. It involves downloading and filling out a registration form that you need to fax to RIM. There’s also a one-time processing fee associated with it. RIM will send you a set of signature keys after the registration form and fee are received.

Signing Your Application

Once you receive the signature keys from RIM, you need to install them on your development environment. The detailed instructions on how to do this can be found in the BlackBerry Java Developer Guide, Volume 2 - Advanced Topics. I recommend that you study this procedure, since installing the keys incorrectly will cause the signing process to fail.
Signing the application is very easy once the keys are installed. You need to manually start the Signature Tool from the Build menu in the JDE:

 
 


When you press the Request button, the Signature Tool submits a hash of the application to RIM's signing authority. The signing authority automatically returns the required signature, that is automatically appended to the application. The application can be loaded onto a device after this step.


Note that RIM does not receive a copy of your application, only a hash of the file(s). This allows them to determine the author of the application by matching the hash of the application against records of the hash kept by the signing authorities.

Where to Find More Information

You can find more information on this topic in the BlackBerry Java Developer Guide, Volume 2 - Advanced Topics.

Monday, December 22, 2008

Showing a manufacturer disclaimer during application installation

Overview

This code snippet demonstrates how to display a manufacturer disclaimer when an application is being installed. This behavior is required at least for VoIP applications that are meant to be sent to Symbian for signing.

This snippet can be self-signed.

data\disclaimer.txt

This is an example of the disclaimer text by Symbian for VoIP applications:

You are about to use , which is
developed and owned by . The
manufacturer of this device shall have no liability for
any aspect of the application whatsoever, including its
performance, call routing, intellectual property rights
or support.

PKG file

To display the disclaimer to the user, add the following line to the PKG file of your application:

"..\data\disclaimer.txt" - "", FILETEXT, TEXTEXIT

The FILETEXT install option indicates that a file is to be displayed to the user during the installation procedure. The file itself is not installed on the target device (the target location is empty).

The TEXTEXIT install option displays a dialog box with "positive" and "negative" buttons, such as Ok and Cancel. If the dialog returns true (the user pressed Ok), the software installer continues with the installation. If the dialog returns false (the user pressed Cancel), the software installer is exited and any files that have already been installed are removed.

Display phonenumber during incoming call

Display phonenumber during incoming call

If your application runs in background and if u want to display phonenumber during incoming call just implement this code in abstract method.
PhoneCall callInfo = Phone.getActiveCall();

if ( callInfo != null )
{
Telephone = callInfo.getDisplayPhoneNumber();
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
Status.show("incoming from: "+Telephone);
}
});

Running Existing MIDlets on the BlackBerry

To run a standard MIDlet on a Java-enabled BlackBerry device, you first need to convert the .jad and .jar files to the .cod format, using the rapc command-line tool that comes with RIM's JDE. You'll find rapc in the bin directory of your JDE installation. This command converts a MIDlet named "LoginMIDlet"

rapc import="c:\BlackBerryJDE3.6\lib\net_rim_api.jar" codename=LoginMIDlet -midlet jad=LoginMIDlet.jad LoginMIDlet.jar
You can load the resulting LoginMIDlet.cod file into your BlackBerry device from your desktop computer over a USB cable. Use the javaloader command, which can also be found in the bin directory of your JDE installation. I used this command to load LoginMIDlet.cod into my BlackBerry 7510:

javaloader -usb load LoginMIDlet.cod

Once the application is loaded into the BlackBerry, you can run it just as if it were a native application. You can use javaloader to delete applications from the BlackBerry as well as to load them. This command will remove LoginMIDlet.cod from the BlackBerry:
javaloader -usb erase -f LoginMIDlet.cod