April 2014 update: we have moved the project and packaged it with a sleek manual on our new website, along with a sleek manual and demo video. Check it out: http://easynativeextensions.com/product/diadraw-e-mail-ane/
News: The post below explains a workaround for a problem, which caused applications built with Adobe AIR 3.2 or lower to forcibly change their orientation, when using a native extension with a native window on iOS, like the Mail Composer.
If you are building with Adobe AIR 3.3 or newer and just need a native extension for e-mail, have a look at this new post: E-mail native extension updated for Adobe AIR 3.4 and iOS 6.0
If I have sinned towards Adobe or Apple, I swear it wasn’t premeditated. For the last couple of weeks however I have been paying for sins I must have committed and that, I hope, has taught me stuff.
The problem
AIR mobile application, iOS native extension for sending e-mail.
Everything works hunky-dory, until you close the e-mail client. Then the app rotates, although you haven’t rotated the device. Sound familiar?
I finally found a workaround that works for me and got flash.display.Stage and MFMailComposeViewController to play nicely together. So I’m thinking of popping my head out and offering my twopence to the community.
This could be a looooong post or a short one, depending on how deep you choose to go down the rabbit hole.
The workaround
For those of you who would rather cut to the chase, here is what worked for me.
There is a link to an example project at the end of the post, based on Piotr Kościerzyński‘s original project for in-app mail composer. Here is the summary in three steps:
- Subclass the native view controller in your native code (MFMailComposeViewController in my case) and override
[sourcecode language="objc"]<br />- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;<br />[/sourcecode]
so you can control how the native view orients itself.
- Add a category to UIViewController in your native code and implement these two methods:
[sourcecode language="objc"]<br />#import<br />@interface UIViewController (Orientation)<br /><%%KEEPWHITESPACE%%> - ( UIInterfaceOrientation ) _preferredInterfaceOrientationGivenCurrentOrientation : ( UIInterfaceOrientation ) interfaceOrientation;<br /><%%KEEPWHITESPACE%%> - (BOOL) _isSupportedInterfaceOrientation : ( UIInterfaceOrientation ) interfaceOrientation;<br />@end<br />[/sourcecode]
This will let you define the behaviour for most of your views, including the ones implemented in Actionscript.
- Add a listener for StageOrientationEvent.ORIENTATION_CHANGING in your Actionscript code and make sure you catch it at the capture phase with high priority. This will let you stop undue reorienting while your native view lives. Make sure you stop listening to the event or stop preventing it from causing reorientation afterwards.
[sourcecode language="actionscript3"]<br />stage.addEventListener( StageOrientationEvent.ORIENTATION_CHANGING, orientationChanging, true, 99 );<br />...<br />private function orientationChanging( _event : StageOrientationEvent ) : void<br />{<br /><%%KEEPWHITESPACE%%> if ( _event.cancelable )<br /><%%KEEPWHITESPACE%%> {<br /><%%KEEPWHITESPACE%%> _event.preventDefault();<br /><%%KEEPWHITESPACE%%> }<br />}<br />[/sourcecode]
Why workaround and not a solution?
Step 2 enforces the same orientation behaviour on all views in the application, so if you need some of your views to be able to orient themselves in certain ways and others – not, you might need a different approach.
Lenghty and potentially boring rant about how we got there
For you, kind reader, who wouldn’t mind lending me a sympathetic ear, this is my tale.
First of all, I would like to offer my thanks to Piotr Kościerzyński for his post iOS native extension for Adobe AIR. In-app mail composer and the example he provided. Although I have rewritten most of it to fit my needs, the code I am offering below is based on his example.
I was glad that someone somewhere had already blazed the way for us, when I found the example a month ago. It seemed a bit bizarre that the app would reorient itself after having shown the mail composer, but I didn’t think much of it at the time. It looked rather an innocent issue and I was certain it wouldn’t take long to fix, so I left it as a desert, to have a look at after everything else was ready for a release.
Little did I know that I would have to put my boxing gloves on for almost two weeks and quite a few rounds…
Round 1: stage.autoOrients, run-time
Don’t laugh. I was young and naive. I thought that if I disabled the auto-orientation of the Actionscript stage before I launched the mail composer and enabled it after it had gone, my problem would be solved.
No such luck. I noticed the app would actually start rotating while the mail composer was popping up. Spooky…
Adobe & Apple : me = 1 : 0
Round 2: stage.autoOrients, package-time
By package-time I mean the application descriptor in the Flex project: MyApp-app.xml:
[sourcecode language="xml"]<br />false<br />[/sourcecode]
Now, this was a bit silly, because we want our app to be able to orient itself in every way possible, but I was curious. Surely this should stop the app from rotating at all, even after I dismiss the mail client, right?
Wrong.
Apparently Apple’s stuff works its magic around this and we still get reoriented. And stay like this, until we show the mail client again.
Adobe & Apple : me = 2 : 0
Round 3: StageOrientationEvent.ORIENTATION_CHANGING
stage.autoOrients = false, in theory, stops any StageOrientationEvent being dispatched. On the other hand, if we want to allow auto orientation sometimes, but stop it at other times, listening to this event before orientation changes occur lets us do just that:
[sourcecode language="actionscript3"]<br />stage.addEventListener( StageOrientationEvent.ORIENTATION_CHANGING, orientationChanging );<br />[/sourcecode]
So I thought I’d stop the event from completing its mission while the mail composer lived:
[sourcecode language="actionscript3"]<br />private function orientationChanging( _event : StageOrientationEvent ) : void<br />{<br /><%%KEEPWHITESPACE%%> if ( _event.cancelable )<br /><%%KEEPWHITESPACE%%> {<br /><%%KEEPWHITESPACE%%> _event.preventDefault();<br /><%%KEEPWHITESPACE%%> }<br />}<br />[/sourcecode]
There were good news and bad news…
The good news: all of the StageOrientationEvent.ORIENTATION_CHANGING events I was intercepting were cancellable.
The bad news: the stage was still being oriented in a funny way after the mail composer was dismissed!
Adding another listener, this time for StageOrientationEvent.ORIENTATION_CHANGE showed me that a relentless ORIENTATION_CHANGE event was sent, informing me that the last orientation attempt succeeded, despite my kicking and screaming and trying to prevent it from happening.
Wonderful.
Adobe & Apple : me = 3 : 0
Round 4: set stage.orientation manually
I am Dyslexia of Borg. Resistance is futile. Your ass will be laminated.
If you are going to force an orientation on me, I’ll retaliate by setting the orientation back to what I need it to be. With my bare hands.
I learnt a couple of things during this round:
- don’t mess with stage.setOrientation
- don’t trust stage.deviceOrientation
I thought that, after we’ve been wrongly (do you hear the indignation?) reoriented, I’d check what orientation the device was in and quietly tell the stage to get itself in order, like Adobe kindly tell us we can do. Well, that kind of worked. Sometimes.
To be fair to Adobe, they do warn that stage.deviceOrientation can sometimes be unknown, for example, when first start the app (until we manually shake or rotate the device, I found) or when the device is lying flat.
But that was not my biggest problem. My sneakily setting the stage orientation usually paid off the first time I did it in any given device orientation. Once the mail composer had been dismissed however and that had done its dirty work, my stage ended up physically reorienting and/or resizing itself, but not knowing it. In other words, the stage.orientation property would politely report the last orientation I had manually set it to, although it was neither oriented, nor sized for what it said it was.
Adobe & Apple : me = 4 : 0
Round 5: override MFMailComposeViewController
I debug my code on an iPhone most of the time, so was for a while oblivious to the fact that on an iPad the mail composer itself would sometimes start in the wrong orientation too. That is, until my brother, who’s the iPad guy, became loud enough about it, so I couldn’t ignore it any more.
Thankfully, that was at least straightforward a fix, outlined in the Apple manual: Why won’t my UIViewController rotate with the device?
So, in the native code, I subclassed MFMailComposeViewController and added an override for
[sourcecode language="actionscript3"]<br />- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;<br />[/sourcecode]
which would return YES for any orientation.
I then saw that confirmed in Aral Balkan’s blog and, actually, in the comments in Piotr’s blog (and I thought I had read carefully the first few times, pah!)
The rotation after the mail composer gracefully left the stage (excuse the pun) still remained a problem, but hey:
Adobe & Apple : me = 4 : 1
Round 6: an attempt to get Flex and Cocoa to play together
Once I had crossed over to the Native side, I decided I may as well explore a bit.
The native code gets a non-native view controller to display the mail client’s view and that view controller, non-native though it might be, must implement an interface that the native can talk to:
[sourcecode language="actionscript3"]<br />[[[[UIApplication sharedApplication] keyWindow] rootViewController] presentModalViewController:mailComposer animated:YES];<br />[/sourcecode]
Now that rootViewController, which is a UIViewController I reckoned would control either my Actionscript spark.components.View or flash.display.Stage. I thought of asking it a few questions and called shouldAutorotateToInterfaceOrientation on it.
Turned out that our little rootViewController changes its mind about whether it shouldAutorotateToInterfaceOrientation, depending on the current orientation: it returns YES for everything else and NO for the orientation it is already in.
At this point it seemed like the dialogue between Apple’s and Adobe’s classes went like this:
Stage. Curtains rising. Orientation: UIInterfaceOrientationPortrait.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Apple: “State your preferred orientation. Do you support UIInterfaceOrientationPortrait?”
Adobe: “Well, I am already oriented in Portrait, so I see no reason to be reoriented to it again. So, NO.”
Apple: “Check again. shouldAutorotateToInterfaceOrientation( UIInterfaceOrientationPortrait )?”
Adobe: “No.”
Apple: “Well, this fella here is telling me we should be oriented UIInterfaceOrientationPortrait, but if you don’t support it… What do you support, then? shouldAutorotateToInterfaceOrientation( UIInterfaceOrientationLandscapeLeft )?”
Adobe: “Well, as a matter of fact, yes. But I don’t see why I should…”
Apple: “Too late. You have now been oriented to UIInterfaceOrientationLandscapeLeft. Resize your troops.”
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Spooky music. Curtains.
Seriously, I’m not making this up. It’s a transcript from a couple of stack traces of where the mail composer gets reoriented – I won’t bore you with the long one:
[sourcecode language="cpp"]<br />#0 0x008482be in -[MailCoposeViewControllerWrapper shouldAutorotateToInterfaceOrientation:]<br />#1 0x33cb1e30 in -[UINavigationController _isSupportedInterfaceOrientation:] ()<br />#2 0x33ce337e in -[UIViewController _preferredInterfaceOrientationGivenCurrentOrientation:] ()<br />#3 0x33d5105a in -[UIWindowController transition:fromViewController:toViewController:target:didEndSelector:] ()<br />#4 0x33d504ea in -[UIViewController presentViewController:withTransition:completion:] ()<br />#5 0x33dab82a in -[UIViewController presentModalViewController:animated:] ()<br />[/sourcecode]
And, as if I needed more proof, I noticed a grumpy comment in the XCode’s output window while debugging, which was a response to my stopping the ORIENTATION_CHANGING event in Round 3:
[sourcecode language="cpp"]<br />The view controller returned NO from -shouldAutorotateToInterfaceOrientation: for all interface orientations. It should support at least one orientation.[/sourcecode]
Just to make sure, I checked what rootViewController would say if I asked it what class it was and there I had it:
[sourcecode language="objc"](lldb) po [[[[UIApplication sharedApplication] keyWindow] rootViewController] class]<br />(id) $0 = 0x008e1dac CTStandaloneViewController[/sourcecode]
It looked like my rootViewController must be masquerading as CTStandaloneViewController, a descendant of UIViewController… So, if I could get this CTStandaloneViewController to answer nicely to shouldAutorotateToInterfaceOrientation, my problems would be solved!
I started reading about categories, extensions and swizzling… The last one seemed like it might cause more problems than it solved, namely a rejection from the App Store.
At this point I realised that I hadn’t been out of my dark cave for days, was out of tuna tins, in need of a hair cut and had messages on my phone from friends checking whether I was still alive. I put the phone aside with a grunt, promising to myself to respond to everyone later and continued to follow the lead on that CTStandaloneViewController guy.
He had left a fingerprint on my crime scene and I could put him there. My problem was that the XCode’s compiler, when dragged to the interrogation room, kept shaking its head and claiming that it had never seen, spoken to or even heard of any CTStandaloneViewController…
Adobe & Apple : me = 5 : 1
Round 7: tickle the stack trace
I had gone too far to give up at that point, so, just for the sake of it, I went a bit mad and messed with whatever calls seemed relatively safe on the stack traces I could see whenever the mail composer was asked about its orientation.
Added categories to UIViewController and UINavigationController, where I made implementations of most methods that had to do with orientation:
[sourcecode language="objc"]<br />UIViewController _preferredInterfaceOrientationGivenCurrentOrientation<br />UIViewController shouldAutorotateToInterfaceOrientation<br />UINavigationController _isSupportedInterfaceOrientation<br />[/sourcecode]
etc. etc.
Unsurprisingly,
[sourcecode language="objc"]<br />UIViewController shouldAutorotateToInterfaceOrientation<br />[/sourcecode]
and the like didn’t make much difference as far as my rootViewController was concerned, because its type, the infamous CTStandaloneViewController must be overriding these, rather than use the implementations in UIViewController. The methods starting with an underscore however (for ‘private’?), seemed to be a different story.
In the end, I got a combination of two of them that tamed my rootViewController:
[sourcecode language="objc"]_preferredInterfaceOrientationGivenCurrentOrientation[/sourcecode]
and
[sourcecode language="objc"]_isSupportedInterfaceOrientation[/sourcecode]
of UIViewController.
Got these to agree with whatever orientation was suggested and… look, ma, no reorientation!
Adobe & Apple : me = 5 : 2
Round 8: involuntary resizing?
But wait, that’s not all! Now, when I closed the mail composer, the stage would stay oriented the way I wanted it to, but it would occasionally resize itself, as if it had switched between Landscape and Portrait. Holly hedgehog!
Back in Actionscript code, I put a listener for my main view’s ResizeEvent.RESIZE and it lead me to this:
[sourcecode language="actionscript3"]Application.stage_orientationChangingHandler()[/sourcecode]
at the bottom of the call stack. And the following comment in the implementation of stage_orientationChangingHandler:
[sourcecode language="actionscript3"]<br />/**<br />* @private<br />* This is the event handler for the stage's orientationChanging event. It<br />* cancels the orientation animation and manually swaps the width and height<br />* of the application to allow the application to validate itself before<br />* the orientation change occurs. The orientaitonChanging is only listened<br />* for on iOS devices.<br />*/<br />[/sourcecode]
So even if we don’t want to reorient ourselves, we’ll be resized, should we smell any reorientation coming, just in case…
I’m really grateful that my brother and partner in crime pays attention to detail and tends to remember what he’s paid attention to in crucial moments. I knew I would be kicking myself even before I had heard the question, but I let him ask it anyway:
“So, what stage do you catch that ORIENTATION_CHANGING event in?”
Darn. I should have come up with this one. Anyway, setting my listener to get the event at the capture phase and putting its priority to something high seemed to do the job. Now I was catching the event before it went to the Application and could prevent the overzealous resizing:
[sourcecode language="actionscript3"]stage.addEventListener( StageOrientationEvent.ORIENTATION_CHANGING, orientationChanging, true, 99 );[/sourcecode]
Adobe & Apple : me = 5 : 3
Round 9: which version?
This is more of a way to mention a detail in passing, rather than a real round…
While I was messing around with the showing and dismissing of the mail composer, I noticed that there were a couple of versions of calls that do that job:
[sourcecode language="objc"]- (void)dismissModalViewControllerAnimated: (BOOL)animated;<br />- (void)presentModalViewController: (UIViewController *)modalViewController animated: (BOOL)animated;[/sourcecode]
and
[sourcecode language="objc"]- (void)presentViewController: (UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion<br />- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^)(void))completion[/sourcecode]
There is a warning in the Apple headers that the first set (with Modal in the name) will be deprecated. The newer versions however require iOS 5.0 or later and let you specify code to be executed when the view has finished showing or hiding, so you can better time whatever needs to be done at each event.
The comlpetion argument in the new versions calls for a code block in Objective-C and one needs to be careful what happens there, if communication with Actionscript is neccessary, as noted in this blog post. In my case an asynchronous message was all I needed, in order to notify Actionscript that the mail composer has been dismissed – have a look at the example code.
Adobe & Apple : me = I think this one should be a draw…
Final round: Workaround
So now you have it. You know why it’s a workaround, rather than a solution. Let me know, when you find a more civilised one. Because I know you will. I’m sure someone who knows their way round Objective-C better will find a way to get to my CTStandaloneViewController suspect.
That’s it from me. I think I’ll get out of the cave now. I hear rumours it’s spring out there…
Code
You can download the example code here:
It builds with Flex 4.6 (SDK 4.6), XCode 4.3.2 and has been tested on iOS 5.1 and iOS 4.3.3.
What’s in there and how to use it
- EmailExtension/ – contains the XCode project with native code and an empty app, set up to pack up and start the AIR application, so that it can be debugged in XCode, as per this very useful tutorial: Debugging Native Extensions for AIR iOS.The app contains almost no code. What is important in it is the script, which will execute when you run it. You will need to replace YourPasswordHere with the password for your provisioning profile and set provisioning_profile and developer_identity to your profile and identity file respectivelly. To do that, in XCode select the TestEmailApp target, go to the Build Phases tab and edit the Run Script:
- certificates/ – put your .p21 and .mobileprovision files here
- scripts/ – contains shell scripts for packaging the .ane (native extension) and .ipa (mobile application) – you’ll need to edit provisioning_profile and developer_identity to what yours are called
- FlexEmailLib/ – contains the bridge between the app and the native extension code
- FlexApp/ – the actual app project; if you want to package it in Flex, you’ll need to add the .ane to it manually in the project settings
Credits
- Piotr Kościerzyński for his original post iOS native extension for Adobe AIR. In-app mail composer
- Rajorshi Ghosh for his tutorial on Debugging Native Extensions for AIR iOS
- Richard Lord for his 20 tips for creating Air Native Extensions for iOS
- My brother, for paying attention to detail, however annoying it may be at the time. I forgive you.
- st_ada for supplying me with tinned tuna and a sympathetic ear.
Thank you for this, I ran into this last night with an ANE I am working on as well and after numerous hours of this I had to call it quits.
Only issue I am having after implementing your workaround is that I only want my app to orient in Landscape mode, and after closing the Native Extension, my app is now orienting to both portrait and landscape. The good news is that my app is at least resuming state in the AIR app in the correct orientation (landscape). Any ideas as to why it now orients in both portrait and landscape?
Thanks again.
Adam
I should probably also provide a link to how I was doing the desired behavior I described in my first entry prior to implementing the Native Extension.
http://esdot.ca/site/2011/creating-a-landscape-app-in-air-for-ios
This link provides an example of how I was only ever letting the device orient in landscape mode.
Hi Adam,
Do you allow only landscape orientations in the UIViewController functions?
I would do this (which you might have already done):
[sourcecode language=”objc”]
– ( UIInterfaceOrientation ) _preferredInterfaceOrientationGivenCurrentOrientation : ( UIInterfaceOrientation ) interfaceOrientation
{
switch ( interfaceOrientation )
{
case UIInterfaceOrientationPortrait:
case UIInterfaceOrientationPortraitUpsideDown:
{
return UIInterfaceOrientationLandscapeLeft;
}
default:
{
return interfaceOrientation;
}
}
}
– (BOOL) _isSupportedInterfaceOrientation : ( UIInterfaceOrientation ) interfaceOrientation
{
return ( UIInterfaceOrientationLandscapeLeft == interfaceOrientation ) || ( UIInterfaceOrientationLandscapeRight == interfaceOrientation );
}
[/sourcecode]
I was also going to suggest making sure that you stop listening to the StageOrientationEvent.ORIENTATION_CHANGING event after the mail composer’s gone, but from the link you have provided it looks like you rely on the event to keep the app in landscape, so that’s probably not an option.
Let me know if this doesn’t work for you.
Awesome!
The changes to the two Objective-C methods worked. Thanks again for the help, and for posting this extremely helpful workaround. Hopefully Adobe manages to fix this in the next release, if not I have a feeling this page will be getting some heavy traffic!
Adam
hi . I have got a problem. mail client opens fine but when I discard message or save it app is getting freeze… any ideas?
fixed that error. now build a release .a file without preprocessor macro variables and set shared libraries to NO and it is working now. but I have got another problem. when mail client is going to dismiss app to going to portrait mode… my app is in landscape mode and I overrided shouldautorotatetointerfaceorientation method so mail composer is in landscape mode but when pressind save, discard or send and composer going to dismiss then it dismisses in portrait mode and app going to portrait mode as well… any sugesstions?
thanks.
Hi Georgi,
Did you add implementations for UIViewController’s
_preferredInterfaceOrientationGivenCurrentOrientation() and _isSupportedInterfaceOrientation()?
These are what will affect the views in the Flex code.
Hope this works for you!
hi. thanks for reply. I made action script project but not flex. maybe that is cause. yes I implemented changes to that two functions. any ideas?
if you can time please look at source files. add also made flex project but still have issue. http://wall3ds.com/extension/source.zip
thanks.
it going to default orientation and you can’t do nothing after that.
Hi Georgi,
I’m having a look at your source files: there doesn’t seem to be anything obviously wrong, so I’d expect this to work for you. I assume you want to force landscape orientation, is that right?
I’d check a couple of things to narrow the problem down:
1. Are you able to debug the native code? (The TestEmailApp target should help with that.)
If you can debug it, put breakpoints in both functions in the UIViewController+Orientation.m file and also a breakpoint in shouldAutorotateToInterfaceOrientation() in MailComposeViewControllerWrapper.m to make sure that all of these get called.
2. In the Actionscript code check whether you stop listening to the StageOrientationEvent.ORIENTATION_CHANGING event when the mail composer gets dismissed.
hi Rad,
yeah I want to force landscape orientation. sorry I’m not good in objC so it is little hard to debug… I did’t listen now for StageOrientationEvent.ORIENTATION_CHANGING event. it is going to default mode after closing client… I’m using air 3.2 and flex 4.6 sdk.
on debug getting “cp: TestEmail.app.dSYM: No such file or directory” … any ideas what error is this? ipa file was extracting but getting this error…
Hi Georgi,
The .dSYM should be produced when you call adt to package the ipa file, so maybe something else was missing before it – a path or a password that the script was unhappy about?
(You are calling it with -target ipa-debug-interpreter, right?)
It might help if you run the scripts/package_ipa.sh sript on the command line and tweak it, until it works for you, then copy the changed script into XCode (into the Run script for the TestEmailApp target).
Both scripts are pretty much the same up to and including the bit where adt is called (the difference is that in the Run script you have to pass your password to adt with the -storepass argument).
Hi,
Can you please put ane file to test.
Thanks,
Kartik
Hi Kartik,
Added NativeEmailExtensionLib.ane in binaries/.
Cheers,
Radoslava
Hello Rad,
My application freezes when i tried to cancel draft. I read in previous post regarding this issue. Can you please let me know the ane you have added is updated as i am facing this issue.
Regards,
Kartik.
Hi Kartik,
I have just done a clean build here to see if I can reproduce the issue: there was a problem with the test app freezing before the e-mail client was shown. A look at the Flash debugger showed that I’d forgotten to check in the file that the app tries to attach.
I’ve now added the file and check whether it exists. There is also a freshly built .ane file.
I can’t reproduce a freeze after the mail client has shown up and has been dismissed, though. If you still experience this, have a look at Georgi Gevorgyan’s comments above – he seems to have run into this problem and fixed it.
Cheers,
Radoslava
Hello Radoslava,
Thanks for the reply. I will try and will update you the result.
Thanks,
Kartik.
Hello Rad,
Thanks for the file.
Regards,
Kartik.
Invalid ANE – Extention XML is not present or invalid
FB 4.6
Hi Astraport,
Is that an error message you are getting when packaging the .ipa?
Are you doing this on the command line or in Flash Builder 4.6? When you add the .ane to the project, does it show OK in the project properties – without warnings or errors next to it?
Is this the only .ane in your project or are you using it with other extensions?
Did you package the .ane yourself or are you using the one I’ve uploaded?
Cheers,
Radoslava
Hi Radoslava,
>Is that an error message you are getting when packaging the .ipa?
In both cases. And when I add ANE in the project properties and when testing in debug mode.
>Are you doing this on the command line or in Flash Builder 4.6?
Second.
>When you add the .ane to the project, does it show OK in the project properties – without warnings or errors next to it?
Not Ok, but errors next to it.
>Is this the only .ane in your project or are you using it with other extensions?
I tried different options. One result.
>Did you package the .ane yourself or are you using the one I’ve uploaded?
I get ready for use here http://code.google.com/p/diadraw-air-email-native-extension-example/source/browse/#hg%2Fbinaries
Hi Astraport,
I can’t seem to reproduce the problem.
Can you try packaging the .ane on the command line (or building it from scratch) on your machine and see whether the problem persists?
You can use the package_ane.sh script in http://code.google.com/p/diadraw-air-email-native-extension-example/source/browse/#hg%2Fscripts.
On the other hand, if you need this to work around the orientation issue, you can switch to AIR 3.3 – it’s out now and the problem has been fixed there. Thanks, Adobe!
Radoslava
Hi,
Is the attachment string includng pipers still the same as the one Piotr? I can attach a jpg to the email, but the file name I’m sending (at the end) isn’t used and the mime type is set incorrectly. Thanks!
[“pattern.jpg|native|image/jpeg|pattern.jpg”]
Hi Sander,
The string looks like the format that Piotr’s example expects.
Our ANE takes a simpler one and does less parsing: it takes the full path to the file, then the mime type, then the file name, so you don’t need the “native” bit:
[fullPathToPattern.jpg|image/jpeg|pattern.jpg”]
Have a look at the test app for a fuller example.
Hope this works for you,
Radoslava
Nice job. Thanks.
I tried using HTML in the body – doesn’t work like the Piotr exmaple seems to.
Anybody tried HTML in the body?
Thank Chuck
Hi Chuck,
I’ve turned HTML off in the native code.
If you build the .a and the ANE yourself, change this line:
[ mailComposer setMessageBody : messageBody isHTML : NO ];
in MailComposerDelegate.m
Alternatively, I can change it so that isHTML is passed in as a parameter from AIR instead.
Cheers,
Radoslava
Thx for the Ane fix.
Works great… except the NO EVENTS are dispatched (not a single one).
Can do without events… but maybe i just missed something.
Everything wrks fine, mail and attachment are sent, any idea ?
Using CS6, iPhoneSDK5.1, AirSDK3.3.
Heres my code snip, maybe i did something wrong.
var nmw:NativeMailWrapper = new NativeMailWrapper();
nmw.addEventListener(MailExtensionEvent.MAIL_COMPOSER_DISMISSED, handleMailExtensionEvent);
nmw.addEventListener(MailExtensionEvent.MAIL_COMPOSER_EVENT, handleMailExtensionEvent);
nmw.addEventListener(MailExtensionEvent.MAIL_COMPOSER_NOT_AVAILABLE, handleMailExtensionEvent);
nmw.addEventListener(MailExtensionEvent.MAIL_RESULT_CANCELED, handleMailExtensionEvent);
nmw.addEventListener(MailExtensionEvent.MAIL_RESULT_FAILED, handleMailExtensionEvent);
nmw.addEventListener(MailExtensionEvent.MAIL_RESULT_SAVED, handleMailExtensionEvent);
nmw.addEventListener(MailExtensionEvent.MAIL_RESULT_SENT, handleMailExtensionEvent);
nmw.addEventListener(MailExtensionEvent.MAIL_RESULT_UNKNOWN, handleMailExtensionEvent);
nmw.addEventListener(MailExtensionEvent.WILL_HIDE_MAIL_COMPOSER, handleMailExtensionEvent);
nmw.addEventListener(MailExtensionEvent.WILL_SHOW_MAIL_COMPOSER, handleMailExtensionEvent);
private function handleMailExtensionEvent(e:MailExtensionEvent):void
{
trace(” handleMailExtensionEvent: ” + e);
}
nmw.sendMail(“stuf here”, “more there”..,. ,.., [attachmentstuff]);
Hi Dave,
Sorry about the delay in responding!
I had a look at the problem and it turned out to be caused by our native code not holding on for long enough to the ExtensionContext instance.
This has now been fixed and checked in, along with other updates that made the extension usable with Adobe AIR 3.4 and iOS 6.0.
There is now a new blog post, summarising what’s new: http://blog.diadraw.com/e-mail-native-extension-updated-for-adobe-air-3-4-and-ios-6-0/
With that said, there is another side to your question: most of the constants in MailExtensionEvent are actually used as ‘event level’ information (stored in MailExtensionEvent.composeResult), rather than as ‘event type’. This wasn’t very obvious in the code – I’ve now added a comment to help clarify it.
So all you need to listen for is MAIL_COMPOSER_EVENT and then check the event’s composeResult field in the event listener function.
There is an example of that in the handleMailComposerEvent() function in FlexApp/src/views/TestEmailAppHomeView.mxml.
Hope this helps. Thanks for reporting this bug!
Radoslava