07-29-2010 06:41 AM
I'm trying to implement a Content Handler and have been working closely with the CHAPIDemo and reading the CHAPI Specification and I'm still unable to get a content handler working with an email attachment, the same handler works fine for a file invoked from the file system.
Reading the forum I've found an identical issue here:
http://supportforums.blackberry.com/t5/Java-Develo
But there was no resolution posted.
My handler is being registed during device startup and on the whole everything seems "right" its just this last problem of the "Open Attachement" option returning "The attachment type cannot be viewed on your device" when invoked from the Mail client (testing with OS5 in simulator).
I'm aware of the "AttachmentHandler" interface and have looked into that but this seems to be a method that has been superseded by the ContentHandler system also the x-rimdevice stuff is a limitation.
Is there something I've over looked - as I've mentioned I've read just about every forum post on the ContentHandler API.
Thanks
John
Solved! Go to Solution.
07-29-2010 07:31 AM
Are you registering a content type and a suffix?
If you are registering a suffix is it with the period or without the period?
Example: ".txt" or "txt"
07-29-2010 08:14 AM
Yes with suffix and yes with period:
String[] types = {ContentType.TYPE_APPLICATION};
String[] suffixes = {".bin"};
String[] actions = {ContentHandler.ACTION_OPEN};
String[] actionNames = {"CHAPI Open"};
ActionNameMap[] actionNameMaps =
{new ActionNameMap(actions,actionNames,"en")};
try{
registry.register(CLASSNAME, types, suffixes, actions, actionNameMaps, ID, null);
}
catch (Exception che){
System.out.print(che.toString());
}Its probably worth noting I've tried many different combinations of values in types, suffixes and actions trying to find a working combination.
07-29-2010 08:22 AM
Did you confirm that the attachment content type is the same as ContentType.TYPE_APPLICATION?
07-29-2010 08:32 AM
Yes I did do some investigation into this, I'm at the mercy of the sending mail application and server I guess but I typically see:
Content-Type: application/octet-stream; name="test.bin" Content-Disposition: attachment; filename="test.bin" Content-Transfer-Encoding: base64 X-Attachment-Id: f_gbz55qp70
This is why I chose: ContentType.TYPE_APPLICATION for type.
I got this information from doing a view source on the message in Thunderbird - is it possible the mime type is modified in the device? - I'm not sure if its possible to see raw headers on a handset?
07-29-2010 08:37 AM
Try hard coding "application/octect-stream" instead of using ContentType.TYPE_APPLICATION.
Also register two suffixes "bin" and ".bin"
07-29-2010 10:15 AM
Tried both those suggestions and sadly neither has worked.
I'm still performing some tests including trying to invoke the CHAPI interface myself to test parameters.
I would love to see that code inside the mail app thats invoking the attachment to see what's being passd into CHAPI!
07-29-2010 10:18 AM
Here's what you should have: Also make sure your classname is the full path of your class that extends the UiApplication
String[] types = {"application/octet-stream"};
String[] suffixes = {".bin", "bin"};
String[] actions = {ContentHandler.ACTION_OPEN};
String[] actionNames = {"Pick a Name"};
ActionNameMap[] actionNameMaps =
{new ActionNameMap(actions,actionNames,"en")};
try{
registry.register(CLASSNAME, types, suffixes, actions, actionNameMaps, ID, null);
}
catch (Exception che){
System.out.print(che.toString());
}
07-29-2010 11:11 AM
Yes thats exactly what I have - still no luck - does this registration persist over device reboots - if so what what happens when the registration code runs on system start - do the new settings over write the old ones?
Going to clean the simulator and test again.
07-30-2010 05:22 AM
Hi,
I've tried all the things suggested so far and still no luck, to clarify: the handler works if invoked using the menu action inside this app, and if the file is accessed from the file system using the BB explorer it also works. It only fails to operate when trying to access from a message attachment.
package com.acme.filehandler; import javax.microedition.content.ActionNameMap; import javax.microedition.content.ContentHandler; import javax.microedition.content.ContentHandlerException; import javax.microedition.content.ContentHandlerServer; import javax.microedition.content.Invocation; import javax.microedition.content.Registry; import javax.microedition.content.RequestListener; import net.rim.device.api.system.ApplicationManager; import net.rim.device.api.ui.Field; import net.rim.device.api.ui.MenuItem; import net.rim.device.api.ui.UiApplication; import net.rim.device.api.ui.component.Dialog; import net.rim.device.api.ui.component.LabelField; import net.rim.device.api.ui.container.MainScreen; public final class SendMediaDemo extends UiApplication implements RequestListener { private static final String ID = "com.acme.filehandler"; private static final String CLASSNAME = ID+ ".SendMediaDemo"; private ContentHandlerServer contentHandlerServer; private Invocation pending; private DemoScreen demoScreen; // Constructor public SendMediaDemo() { try { this.contentHandlerServer = Registry.getServer(CLASSNAME); this.pending = this.contentHandlerServer.getRequest(false); this.contentHandlerServer.setListener(this); } catch(ContentHandlerException che) { System.out.println(che.toString()); } } // Construct GUI for the app public void ShowGUI() { this.demoScreen = new DemoScreen(); pushScreen(this.demoScreen); } public static void main(String[] args) { SendMediaDemo app = new SendMediaDemo(); // Start up - the register the handler if (ApplicationManager.getApplicationManager().inStar tup()){ app.register(true); } // Invoked with a pending request process it now. else if (app.pending != null){ app.ShowGUI(); app.processRequest(); app.requestForeground(); app.enterEventDispatcher(); } // Direct user invoke of the GUI else { app.register(false); app.ShowGUI(); app.enterEventDispatcher(); } } private void processRequest(){ if(this.pending!= null) { // Finish the invocation and set its status this.demoScreen.SetMessage("Handler has been invoked for: " + this.pending.getURL()); this.contentHandlerServer.finish(pending, Invocation.OK); } } /** * Registers this application as a content handler for image files */ private void register(boolean force) { Registry registry = Registry.getRegistry(CLASSNAME); if (force == false){ ContentHandler registered = registry.forID(ID, true); if (registered != null){ return; } } String[] types = {"application/octet-stream"}; String[] suffixes = {".bin", "bin"}; String[] actions = {ContentHandler.ACTION_OPEN}; String[] actionNames = {"Open Binary"}; ActionNameMap[] actionNameMaps = {new ActionNameMap(actions,actionNames,"en")}; try{ registry.register(CLASSNAME, types, suffixes, actions, actionNameMaps, ID, null); } catch (Exception che){ System.out.print(che.toString()); } } /** * RequestListener implementation * @param server The content handler server from which to request Invocation objects */ public void invocationRequestNotify(ContentHandlerServer server) { pending = server.getRequest(false); if (pending != null){ processRequest(); } } /** * A main screen in which to play video files */ private final class DemoScreen extends MainScreen { // Constructor private DemoScreen() { // Initialize UI components setTitle(new LabelField("Demo Screen",Field.FIELD_HCENTER)); add(new LabelField("Select Invoke from the menu")); addMenuItem(new MenuItem("Invoke" , 5, 5) { public void run() { try{ Invocation inv = new Invocation("file:///SDCard/test2.bin", "application/octet-stream"); inv.setResponseRequired(false); inv.setAction(ContentHandler.ACTION_OPEN); // Get access to the Registry and pass it the Invocation Registry registry = Registry.getRegistry(CLASSNAME); registry.invoke(inv); } catch (Exception e){ Dialog.alert(e.toString()); } } }); } public void SetMessage(String Message){ add(new LabelField(Message)); } } }
Thanks