Showing posts with label BB Class. Show all posts
Showing posts with label BB Class. Show all posts

Friday, March 27, 2009

How to : Create a custom layout manager for a screen

3 comments

How To You can create your own custom layout manager by extending the net.rim.device.api.ui.Manager class and customizing it to fit your needs. Custom layout managers enable you to customize the placement of fields on the screen and customize navigation within these fields. To do this, you need to implement at least the following three methods:

  1. public int getPreferredWidth()

This method returns the manager's preferred width.

  1. public int getPreferredHeight()

This method returns the manager's preferred height.

  1. public void sublayout(int height, int width)

This method is invoked by the manager's layout() method and instructs each child field how and where to be laid out.

This can be accomplished by calling Manager.setPositionChild(Field field, int x, int y) and LayoutChild(Field field, int width, int height) for each field contained in the manager.

Here is an example of how a screen can associate itself with a custom layout manager:

class LayoutManager extends Manager {
   public LayoutManager() {
       //construct a manager with vertical scrolling
       super(Manager.VERTICAL_SCROLL);
   }
   //overwrite the nextFocus method for custom navigation
   protected int nextFocus(int direction, boolean alt) {
       //retrieve the index of the current field that is selected
       int index= this.getFieldWithFocusIndex();
       if(alt) {
           if(direction 0){...}
               else{...}
       }
      // if we did not handle it, let the manager's parent class
      if (index == this.getFieldWithFocusIndex())
          return super.nextFocus(direction, alt);
      else
          return index;
   }
   protected void sublayout(int width, int height) {
       Field field;
       //get total number of fields within this manager
       int numberOfFields = getFieldCount();
       int x = 0;
       int y = 0;
       for (int i = 0;i < numberOfFields;i++) {
           field = getField(i); //get the field
           setPositionChild(field,x,y); //set the position for the field
           layoutChild(field, width, height); //lay out the field
           y += ...;
           ...
       }
       setExtent(width, height);
   }
   public int getPreferredWidth() {
       return 160;
   }
   public int getPreferredHeight() {
       int height= 0;
       int numberOfFields= getFieldCount();
       for (int i= 0; i < numberOfFields; i++) {
           height+= getField(i).getPreferredHeight();
           return height;
       }
   }

the main class :

   ...
   RichTextField myField = new RichTextField("Hello");
   RichTextField myOtherField = new RichTextField("World");
   LayoutManager myManager = new LayoutManager();
   MainScreen myScreen = new MainScreen();
   myScreen.add(myManager);
   myManager.add(myField);
   myManager.add(myOtherField);
   ...

Friday, March 13, 2009

How To : Detect if the BlackBerry smartphone is holstered or flipped

0 comments

How To The Sensor API allows third-party applications to query the existence and states of BlackBerry smartphone sensors (for example, holster or flip). This API also supports registration to a SensorListener that can receive updates for specified sensor(s).

Note: The relevant classes added to BlackBerry® Java® Development Environment (BlackBerry JDE) 4.6 are as follows:

  • net.rim.device.api.system.Sensor
  • net.rim.device.api.system.SensorListener

The following code snippet shows how to receive sensor updates for both flip and holster events using the SensorListener:

public class SensorDemo extends Application implements SensorListener {
…
public SensorDemo() {
Sensor.addListener(this,this,Sensor.HOLSTER | Sensor.FLIP);
System.exit(0);
}
public void onSensorUpdate(int sensorId, int update)
{
switch(sensorId)
{
case Sensor.HOLSTER:
System.out.println("Received an Holster update!");
switch(update){
case Sensor.STATE_IN_HOLSTER:
System.out.println("Device Holstered!");
break;
case Sensor.STATE_OUT_OF_HOLSTER:
System.out.println("Device out of Holster!");
break;
default:
System.out.println("Unknown Holster update");
}
break;
case Sensor.FLIP:
System.out.println("Received a Flip update!");
switch(update){
case Sensor.STATE_FLIP_OPEN:
System.out.println("Device Flip opened!");
break;
case Sensor.STATE_FLIP_CLOSED:
System.out.println("Device Flip closed!");
break;
default:
System.out.println("Unknown Flip update");
}
break;
default;
}
}
public static void main(String[] args)
{
new SensorDemo().enterEventDispatcher();
}

Wednesday, March 4, 2009

Code : Access and Obtain Service Books

0 comments

The BlackBerry JDE 4.0 has a package, net.rim.device.api.servicebook, that allows the retrieval of service book information on a BlackBerry device.

The example below uses both the ServiceBook and ServiceRecord classes to obtain the APN of the WAP Browser service book:

import net.rim.device.api.system.*;
import net.rim.device.api.servicebook.*;
public class ServiceBookExample extends Application {
ServiceRecord[] _sRecordsArray; //Creates a ServiceRecord array.
ServiceBook _servicebook; //Creates a ServiceBook variable.
String cidValue, sbName, sbAPN;
public static void main(String[] args)
{
// Create a new instance of the application and
// start the event thread.
ServiceBookExample app = new ServiceBookExample();
app.enterEventDispatcher();
}
public ServiceBookExample() {
// Returns a reference to the service book from the factory.
_servicebook = ServiceBook.getSB();
// Returns an array of all registered service records.
_sRecordsArray = _servicebook.getRecords();
// Loops through the service record array
// and obtains specific information relating
// to each item and prints it to the debugging output.
for(int i = 0; i < _sRecordsArray.length; i++) {
// Obtains the Service Book CID
cidValue = _sRecordsArray[i].getCid();
// Obtains the Name of the Service Book
sbName = _sRecordsArray[i].getName();
if(cidValue.equals("BrowserConfig")
&& sbName.startsWith("WAP Browser")) {
// Obtains the Service Book's APN
// (Associated Access Point Name)
String sbAPN = _sRecordsArray[i].getAPN();
}
}
}
}

For a complete listing of available methods, please see the API reference included within the BlackBerry JDE 4.0. Additional information can be found in Chapter 10 of the BlackBerry Application Developer Guide Volume 2.

Tuesday, March 3, 2009

Code : BlockDecryptor class

0 comments

I need to encrypt the string using AES encryption and CBC mode.

The way given in one of the post 'How to - Use Basic Encryption'. This code works fine.

But when I am encrypting the string using blockdescryptor and CBCBlockDescryptor the string is not encrypted fully.

Now the question was “How can I encrypt the string properly?”.

Following is the code:

private static byte[] encrypt(byte[] keyData, byte[] data) throws CryptoException, IOException

{

// Create the AES key to use for encrypting the data.

// This will create an AES key using as much of the keyData
// as possible.
AESKey key = new AESKey(keyData, 0, 128);

// Now, we want to encrypt the data.
// First, create the encryptor engine that we use for the actual
// encrypting of the data.
AESEncryptorEngine engine = new AESEncryptorEngine(key);

String strInitVector = "1234567890123456";
byte[] initVector = strInitVector.getBytes();
// Create a new initialization vector using the 8 bytes in initVector
InitializationVector iv = new InitializationVector(initVector);
// Create a BlockEncryptor to hide the engine details away.
ByteArrayOutputStream output = new ByteArrayOutputStream();
BlockEncryptor encryptor = new BlockEncryptor(new CBCEncryptorEngine(engine, iv) , output);
//BlockEncryptor encryptor = new BlockEncryptor(fengine , output);
encryptor.write(data, 0, data.length);
int nSize = output.size();
encryptor.flush();
output.close();
//encryptor.close(); // At this line application is throwing uncaught exception

// Now, the encrypted data is sitting in the ByteArrayOutputStream.
// We simply want to retrieve it.
return output.toByteArray();
}

The string given for encryption is "The quick brown fox jumped over the lazy dog".

Actual encrypted string from PHP for this string is of 42 characters. Where as my application is giving me the encrypted string of 32 characters. After decryption I am getting the plain text as "The quick brown fox jumped over ".

I have tried the same thing,appended '0' byte at the end of the string if the string length is less than block length.

And, It is working perfect.

How to - Use Basic Encryption

1 comments

Data sent between a BlackBerry device and the BlackBerry Enterprise Server™ is encrypted using Triple DES (Date Encryption Standard) or AES (Advanced Encrption Standard). This is performed automatically and does not require application implementation to use it.

There are cases where encrypting data can be required, such as secure communication with an external application using the BlackBerry Mobile Data Server. Communication between the BlackBerry and BlackBerry Mobile Data Server would be automatically encrypted but communication between the BlackBerry Mobile Data Server and an application server would not unless implemented in the BlackBerry application.

Note: The BlackBerry supports https, tls and ssl for secure communication beyond the BlackBerry Mobile Data Server.

The following is an example of how to utilize basic encryption using AES on the BlackBerry:

package com.rim.samples.crypto;
import java.io.*;
import net.rim.device.api.crypto.*;
import net.rim.device.api.util.*;
/**
* This sample code provides information on how to encrypt and
* decrypt data using the most common symmetric key algorithm
* in use today. That algorithm is the Advanced Encryption Standard (AES).
*/
public class BasicCryptoDeveloperLab
{
public static void main( String[] args )
{
try {
// Create the data that you want to encrypt.
String message = "Welcome to the RIM Crypto API.";
byte[] data = message.getBytes();
// Create the key we want to use for encryption and decryption.
// Note that the RandomSource class provides cryptographically random
// data which is suitable for use when creating keys. This is different
// than using the Random class.
byte[] keyData = RandomSource.getBytes( 256 );
// Encrypt the data using
byte[] ciphertext = encrypt( keyData, data );
// Decrypt the data.
byte[] plaintext = decrypt( keyData, ciphertext );
String message2 = new String( plaintext );
if( message.equals( message2 )) {
// The encryption/decryption operation worked as expected.
System.out.println( "Congratulations! You just encrypted and decrypted data." );
} else {
System.out.println( "Oops. The decrypted message should equal the original.
Check your code." );
}
} catch( CryptoException e ) {
System.out.println("An unexpected exception occurred.
Please verify your work or ask for help.");
} catch( IOException e ) {
System.out.println("An unexpected exception occurred.
Please verify your work or ask for help.");
}
}
private static byte[] encrypt( byte[] keyData, byte[] data )
throws CryptoException, IOException
{
// Create the AES key to use for encrypting the data.
// This will create an AES key using as much of the keyData
// as possible.
AESKey key = new AESKey( keyData );
// Now, we want to encrypt the data.
// First, create the encryptor engine that we use for the actual
// encrypting of the data.
AESEncryptorEngine engine = new AESEncryptorEngine( key );
// Since we cannot guarantee that the data will be of an equal block
// length we want to use a padding engine (PKCS5 in this case).
PKCS5FormatterEngine fengine = new PKCS5FormatterEngine( engine );
// Create a BlockEncryptor to hide the engine details away.
ByteArrayOutputStream output = new ByteArrayOutputStream();
BlockEncryptor encryptor = new BlockEncryptor( fengine, output );
// Now, all we need to do is write our data to the output stream.
// But before doing so, let's calculate a hash on the data as well.
// A digest provides a one way hash function to map a large amount
// of data to a unique 20 byte value (in the case of SHA1).
SHA1Digest digest = new SHA1Digest();
digest.update( data );
byte[] hash = digest.getDigest();
// Now, write out all of the data and the hash to ensure that the
// data was not modified in transit.
encryptor.write( data );
encryptor.write( hash );
encryptor.close();
output.close();
// Now, the encrypted data is sitting in the ByteArrayOutputStream.
// We simply want to retrieve it.
return output.toByteArray();
}
private static byte[] decrypt( byte[] keyData, byte[] ciphertext )
throws CryptoException, IOException
{
// First, create the AESKey again.
AESKey key = new AESKey( keyData );
// Now, create the decryptor engine.
AESDecryptorEngine engine = new AESDecryptorEngine( key );
// Since we cannot guarantee that the data will be of an equal block length
// we want to use a padding engine (PKCS5 in this case).
PKCS5UnformatterEngine uengine = new PKCS5UnformatterEngine( engine );
// Create the BlockDecryptor to hide the decryption details away.
ByteArrayInputStream input = new ByteArrayInputStream( ciphertext );
BlockDecryptor decryptor = new BlockDecryptor( uengine, input );
// Now, read in the data. Remember that the last 20 bytes represent
// the SHA1 hash of the decrypted data.
byte[] temp = new byte[ 100 ];
DataBuffer buffer = new DataBuffer();
for( ;; ) {
int bytesRead = decryptor.read( temp );
buffer.write( temp, 0, bytesRead );
if( bytesRead < 100 ) {
// We ran out of data.
break;
}
}
byte[] plaintextAndHash = buffer.getArray();
int plaintextLength = plaintextAndHash.length - SHA1Digest.DIGEST_LENGTH;
byte[] plaintext = new byte[ plaintextLength ];
byte[] hash = new byte[ SHA1Digest.DIGEST_LENGTH ];
System.arraycopy( plaintextAndHash, 0, plaintext, 0, plaintextLength );
System.arraycopy( plaintextAndHash, plaintextLength, hash, 0,
SHA1Digest.DIGEST_LENGTH );
// Now, hash the plaintext and compare against the hash
// that we found in the decrypted data.
SHA1Digest digest = new SHA1Digest();
digest.update( plaintext );
byte[] hash2 = digest.getDigest();
if( !Arrays.equals( hash, hash2 )) {
throw new RuntimeException();
}
return plaintext;
}
}

Tuesday, February 24, 2009

Code : Backup and restore data using SyncItem

0 comments

SyncItem (net.rim.device.api.synchronization.SyncItem) provides an easy method of backing up and restoring small amounts of data such as application configuration information. Allowing data to be backed up and restored ensures that the same information will be reloaded onto a user’s BlackBerry device when they upgrade the OS on their device. It can also allow configuration information to be transferred from one device to another.

It is not recommended to use this method to backup and restore a large amount of data. For more information on backing up and restoring a large amount of data see Chapter 6, Backing up and restoring persistent data in the BlackBerry Developer's Guide, Volume 2, Advanced Topics.

Procedure

In order for the SyncItem to register when the device starts, a separate project will have to be created that acts as an alternate entry point to your main application. This passes an argument to your application the first time that the device starts so that your application registers only once.

  1. In the BlackBerry JDE, create a project.
  2. Right-click the project and click Properties. The Properties window appears.
  3. Click the Application tab.
  4. From the Project type drop-down list, select Alternate CLDC Application Entry Point.
  5. From the Alternate entry point for drop-down list, select the main project that implements synchronization.
  6. In the Arguments passed to field, type init.
  7. Select the Auto-run on startup option.
  8. Select the System module option.
  9. Click OK.

/**
* SyncItemSample.java
*
* Allows a small list of names and ages that are stored in persistant
* store to be backed up and restored by the Desktop Manager.
*
*/
package com.samples.syncItemSample;
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.device.api.util.*;
import net.rim.device.api.synchronization.*;
import java.util.*;
public class SyncItemSample extends UiApplication
{
private String[] names
= {"Homer", "Marge", "Bart", "Lisa", "Maggie"};
private int ages[] = {36, 34, 10, 8, 3};
private static PersistentObject store;
private static UserList userList;
//This store is static so that all instances of this class
//use the same Persistent Store
static
{
//Unique identifier for the persistent store object.
//Long value = com.samples.syncItemSample.SyncItemSample
store = PersistentStore.getPersistentObject(0x677bb65afc4a6814L);
}
public static void main(String[] args)
{
boolean startup = false;
//Check parameters to see if the application was entered
//through the alternate application entry point.
for (int i=0; i<args.length; ++i)
{
if (args[i].startsWith("init"))
{
startup = true;
}
}
if (startup)
{
//Entered through the alternate application entry point.
//Enable application for synchronization on startup.
SerialSyncManager.getInstance().enableSynchronization
(new UserListSync());
} else
{
//Entered by selecting the application icon on the ribbon.
SyncItemSample app = new SyncItemSample();
app.enterEventDispatcher();
}
}
public SyncItemSample()
{
UserListScreen userListScreen;
//Check to see if the store exists on the BlackBerry.
synchronized (store)
{
if (store.getContents() == null)
{
//Store does not exist, create it with default values
userList = new UserList(names, ages);
store.setContents(userList);
store.commit();
}
else
{
//Store exists, retrieve data from store.
userList = (UserList)store.getContents();
names = userList.getNames();
ages = userList.getAges();
}
}
//Create and push the UserListScreen.
userListScreen = new UserListScreen(names, ages);
pushScreen(userListScreen);
}
/**
* UserListSync.java
*
* Handles the backup and restore of persistent data.
*
*/
package com.samples.syncItemSample;
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.device.api.util.*;
import net.rim.device.api.synchronization.*;
import java.util.*;
import net.rim.device.api.i18n.Locale;
public final class UserListSync extends SyncItem
{
private String[] permNames = new String[5];
private int permAges[] = new int[5];
private static UserList permUserList;
private static final int FIELDTAG_NAME = 1;
private static final int FIELDTAG_AGE = 2;
private static PersistentObject store;
//This store is static so that all instances of this class
//use the same Persistent Store
static
{
//Unique identifier for the persistent store object.
//Long value = com.samples.syncItemSample.SyncItemSample
store = PersistentStore.getPersistentObject(0x677bb65afc4a6814L);
}
public UserListSync()
{
}
//The name that will be used to reference this SyncItem.
//It is shown in the Desktop Manager under backup/restore advanced.
public String getSyncName()
{
return "Sync Item Sample";
}
//Localization is not supported in this example.
public String getSyncName(Locale locale)
{
return null;
}
//The version of this SyncItem.
public int getSyncVersion()
{
return 1;
}
//Formats the data to the specification required
//by the Desktop Manager.
public boolean getSyncData(DataBuffer db, int version)
{
int count;
boolean retVal = true;
String tempString;
synchronized (store)
{
//Check to see if the persistent store object
//exists on the BlackBerry.
if (store.getContents() != null)
{
//Store exists, retrieve data from store.
permUserList = (UserList)store.getContents();
permNames = permUserList.getNames();
permAges = permUserList.getAges();
}
}
//Format data that will be interpreted by the Desktop Manager.
//Format is Length Type Data
//Length is a short, type is a byte and data is the length
// specified by Length.
//Data must be structured in this format to be understood
// by the Desktop Manager.
try
{
for (count = 0; count < 5; ++count)
{
//Write the name.
db.writeShort(permNames[count].length() + 1);
db.writeByte(FIELDTAG_NAME);
db.write(permNames[count].getBytes());
db.writeByte(0);
//Write the age.
tempString = permAges[count] + "";
db.writeShort(tempString.length() + 1);
db.writeByte(FIELDTAG_AGE);
db.write(tempString.getBytes());
db.writeByte(0);
}
} catch (Exception e)
{
retVal = false;
}
//Return true if all data was processed.
return retVal;
}
//Interprets and stores the data sent from the Desktop Manager.
public boolean setSyncData(DataBuffer db, int version)
{
int length, nameCount = 0, ageCount = 0;
boolean retVal = true;
try
{
//Read until the end of the Databuffer.
while (db.available() > 0)
{
//Read the length of the data.
length = db.readShort();
//Set the byte array to the length of the data.
byte[] bytes = new byte[length];
//Determine the type of data to be read (name or age).
switch (db.readByte())
{
case FIELDTAG_NAME:
//Read the name from the Databuffer.
//Convert and store it in the String array.
db.readFully(bytes);
permNames[nameCount] = new String(bytes).trim();
++nameCount;
break;
case FIELDTAG_AGE:
//Read the age from the Databuffer.
//Convert and store it in the int array.
db.readFully(bytes);
permAges[ageCount]
= (int)(Integer.parseInt(new String(bytes).trim()));
++ageCount;
break;
}
}
} catch (Exception e)
{
retVal = false;
}
try
{
//Store the new data in the persistent store object.
permUserList = new UserList(permNames, permAges);
store.setContents(permUserList);
store.commit();
} catch (Exception e)
{
retVal = false;
}
//Return true if the data was successfully restored,
//or false if it was not.
return retVal;
}
}
/**
* UserList.java
*
* UserList is persistable and holds the list of names and ages.
*
*/
package com.samples.syncItemSample;
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.device.api.util.*;
import net.rim.device.api.synchronization.*;
import java.util.*;
import net.rim.device.api.i18n.Locale;
public final class UserList implements Persistable
{
//The persistable objects.
private String[] permNames = new String[5];
private int permAges[] = new int[5];
//Initialize the class with empty values.
public UserList()
{
}
//Initialize the class with the specified values.
public UserList(String[] names, int ages[])
{
permNames = names;
permAges = ages;
}
//Get/set methods.
public String[] getNames()
{
return permNames;
}
public void setNames(String[] names)
{
permNames = names;
}
public int[] getAges()
{
return permAges;
}
public void setAges(int[] ages)
{
permAges = ages;
}
}
/**
* UserListScreen.java
*
* This screen displays the list of names and ages.
*
*/
package com.samples.syncItemSample;
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 java.util.*;
public final class UserListScreen extends MainScreen
{
public UserListScreen(String[] names, int[] ages)
{
super();
//Create a horizontal field manager to hold the two vertical field
//managers to display the names and ages in two columns.
HorizontalFieldManager backGround = new HorizontalFieldManager();
VerticalFieldManager leftColumn = new VerticalFieldManager();
VerticalFieldManager rightColumn = new VerticalFieldManager();
//Array of fields to display the names and ages.
LabelField displayNames[] = new LabelField[5];
LabelField displayAges[] = new LabelField[5];
int count;
//Set the screen title.
LabelField title = new LabelField("User List",
LabelField.ELLIPSIS | LabelField.USE_ALL_WIDTH);
setTitle(title);
//Add the column titles and a blank field to create a space.
LabelField leftTitle = new LabelField("User ");
leftColumn.add(leftTitle);
LabelField rightTitle = new LabelField("Age");
rightColumn.add(rightTitle);
leftColumn.add(new LabelField(""));
rightColumn.add(new LabelField(""));
//Populate and add the name and age fields.
for (count = 0; count < 5; count++)
{
displayNames[count] = new LabelField(names[count]);
displayAges[count] = new LabelField(String.valueOf(ages[count]));
leftColumn.add(displayNames[count]);
rightColumn.add(displayAges[count]);
}
//Add the two vertical columns to the horizontal field manager.
backGround.add(leftColumn);
backGround.add(rightColumn);
//Add the horizontal field manager to the screen.
add(backGround);
}
public boolean onClose()
{
System.exit(0);
return true;
}
//Close the screen whenever a key is pressed.
public boolean keyChar(char key, int status, int time)
{
this.close();
return true;
}
//Close the screen if the trackwheel is clicked.
public boolean trackwheelClick(int status, int time)
{
this.close();
return true;
}
}