Random Noise

cat /dev/random >> /dev/dsp

Archive for the ‘Java’ Category

Blackberry: ContentHandler and ApplicationMenuItem

with one comment

ContentHandler gives us the ability to register our application, so that our app is invoked automatically
when user clicks to open particular type of a file. ContentHandler uses ‘Server – Client’ model.
Client requests for processing a file type and Server processes it. All the application-filetype bindings are
stored in a Registry, the client must query this registry to find out if there are any handlers available for that
file type. Then invoke it.

To make our app a ‘Server’, we need to implement RequestListener. See below for sample implementation of a mp3 file handler.

It is important to register our app. It is recommended to perform/verify registration once during device startup.
You shoud pass an argument say “startup” during startup to differentiate from other entry points.
In eclipse this can be configured by editing the App_Descriptor.xml.

Also note that APP_IDs used for registration must be unique and failure to do so will render your app unusable.

package com.serialize.apps;

public class Mp3Player extends UiApplication implements RequestListener {
	public static final long MY_APP_KEY = 0x4a23b634ab2baf78L;
	public static final String MY_APP_CLASS = Mp3Player.class.getName();
	public static final String MY_APP_ID = "com.serialize.Mp3Player"
	private Invocation pending;
	private ContentHandlerServer server;
	
	public Mp3Player() {
		try {
			this.server = Registry.getServer(MY_APP_CLASS);
			//start listening formp3 invocation requests
			this.server.setListener(this);	
		} catch (ContentHandlerException e) {
		}					
	}

	public static void main(String[] args) {
		// On device startup register our app
		if (args != null && args.length > 0 && args[0].equals("startup")) {
			ensureRegistration();
		} else {			
			Mp3Player app = new Mp3Player();
			app.enterEventDispatcher();
		}
	}

	private static void ensureRegistration() {
		Object o = RuntimeStore.getRuntimeStore().get(MY_APP_KEY);
		// register only if not done already.
		if (o == null) {
			String[] types = {"audio/mp3"};
			String[] suffixes = {".mp3"};            
			String[] actions = {ContentHandler.ACTION_OPEN};
			String[] actionNames = {"Open with Mp3Player"}; 
			ActionNameMap[] actionNameMaps = {new ActionNameMap(actions,actionNames,"en")};


			Registry registry = Registry.getRegistry(MY_APP_CLASS);
		
			try {
				// Register our app as mp3 content handler
				registry.register(MY_APP_CLASS, types ,	suffixes , actions , actionNameMaps, MY_APP_ID, null);

				/* Register Menu Item here */
				new Mp3MenuItem().registerInstance();			
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	/* Utility method to perform invocation from other classes */
	public synchronized static void invoke(String className, String fileName, byte[] contents) {

		Invocation request = new Invocation();
		request.setID(MY_APP_ID); // request Mp3Player
		request.setURL(fileName);
		request.setData(contents); // set byte array if we have it
		request.setType("audio/mp3");

		// we don't care about the response
		request.setResponseRequired(false);

		try {
			Registry registry = Registry.getRegistry(className);
			registry.invoke(request);
		} catch (Exception ex) {
			System.out.println(className + ": Error occured while opening file");
		}
	}	
	
	public synchronized void invocationRequestNotify(ContentHandlerServer handler) {

		pending = handler.getRequest(false);
		
		if (pending != null) {
			byte[] contents = getContents();
			if (contents != null && contents.length != 0) {
				// TODO: Implement your Main screen and push it on the stack
				// remember that pushScreen is non blocking
				pushScreen(new Mp3PlayerScreen(contents));
				
				// notify the server that we are handling the invocation
				this.server.finish(pending, Invocation.OK);
			}
			else{
				// Close this instance or else you'll get "previous instance still active"
				// So we stop listening to invocation requests
				System.exit(0);
			}			
		} else {
			// Stop listening to invocation requests
			System.exit(0);
		}			
	}

	// Reads data from the invocation request
	// The invocation may contain associated byte array or URL to a file
	// or it could have associated stream (say network stream).
	private byte[] getContents() {
		InputStream is = null;
		StreamConnection sc = null;
		FileConnection fc = null;
		try {
			String filename = null;
			byte[] data = null;
			synchronized (this) {
			
				filename = pending.getURL();
				
				/* try to get associated byte array */
				if(filename.toLowerCase().indexOf("mp3") != -1) {
					data = pending.getData();
				}
				else {
				    // if file name did not end with mp3, don't handle it
					filename = null;
				}
			}
			
			// if we retrieved a byte array
			if (data != null && data.length > 0) {
				return data;
			} else if (filename != null) {
				
				// this is blocking call. use thread instead [e.g for network connection.]
				Connection conn = pending.open(false);
				
				// if this is a file connection the file is already on our phone
				// remember that a FileConnection is also a StreamConnection, 
				// so check FileConnection first				
				if (conn instanceof FileConnection) {
					fc = (FileConnection) conn;
					is = fc.openInputStream();
					
					return IOUtilities.streamToBytes(is);
				} else {
					sc = (StreamConnection) conn;
					is = sc.openInputStream();
					return IOUtilities.streamToBytes(is);
					// TODO: Save the array to SD Card?
				}

			}
		} catch (Exception ex) {
			System.out.println("Error occured while reading file.");
		} finally {
			try {
				if (is != null) {
					is.close();
				}
				if (fc != null) {
					fc.close();
				}
				if (sc != null) {
					sc.close();
				}
			} catch (Exception ex) {

			}
		}
		return new byte[0];
	}
}

Implementing the ApplicationMenuItem:

Although you may not need to implement a custom context menu item, it is particularly useful when there are
other third party applications already handling the same file type.

ApplicationMenuItem provides an alternate entry point, i.e a way to add a custom menu item when a specific application is running.
For example File Browser or Email app. To do this you have to register your implementation with ApplicationMenuItemRepository,
once registered that instance will be cached in memory until the device is on. But this repository gets wiped out every time the device is rebooted.

So it is a good practice to register once per startup(see above). Now, if you have a UIApplication and it has an icon, user will
start it by selecting it. In this case we have to make sure that we do not register our menu item twice. For this we will have to
use RuntimeStore to save state of our registration.

ApplicationMenuItem construct takes a context, if you are registering this menu item for specific files, mime type of the file type
must be passed as context. This especially important when you are registering your menu item with File Browser.

Important gotcha here is that when you request for an invocation, and the server is not running,
the server will be initialized before the invocation request is made.

package com.serialize.apps;

public class Mp3MenuItem extends ApplicationMenuItem {
	public static final long MP3_MENU_ITEM_KEY = 0x1a23b6c6ab2b1075L;

	public Mp3MenuItem() {
		/* will only be shown if the file mime type matches the context */ 
		super("audio/mp3", 500000); // order is found by trial and error method
	}

	/* This will be menu item text */
	public String toString() {
		return "Open MP3 File";
	}

	public void registerInstance() {
		/* verify Registration */
		Object o = RuntimeStore.getRuntimeStore().remove(MP3_MENU_ITEM_KEY);
		 if(o == null) {
			ApplicationMenuItemRepository amir = ApplicationMenuItemRepository.getInstance();
			// Gets Mp3Player descriptor, since this method is called from ensureRegistration()
			ApplicationDescriptor ad_startup = ApplicationDescriptor.currentApplicationDescriptor();
			ApplicationDescriptor ad_gui = new ApplicationDescriptor(ad_startup, new String[] {"menuitem_entry"});
			
			/* Register for File Browser */
			amir.addMenuItem(ApplicationMenuItemRepository.MENUITEM_FILE_EXPLORER, this, ad_gui);	 	
			RuntimeStore.getRuntimeStore().put(MP3_MENU_ITEM_KEY, this);
		 }
	}

	/* Mp3Player main() will be called before call to this function */
	public Object run(Object context) {
		if (context != null && context instanceof String) {
			String inputFile = (String) context;

			// excecution control is automatically passed to Mp3Player.invocationRequestNotify() after this
			Mp3Player.invoke(getClass().getName(), inputFile, null);
		}
		return context;
	}
}

Written by Vivek Unune

June 30, 2010 at 2:40 am

Posted in blackberry, Java

Tagged with ,

Signing a JAR file with .spc and .pvk file

with 2 comments

0. You must have a .spc(Certificate) file and a .pvk(Key) file

1. Download pvkimprt.exe from here.

And yes don’t forget to install the downloaded exe!!

2. To generate a .pfx file run:

pvkimprt -PFX myspcfile.spc mypvkfile.pvk

type in the password and give a pathname

3. Import this file from Firefox

4. Export the certificate from Firefox to a .p12 file

5. This file can be used with jarsigner

6. We also need to know the alias of the .p12 file, so copy the .p12 file to the Java bin directory and run:

keytool -list -storetype pkcs12 -keystore mycert-p12.p12

7. Enter the password

8. Then you will see output like this:

Keystore type: pkcs12

Keystore provider: SunJSSE

Your keystore contains 1 entry

xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx, Aug 13, 2007, keyEntry,

Certificate fingerprint (MD5):

hh:hh:hh:hh:hh:hh:hh:hh:hh:hh:hh:hh:hh:hh:hh:hh

9. The xxxx-xxx… number is the alias for the key

10. To sign a jar run:
jarsigner -storetype pkcs12 -keystore mycert-p12.p12 myjar.jar \
“xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx”

Update 18th April 2008:

You can also sign the jar using pkcs12 or .p12 certificate using this:

jarsigner -keystore mycert.p12 -storepass mystorepass -keypass mykeypass -storetype “pkcs12” -signedjar myjar-signed.jar myjar.jar “xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx”

To verify your signed jar do:

jarsigner -verify -verbose -keystore mycert.p12 -storepass mystorepass -keypass mykeypass -storetype “pkcs12” myjar-signed.jar

Written by Vivek Unune

August 14, 2007 at 2:58 am

Posted in Java

Tagged with , , ,

Installing ANT

with 3 comments

  1. Download the latest zip from http://ant.apache.org/bindownload.cgi.
  2. Extract it to a directory. For example C:\Users\Joe\apache-ant-1.7-bin.
  3. Edit your environment variables: On Windows XP: Right click on
    My Computer and select properties, then select Advance tab. On
    Vista: Right click on Computer and select properties => Advanced
    System Settings, then click on Environment Variables button.
  4. Add two system environment variables:
    JAVA_HOME = C:\Program Files\Java\jdk1.6.0_01
    ANT_HOME = C:\Users\Joe\apache-ant-1.7-bin
  5. Edit PATH envroment variable and add the following to the end:
    ;%JAVA_HOME%\bin;%ANT_HOME%\bin;

Written by Vivek Unune

June 30, 2007 at 2:41 pm

Posted in Java, Windows Tip

Tagged with , ,

JNI debugging using Eclipse and Visual Studio 2005

with 2 comments

Recently I was involved in a project that involved java code accessing native c++ libraries. All went fine from creation of the JNI functions to its implementation. In one of the functions has java.nio.ByteBuffer as parameter. On the java side this buffer was initialized using allocateDirect. On the c++ side, the buffer content is altered and size gets reduced. The limit is changed using limit(int). I managed this all using cout/printfs/err to print the debug information.

I put up a screen cast (without voice) for anyone who needs to watch this method inaction. Download this video from here: http://www.hotlinkfiles.com/files/1266155_p61kq/jni-debug.divx

Short description of the same:

So, I really needed to look at the live data. Hence needed a way to debug JNI c++ code. So, as everyone else I turned to Google. Finally this article described the need for dual debuggers. I understood that we need to start the java application that uses jvm in debug mode (-Xdebug). We also need to make sure that Eclipse and Visual Studio co-operate. So we need the -Xrunjdwp jvm argument. This will specify the protocol and port address where Eclipse (remote java application) will listen to.

So, open the JNI C++ VS 2005 project and navigate to project->settings->debugging. in command specify the path to java.exe, in command arguments add this:

-Xmx400m -Xms400m -Xdebug -Xnoagent \
-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 \
-Djava.library.path=”[path to debug folder containing JNI DLL]” \
-cp “.;[path to folder containing .class files for he java app]” \
[main java class]

And then set break points in the c++ code.

Then we need to create a remote java application configuration in Eclipse. Specify the port number (in this case 8000). Also in my case I had to add java source directory where Eclipse will search for the java code of the remote application. This is done from the source tab. Once done add break points where the java application loads the native library and where you call the native function.

Then start debugging the VS project (f5). The java application will be in suspended mode (because suspend=y argument) and wait for external debugger to attach. So, start the Eclipse’s remote java application configuration that we created in debug mode. And start debugging!

Written by Vivek Unune

May 18, 2007 at 11:58 pm

Posted in Java, linux, VC++

Tagged with , , , ,