If you are using Internet Explorer, please remove blackberry.com from your compatibility view settings.

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
New Developer
jcjones
Posts: 5
Registered: ‎08-21-2009
My Device: Not Specified
Accepted Solution

Programmatically retrieving attachments larger than 64kilobytes

Greetings,

 

I'm trying to programmatically retrieve an image attachment from an e-mail sent to my Blackberry. My issue is that once the attachment is larger than 64kb, I cannot seem to retrieve the data from the BIS server. All of my testing is being done on live hardware, and I am signing my application.

 

In my application I've registered an AttachmentHandler set to accept  both the "image/jpg" and "application/octet-stream" types (as suggested here), so the Message's Multipart object contains a SupportedAttachmentPart. However, SupportedAttachmentPart.getContent returns a zero-length array *and* SupportedAttachmentPart.hasMore returns false. Furthermore, calling Transport.more has no apparent effect (so perhaps I'm missing something important from this post?)

 

I believe I've read all the existing threads on this subject, but I must be missing something. Can anyone give me some suggestions / different approaches to try?

 

My test hardware is a Bold 9000 running 4.6.0.167.

 

Here's some test routines that I'm currently using.

 

This routine is intended to read the image attachment into memory so that I can manipulate it: (Don't get concerned regarding memory usage nor multiple attachments; this is just a prototype :smileyhappy: )

 

private byte[] getPayload(Message message) {
if (message.getContent() instanceof Multipart) {
Multipart multi = (Multipart) message.getContent();

System.out.println("in multipart - sz: " + multi.getCount());

for (int i = 0; i < multi.getCount(); i++) {
BodyPart bp = multi.getBodyPart(i);
if (bp.hasMore()) {
System.out.println("Requesting more");
try {
Transport.more(bp, true);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

for (int i = 0; i < multi.getCount(); i++) {
BodyPart bp = multi.getBodyPart(i);
if (bp instanceof SupportedAttachmentPart) {
if (bp.getContent().getClass().isArray()) {
byte[] content = (byte[]) bp.getContent();
return content;

}
}
}
}

System.out.println("Found none");
return new byte[0];
}

 

 


This one sends an email with the test image attached (just for completeness)

menu.add(new MenuItem("Email Test",999,0) {

public void run() {
try {
final Message msg = new Message();
msg.setSubject("Test Picture Attachment");
msg.addRecipient(Message.RecipientType.TO, new Address("blackberryEmail@att.blackberry.net", "My Phone"));
msg.addRecipient(Message.RecipientType.CC, new Address("myEmail@gmail.com", "My Gmail"));

final Multipart parts = new Multipart();

byte[] imageData = getImageDataFromDisk();

final TextBodyPart textPart = new TextBodyPart(parts);
textPart.setContent("Cry 'God for Harry, England, and Saint George!'");

final SupportedAttachmentPart imagePart = new SupportedAttachmentPart(parts);
imagePart.setContentType("image/jpg");
imagePart.setFilename("a.jpg");
imagePart.setContent(imageData);

parts.addBodyPart(textPart);
parts.addBodyPart(imagePart);

msg.setContent(parts);

Transport.send(msg);
} catch (Throwable t) {
t.printStackTrace();
}
}
});

 


 

My attachment handler looks like:

private final class ShowAttachmentHandler implements AttachmentHandler {

public String menuString() {
return "Show";
}

public void run(Message m, SupportedAttachmentPart p) {
System.out.println("Attachment Handler Called");
}

public boolean supports(String contentType) {
if (contentType == null)
return false;

 

boolean result = contentType.toLowerCase().indexOf("jpg") != -1;
if (contentType.toLowerCase().indexOf("octet-stream") != -1) {
System.out.println("It's an octet stream");
result = true;
}

return result;
}
}

 

 

Thanks!

Please use plain text.
New Developer
redbutt
Posts: 37
Registered: ‎03-02-2009
My Device: Bold 9700
My Carrier: TMO

Re: Programmatically retrieving attachments larger than 64kilobytes

[ Edited ]

I don't know if I'm having the same issue or not, but there's definately a similarity.  When I call Transport.more(part, true) I don't really see anything happen.  I've attached a MessageListener to the message and I do see the listener get activated with an UPDATED event, but when the handler does it's work, the content size of the part is still 0 bytes (I'm trying to grab a 65k wav file).

 

Now, for more fun...if I manually go to the message and select the attachment to download, I see a flurry of activity...constant updates on my MessageListener, but my check for part.hasMore() never returns false...so my routine never completes because it is waiting for the final UPDATE event where the download is complete.

 

No errors are getting thrown.  This is inside a method called extractAudioAttachment, and this is executed after looping through the body parts and finding the octet-stream part...all this works great.

 

 

if (part.hasMore() && !part.moreRequestSent()) {
try {
System.out.println("Requesting the full data for the part.");
m.addMessageListener(getInstance());
Transport.more(part, true);

} catch (Throwable e) {
System.out.println("Error getting audio content: " + e);
e.printStackTrace();
}
} else if (!part.hasMore()) {
System.out.println("Audio part appears to have content: " + part.getSize());

byte[] ba = null;

if (part.getContent() instanceof String) {
ba = ((String)part.getContent()).getBytes();
} else if (part.getContent() instanceof byte[]) {
ba = (byte[])part.getContent();
}

String fName = Settings.MSGS_DIR + "mywav.wav";
System.out.println("Saving message part as: "+ fName);
try {
FileUtils.createDirectories(Settings.MSGS_DIR);
FileUtils.writeToFile(fName, ba, true);

} catch (IOException e) {
System.out.println("Error saving audio file: " + e);
} finally {
m.removeMessageListener(getInstance());
}
} else {
System.out.println("Waiting for more request to finish ("+part.hasMore()+"): " + part.getSize());
}

 Any my MessageListener "changed" event:

 

public void changed(MessageEvent e) {
if (e.getMessageChangeType() == MessageEvent.UPDATED) {
System.out.println("Message has been updated...this should mean we have the audio now.");

Message m = e.getMessage();

System.out.println("Update vm object with id: " + m.getMessageId());
getInstance().extractAudioAttachment(m);
}
}

 Again...this works too.  But, when called from my app it only happens once, and the part.getSize() returns 0.  But, as I said...manually going to the message and selecting download I see this method accessed a ton...but then part.hasMore() never returns false.

 

 

 P.S.  Sorry for the code formatting...that didn't paste cleanly at all.

 

Message Edited by redbutt on 08-25-2009 03:59 AM
Please use plain text.
Administrator
MSohm
Posts: 14,362
Registered: ‎07-09-2008
My Device: BlackBerry Z30, BlackBerry PlayBook
My Carrier: Bell

Re: Programmatically retrieving attachments larger than 64kilobytes

SupporttedAttachmentParts are limited to 64kb.  It is not possible to request more on an AttachmentPart.

 

Instead of creating an AttachmentHandler you can use the content handler APIs and register a content handler for the attachment type.  This allows you to download the contents of attachments greater than 64kb.  Please refer to the chapidemo included with the BlackBerry JDE for an example.

Mark Sohm
BlackBerry Development Advisor

Please refrain from posting new questions in solved threads.
Problem solved? Click the Accept As Solution button.
Found a bug? Report it using Issue Tracker
Please use plain text.
New Developer
jcjones
Posts: 5
Registered: ‎08-21-2009
My Device: Not Specified

Re: Programmatically retrieving attachments larger than 64kilobytes

Mark, thanks for replying.

 

Just to make this crystal clear: There is at present no way for an application to retrieve attachments larger than 64kb without having the user manually invoke an attachment handler through the existing Messages/Inbox interface?

 

Cheers,

Please use plain text.
New Developer
jcjones
Posts: 5
Registered: ‎08-21-2009
My Device: Not Specified

Re: Programmatically retrieving attachments larger than 64kilobytes

Just to reply to myself: It looks like there is no way to download large attachments programmatically in the 4.x series APIs, but 5.0 adds the AttachmentDownloadManager which does exactly what I'm looking for.

Please use plain text.
New Developer
redbutt
Posts: 37
Registered: ‎03-02-2009
My Device: Bold 9700
My Carrier: TMO

Re: Programmatically retrieving attachments larger than 64kilobytes

Mark...you mention SupportedAttachmentParts, but what about UnsupportedAttachmentParts?   I think that I'm basically realizing that I can't do what I want, but I jsut want to make sure I'm not being dense.  I don't want to have a menu option that a user clicks on...I just want my app to grab the attachment and do something automatically...but I can see how that might be a ginormous security hole...anyone could write an app that could intercept email.

 

However, what I really don't get is why I can't get any part of the attachment at all.  Does Transport.getMore() just fail to function if the attachment is too large (vs. downloading up to the 64k limit)?  I get no error at all, but I also never get the update that getMore has completed.  I just get this same log signature (my log from the attached MessageListener)...the last line...the 0 is the bytes downloaded.

 

Processing body parts for message: -7177724
Have multipart type: text/plain
Have multipart type: application/octet-stream
Waiting for more request to finish (true): 0

 

When I download the attachement manually (from the email itself), this just loops over and over...0 bytes, even though the attachmetn clearly downloads...because I can open it.  The main nasty thing here is that since part.hasMore() never returns false, I never unhook the MessageListener.

Please use plain text.