Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Contributor
goojo
Posts: 16
Registered: ‎07-28-2010
My Device: Bold 9700
My Carrier: Vodafone
Accepted Solution

ContentHandler and Email Attachments

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-Development/Attachment-handling-problems/m-p/221605

 

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

 

// John Goodyear
Please use plain text.
Developer
BB-Dude
Posts: 516
Registered: ‎07-23-2010
My Device: 9900

Re: ContentHandler and Email Attachments

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"

Please use plain text.
Contributor
goojo
Posts: 16
Registered: ‎07-28-2010
My Device: Bold 9700
My Carrier: Vodafone

Re: ContentHandler and Email Attachments

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.

 

 

// John Goodyear
Please use plain text.
Developer
BB-Dude
Posts: 516
Registered: ‎07-23-2010
My Device: 9900

Re: ContentHandler and Email Attachments

 

Did you confirm that the attachment content type is the same as ContentType.TYPE_APPLICATION?

Please use plain text.
Contributor
goojo
Posts: 16
Registered: ‎07-28-2010
My Device: Bold 9700
My Carrier: Vodafone

Re: ContentHandler and Email Attachments

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?

 

// John Goodyear
Please use plain text.
Developer
BB-Dude
Posts: 516
Registered: ‎07-23-2010
My Device: 9900

Re: ContentHandler and Email Attachments

Try hard coding "application/octect-stream" instead of using ContentType.TYPE_APPLICATION.

Also register two suffixes "bin" and ".bin"

Please use plain text.
Contributor
goojo
Posts: 16
Registered: ‎07-28-2010
My Device: Bold 9700
My Carrier: Vodafone

Re: ContentHandler and Email Attachments

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!

 

// John Goodyear
Please use plain text.
Developer
BB-Dude
Posts: 516
Registered: ‎07-23-2010
My Device: 9900

Re: ContentHandler and Email Attachments

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()); }
Please use plain text.
Contributor
goojo
Posts: 16
Registered: ‎07-28-2010
My Device: Bold 9700
My Carrier: Vodafone

Re: ContentHandler and Email Attachments

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.

 

// John Goodyear
Please use plain text.
Contributor
goojo
Posts: 16
Registered: ‎07-28-2010
My Device: Bold 9700
My Carrier: Vodafone

Re: ContentHandler and Email Attachments

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().inStartup()){
            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

 

// John Goodyear
Please use plain text.