Help! My BlackBerry JDE won’t start anymore.

You’ve been writing BlackBerry applications and building your code with the BlackBerry JDE for some time now. Then, one day, you launch the JDE and it fails to open!

What gives?

I assume you’ve covered the basics – your system has the Java runtime environment set up, with all the Java-related environment variables set up properly and pointing to the right places.

Are you running on a 64-bit system?

BlackBerry tools don’t play nice with 64-bit systems. Tools don’t run properly, simulators don’t simulate accurately (sometimes not at all). If you are running the BlackBerry dev tools on a 64-bit version of Windows, and start seeing weird behavior, all other things aside, this could be the cause.

At Antair, we run all of our BlackBerry tools on 32-bit Windows XP (virtual) machines. Until RIM updates their tools to support 64-bit systems (ha!), I suggest you set up a 32-bit rig for your BlackBerry dev work.

I’m already running on a 32-bit system. The JDE just fails to open!

OK. Maybe it’s a memory or configuration issue.

Let’s take a look at the batch file that launches the IDE. If you’re working with JDE 4.5, you’ll find the launcher batch file in

“C:\Program Files\Research In Motion\BlackBerry JDE 4.5.0\bin”

Take a look at the ide.bat file. The batch file launches the JDE with something like:

start javaw -Xmx256M -DRIM_RUNTIME=..\lib -DRIM_BIN=..\bin -jar IDE.jar

Open up the command prompt, go to the directory containing the ide.bat file, and run the launch command manually to see if any errors are thrown out to the console:

javaw -Xmx256M -DRIM_RUNTIME=..\lib -DRIM_BIN=..\bin -jar IDE.jar

If you get a clear error message,  you can take steps to address whatever the process was complaining about. In certain instances, you may get an error indicating that there isn’t enough memory provided to the process to launch the IDE. It can happen. But hey, memory is cheap, so let’s give it some more:

javaw -Xmx1024M -DRIM_RUNTIME=..\lib -DRIM_BIN=..\bin -jar IDE.jar

See if that fixes things. We’ve had instances where allowing the process to grab more memory fixes the entire “JDE not starting” issue.

OK. 256, 1024, 2048, it doesn’t matter. I don’t see any error messages on the console, and the JDE still won’t start.

You installed a simulator recently didn’t you? Admit it. You’re testing an existing application to see if it will run on a new BlackBerry device, and you just downloaded and installed one of those brand new simulators that RIM provides. Right?

This breaks JDEs. I don’t know why, but installing standalone simulators with existing JDEs on the system, sometimes breaks some of those JDEs.

To fix it, go into the same bin directory that contained the ide.bat file we’ve been messing with. In there, you’ll find a “Settings.rc” file.

Delete it. Or move it, to be safe. Then start the JDE.

It’ll start as a “newly installed” JDE, with the samples project open, and no customizations that you spent all that time setting up … but it will start.

 

How do I find unused functions in my PHP project?

Find unused functions and methods in a set of PHP files.

USAGE: find_unused_functions.php <root_directory>

NOTE: This is a ‘quick-n-dirty’ approach to the problem. This script only performs a lexical pass over the files, and does not respect situations where different modules define identically named functions or methods. If you use an IDE for your PHP development, it may offer a more comprehensive solution.

Requires PHP 5

Direct download: find_unused_functions.zip

Code:

#!/usr/bin/php -f
 
<?php
 
// ============================================================================
//
// find_unused_functions.php
//
// Find unused functions in a set of PHP files.
// version 1.3 - 08/20/2011
//
// ============================================================================
//
// Copyright (c) 2011, Andrey Butov. All Rights Reserved.
// This script is provided as is, without warranty of any kind.
//
// http://www.andreybutov.com
//
// ============================================================================
 
// This may take a bit of memory...
ini_set('memory_limit', '2048M');
 
if ( !isset($argv[1]) ) 
{
	usage();
}
 
$root_dir = $argv[1];
 
if ( !is_dir($root_dir) || !is_readable($root_dir) )
{
	echo "ERROR: '$root_dir' is not a readable directory.\n";
	usage();
}
 
$files = php_files($root_dir);
$tokenized = array();
 
if ( count($files) == 0 )
{
	echo "No PHP files found.\n";
	exit;
}
 
$defined_functions = array();
 
foreach ( $files as $file )
{
	$tokens = tokenize($file);
 
	if ( $tokens )
	{
		// We retain the tokenized versions of each file,
		// because we'll be using the tokens later to search
		// for function 'uses', and we don't want to 
		// re-tokenize the same files again.
 
		$tokenized[$file] = $tokens;
 
		for ( $i = 0 ; $i < count($tokens) ; ++$i )
		{
			$current_token = $tokens[$i];
			$next_token = safe_arr($tokens, $i + 2, false);
 
			if ( is_array($current_token) && $next_token && is_array($next_token) )
			{
				if ( safe_arr($current_token, 0) == T_FUNCTION )
				{
					// Find the 'function' token, then try to grab the 
					// token that is the name of the function being defined.
					// 
					// For every defined function, retain the file and line
					// location where that function is defined. Since different
					// modules can define a functions with the same name,
					// we retain multiple definition locations for each function name.
 
					$function_name = safe_arr($next_token, 1, false);
					$line = safe_arr($next_token, 2, false);
 
					if ( $function_name && $line )
					{
						$function_name = trim($function_name);
						if ( $function_name != "" )
						{
							$defined_functions[$function_name][] = array('file' => $file, 'line' => $line);
						}
					}
				}
			}
		}
	}
}
 
// We now have a collection of defined functions and
// their definition locations. Go through the tokens again, 
// and find 'uses' of the function names. 
 
foreach ( $tokenized as $file => $tokens )
{
	foreach ( $tokens as $token )
	{
		if ( is_array($token) && safe_arr($token, 0) == T_STRING )
		{
			$function_name = safe_arr($token, 1, false);
			$function_line = safe_arr($token, 2, false);;
 
			if ( $function_name && $function_line )
			{
				$locations_of_defined_function = safe_arr($defined_functions, $function_name, false);
 
				if ( $locations_of_defined_function )
				{
					$found_function_definition = false;
 
					foreach ( $locations_of_defined_function as $location_of_defined_function )
					{
						$function_defined_in_file = $location_of_defined_function['file'];
						$function_defined_on_line = $location_of_defined_function['line'];
 
						if ( $function_defined_in_file == $file && 
							 $function_defined_on_line == $function_line )
						{
							$found_function_definition = true;
							break;
						}
					}
 
					if ( !$found_function_definition )
					{
						// We found usage of the function name in a context
						// that is not the definition of that function. 
						// Consider the function as 'used'.
 
						unset($defined_functions[$function_name]);
					}
				}
			}
		}
	}
}
 
 
print_report($defined_functions);	
exit;
 
 
// ============================================================================
 
function php_files($path) 
{
	// Get a listing of all the .php files contained within the $path
	// directory and its subdirectories.
 
	$matches = array();
	$folders = array(rtrim($path, DIRECTORY_SEPARATOR));
 
	while( $folder = array_shift($folders) ) 
	{
		$matches = array_merge($matches, glob($folder.DIRECTORY_SEPARATOR."*.php", 0));
		$moreFolders = glob($folder.DIRECTORY_SEPARATOR.'*', GLOB_ONLYDIR);
		$folders = array_merge($folders, $moreFolders);
	}
 
	return $matches;
}
 
// ============================================================================
 
function safe_arr($arr, $i, $default = "")
{
	return isset($arr[$i]) ? $arr[$i] : $default;
}
 
// ============================================================================
 
function tokenize($file)
{
	$file_contents = file_get_contents($file);
 
	if ( !$file_contents )
	{
		return false;
	}
 
	$tokens = token_get_all($file_contents);
	return ($tokens && count($tokens) > 0) ? $tokens : false;
}
 
// ============================================================================
 
function usage()
{
	global $argv;
	$file = (isset($argv[0])) ? basename($argv[0]) : "find_unused_functions.php";
	die("USAGE: $file <root_directory>\n\n");
}
 
// ============================================================================
 
function print_report($unused_functions)
{
	if ( count($unused_functions) == 0 )
	{
		echo "No unused functions found.\n";
	}
 
	$count = 0;
	foreach ( $unused_functions as $function => $locations )
	{
		foreach ( $locations as $location )
		{
			echo "'$function' in {$location['file']} on line {$location['line']}\n";
			$count++;
		}
	}
 
	echo "=======================================\n";
	echo "Found $count unused function" . (($count == 1) ? '' : 's') . ".\n\n";
}
 
// ============================================================================
 
/* EOF */

Whatcha doin’?

What are you doing?

Working.

But it’s Sunday!

Yeah.

How much do you work?

I don’t understand.

Well … how many hours do you work?

I always work.

Testing Your Web App on a BlackBerry Simulator

The web browser provided by BlackBerry simulators is a fairly accurate representation of what your users are running on their BlackBerry devices.

While it’s always advisable to test native client applications on a real device prior to shipping the product, as a web app developer, you can get a good understanding of how your application will act on a BlackBerry, without having to purchase a real device.

Downloading the simulators

RIM offers a wide variety of simulators for you to choose from. If you’re not sure which to choose, I would recommend the following selections:

BlackBerry Torch, 98xx

This is one of the most popular models in today’s BlackBerry market, and has one of the largest screen resolutions. The BlackBerry Torch also features a touch-screen, and the ability to flip from portrait to landscape mode.

BlackBerry Style, 9670

The BlackBerry Style is RIM’s current flip-style phone. While not as popular as some of the other models, it has a unique screen size. If you need to reach as wide an audience as possible, it wouldn’t hurt to test your web application on this simulator.

BlackBerry Pearl, 81xx

The Pearl was the first consumer-targeted BlackBerry. While they have lost popularity as of late, plenty of BlackBerry users are still walking around with these models. The Pearl has a long-and-thin form-factor, with a resolution of 240×260.

BlackBerry Curve, Bold, or Tour

While the BlackBerry Torch has recently gained popularity, most BlackBerry owners of the past few years would have one of these three models. The Curve, Bold, and Tour share a similar form-factor. With the exception of recent models, these devices do not have a touch-screen, and they do not allow the user to switch from portrait mode to landscape mode.

Your web application may behave differently depending on the version of the operating system running on the device. When choosing simulators, it’s a good idea to select a wide range of operating systems.

A good “older” model would be a simulator running RIM OS 4.2. As I’m writing this, the newer simulators will be running RIM OS 6.x.

Downloading a BlackBerry Simulator

Downloading the MDS simulator

To test your web application on a BlackBerry simulator, the simulator’s web browser needs to be able to connect to the internet, and for that, you will need to run the MDS simulator first.

The MDS simulator allows the BlackBerry simulator to connect to the internet. You can download the MDS simulator as part of the BlackBerry Email and MDS Services simulator package.

MDS Package

Testing your web application on the simulator

Start with installing both the MDS simulator and the phone simulators you’ll be testing on.

It’s worth noting that although the BlackBerry phone simulators are Java-based, and require Java to be installed on the computer to run, they will only work on Windows machines. The simulators also tend to behave strangely on 64-bit systems.

At Antair, we do our simulator testing on 32-bit Windows XP hosts, running as virtual machines.

Once installed, start the MDS simulator. All it will do is open a terminal window and dump some startup output. If an error comes up, you can look at the output information for a clue. Otherwise, you can just minimize this window.

MDS Simulator

Now, start one of the BlackBerry phone simulators.

You should be able to launch the web browser and type in the URL of your web application.

The settings and options presented by the web browser in the simulator, are the same options that will be available to your users. You will be able to test whether your web application works well with Javascript turned off, or cookies disabled, etc.

BlackBerry Web Browser with CNN mobile.

Antair Nightstand 1.6

Antair Nightstand 1.6 for the BlackBerry PlayBook is now available.

This release introduces the news functionality, adds a new animated theme called Daydream, and has several other improvements.

The Daydream theme displays the clock and weather information over a background of animated lights.

Antair Nightstand - Daydream Theme

The News feature allows you to view local and international news directly from Nightstand.

Antair Nightstand - News

The new Antair Nightstand is available in the BlackBerry App World.

Here’s a brand new video of Antair Nightstand, with the new theme and news functionality.