Monday, 13 April 2015

Send email from iOS and Android via Xamarin Forms

Email service with default email composer
Send email from Xamarin Forms requires different implementation for iOS and Android. The default behaviour of using the default email service from each platform will populate a composer, which is visiable to the end user with the option to see, send, cancel, etc.

Concepts:  iOS

Compoment: MFMailComposeViewController
Present MFMailComposeViewController
In order to use the above iOS component as a dependency service, it is required to have a statement to present the view controller explicitly in your code. In this case, we use:
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(mailer, true, null)


Dismiss MFMailComposeViewController
When finished sending the email, it is required to dismiss the view controller manually. The DismissViewController has to be inside the MainThread of iOS.
mailer.Finished += (s,e)=>{
    UIApplication.ShareApplication.InvokeMainThread(()=>{
        ((MFMailComposeViewController)s).DismissViewController(true,()=>{});
    });
}


Set Mime Type for an attachment
It is important to provide the right "Mime Type" to the attachment you plan to add to your email.

Concepts: Android

Intent:  Intent.ActionSend  (Not "Intent.ActionSendTo" ,  using this will cause some error when sending email to exchange or google)
Intent type: "message/rfc822"  (follow the receipe from Xamarin website: http://developer.xamarin.com/recipes/android/networking/email/send_an_email/)

Present Composer
Setting the Intent’s mime type to message/rfc822 causes the mail application to launch. If multiple applications are capable of handling mail, the user will get a list to choose from.
Note: user can choose, sending out a message via gmail, exchange, skype, hangout. whatsapp, etc.

File object:
With the given file path of the attachment, you still need the Java object to form the file object. But, use Android.Net.Uri.FromFile to form the uri to the file.
var file = new Java.IO.File(attachmentPath);
Use intent.PutExtra(Intent.ExtraStream, Android.Net.Uri.FromFile(file)


Start Android Activity:

It is important to start the Android activity via the right context.
In Xamarin Forms, we use: 
Forms.Context.StartActivity(intent)
//Not: this.Context.StartActivity(intent)



It is important to set "setReadable()" after obtaining a file object in Android.

Without this line, you would't get the attachment even though you can see the attachment appear in the email composer.
file.SetReadable(true, false)

Usage:
//Example in Xamarin.Forms 
var mailService = DependencyService.Get<IEmailService>(); 
if (mailService.CanSend){
    mailService.ShowDraft("Subject","Body",false, "receipient email address", "path to the attachment");
}else{
    //Please activate or setup your email account from your device settings.
}

Alternative approach:

MAILTO 
string strMailTo = @"mailto:jeff.wei-lim@artesiansolutions.com?Subject=test&Body=testBody";
Device.OpenUri(new Uri(strMailTo));

Note for using MailTo:
  1. user can choose, sending out a message via email client only (such as email app or gmail...)
  2. Unable to send an email with attachment.

Tuesday, 7 April 2015

TeamCity with Xamarin Form

This is my second time setting up the end-to-end continuously integration(CI) /build for mobile application development. The 1st project was purely an end-to-end process for iOS project, with TestFlightApp. This time, I have extended my previous experience to both iOS  and Android projects. 

This page contain information about entities that involved using SVN, TeamCity to compile mobile applications written in Xamarin Forms, and build the projects from the build agent, and finally submit them to TestFairy (No more TestFlight).
It is a complete end-to-end continuously process with the facilities to dispatch to app to the end user or tester automatically. See the diagram below: 

So, what it does? 

  • Developers - commit changes to SVN via the SVN Client installed in Xamarin Studio.
  • Trigger - used to add builds to the queue when an event occurs (like commit a file)
  • Transfer - transfer file from SVN to Build Agent (setup mac mini as a build agent to TeamCity).
  • Major Build Steps:
    • 'mdtool' on Xamarin PCL shared project
    • 'mdtool' on iOS app
    • 'xbuild' on Android app
  • Custom script for publishing
    • Publish iOS app to TestFairy
    • Publish Android app to TestFairy
  • Test fairy send out invitation email



Example Command:
Command Line to build iOS project:
/Applications/Xamarin\ Studio.app/Contents/MacOS/mdtool -v build --project:YouiOSProject.iOS --configuration:"Ad-Hoc|iPhone" YourSolution.sln;


Command Line to build Android project:
Signed: 
xbuild /t:SignAndroidPackage /p:Configuration=release Droid/YourDroidProject.csproj

xbuild /t:SignAndroidPackage /p:Configuration=release %teamcity.build.checkoutDir%/Droid/YouDroidProject.csproj

Unsigned:
xbuild /t:PackageForAndroid /p:Configuration=release Droid/YourDroidProject.csproj


Publish YouriOSProject.iOS to TestFairy:
If you need dSYM, then you need to zip it:

zip -r %teamcity.build.checkoutDir%/Pro/build/iOS/iPhone/Ad-Hoc/YouriOSProject.app.dSYM.zip %teamcity.build.checkoutDir%/Pro/build/iOS/iPhone/Ad-Hoc/YouriOSProject.app.dSYM

curl -s http://app.testfairy.com/api/upload -F api_key='xxxxxxxxxxxxxxxxxxxx' -F file=@%teamcity.build.checkoutDir%/Pro/build/iOS/iPhone/Ad-Hoc/YouriOSProject.ipa -F symbols_file=@%teamcity.build.checkoutDir%/Pro/build/iOS/iPhone/Ad-Hoc/YouriOSProject.app.dSYM.zip -F testers_groups='TesterGroupInTestFairy' -F comment=‘Hello Built from TeamCity. %env.TEAMCITY_BUILDCONF_NAME% build#: %changesComment%’

Publish YourAndroidProject.Android to TestFairy
curl -s http://app.testfairy.com/api/upload -F api_key='xxxxxxxxxxxxxxxxxxxxx' -F file=@%teamcity.build.checkoutDir%/Pro/build/Droid/Release/YourDroidProject.pro-Signed.apk -F testers_groups='TesterGroupInTestFairy' -F comment=‘Your Droid Project;Built from TeamCity. %env.TEAMCITY_BUILDCONF_NAME% build#: %changesComment%’


SigningSigning is the most tricky thing for mobile application. For instance, you need to create a specific provisioning profile for iOS project; specific target for Android, etc. Well, I will focusing on some concerns of signing Android application here.

AndroidIn order to run on an Android device, packages must be signed. In order to allow quicker build iteration, the Xamarin.Android tasks do not sign packages during the build process, because signing is quite slow. Instead, they are signed (if necessary) before installation or during export, by the IDE or the Install build target. Invoking the SignAndroidPackage target will produce a package with the "- Signed.apk" suffix in the output directory. 

Tuesday, 16 December 2014

TestFlight Beta Testing

Just done my first try on distributing app to our tester via the new TestFlight Beta Testing.
Thought I will encounter a lot of issues after reading so many articles and feedback about the challenge of using it. However, everything went smooth on my first attempt.

So, I've setup 2 set of TestFlight now. I use the new one  "beta testing (pre-release)" for our internal tester , a step before we submit it to AppStore. And, the old one for our normal building and testing process.

Personally, I enjoyed using it. Here are the advantages I gained:
1. It is easier to ask for tester's Apple ID instead of UDID.
2. It is easy to manage, invite and toggling the testing mode between ON / OFF.
3. Smooth deployment in the way of the flexibility of picking a build version from the pre-release to become the final one to AppStore.


So, what I have done?

First of all, read through what is TestFlight Beta Testing about: https://developer.apple.com/testflight/

Especially the link to TestFlight video tutorial. It does give you a quick understanding about how TestFlight Beta Testing work and the benefits of using it.

Next, look at the iTune Connect Developer Guide (The linked show in the above url).  Particularly on 'The steps to setup prerelease versions of your app for testing in iTunes Connect.'.

However,......
There are number of stuffs or doubts you need to resolve first:
1) The step about generate profile that contain beta entitlement:
  • Generate a new App Store Distribution profile containing the beta entitlement to distribute builds via TestFlight.
Bunches and bunches of question around how to create profile that contain beta entitlement can be found from number of forums. Some people even work out a solution by editing the entitlement.plist file manually. Change the XML and make the beta testing work. Well, the trick is:

See the note here:
Important:  In order to use iTunes Connect for TestFlight beta testing, you must submit your app using the latest App Store Distribution profiles that contain the beta entitlement. 

The keyword is 'Latest!!!!'. Instead of doing any changes on the entitlement.plist or reuse your existing AppStore profile, create a new AppStore profile via iTunes Connect now.  The latest profile will include the BIT to turn on the TestFlight Beta Testing for you automatically.  1st doubts solved!

Don't forget to sign your app again with the new profile.

2) What do you need from the Tester? 
Well, I was doubts about whether I need the UDID anymore when I started using TestFlight Beta Testing. The answer is NO. The new TestFlight Beta Testing does not require any UDID from the tester, which has really benefit me from spending extra hour to instruct tester on how to get the UDID. Instead, just APPLE ID, that's all. 

Some common case of setting up a tester:

1. Error message in iTunes Connect User: 
"The email address you entered already belongs to an iTunes Connect account. To continue, enter a different email address."

This was really another painful stuff when you try to add a tester who already belongs to another iTunes connect team.  To overcome it, add a plus sign as a suffix after email name before the @ sign will solve the problem. For instance, this is my apple ID:   jeff@gmail.com, somehow this apple ID has been used in another iTunes Connect Team. In order to make sure Jeff can receive the invitation in his gmail account, enter the email address as jeff+@gmail.com

As a result, an email will be sent from iTune Connect to jeff@gmail.com


2. Continue the above issue: 
Once jeff received the email,  Jeff can follow the instruction from the email and continue login using jeff@gmail.com.   No changes are required. No need to change the Apple ID in your device to jeff+@gmail.com. 

3. Beta testing - No invitation being sent out at all? 
I think there is a bug on the TestFlight Beta Testing website. Basically, I didn't receive any email after a clicked on the invite button. But, switch off and on and beta testing switch again will solve the problem.


Some common cases and questions from the tester 

1. Error message from clicking the link from the invitation email:
"You aren't currently testing any apps. To accept an invitation, please click on the link...".

This is because the testers were reading the email from OUTSIDE the default email client in the device. For instance, your apple id:  xzy@gmail.com.  And, you have gmail app installed in your iPhone. It is very common that you will use gmail app to read the email. If you do that, then you will hit the above error message. 

To overcome it, forward the invitation email to the default email account set in iPhone's email client. Click the link again.   Problem solved!

2. Error / Alert in TestFlight APP (new app that need iOS 8):
"Redownload unavailable with this Apple ID - this redownload is not available for this Apple ID either because it was bought by a different user or the item was refunded or cancelled.".

OK, the above error is nothing to do with your App. The cause was something with the user's apple id in his/her device. 
In order to resolve it, there are 2 things to try out:

  1. Try download other app from AppStore. Just to confirm the tester's Apple ID is working.
  2. Please logout and login using the same Apple ID again. (Goto device settings --> iTune & AppStore --> Logout). Usually, this will solve the issue. 


Wednesday, 19 March 2014

SignalR - Create 'Real-Time' web functionality to your ASP.NET application now!

Try to make a chat program? Poll the message very 5 seconds? refresh or reload the web page using complicated javascript?

I've been spending time to create a chatroom on classic ASP (12 years ago). Refresh client side to get the latest data from other client via a service side script is really a pain. However, it hasn't been easy in ASP.NET, because there hasn't been a decent abstractions for this on server or a client library to talk to.

SignalR - an asynchronous signalling library for ASP.NET that help build real-time multi-user web application!

It is really a MAGIC ! Something you must try and experience it.

Here is the min req:
.Net framework 4.5

If you are using VS2012,  you can install the Microsoft ASP.NET SignalR from NuGet. (There is another one called "Microsoft ASP.NET SignalR System.Web" , I haven't try this yet. Not quite sure what are the differences.)

There are number of tutorial available from Mircosoft asp.net website:
http://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/tutorial-getting-started-with-signalr-20

Cool !

Friday, 30 August 2013

英国知多少?

英国 Q & A
问:我需要带电脑去吗?
答:旅行有tablet 当然最好。可以为明天的旅程做好准备。网上看地图,地铁,都很方便。

问:上网方便吗?
答:若用手机上网,可以到电话公司(vodanfone, O2, car phone, etc) 购买 ‘data plan' 的sim card. 电脑上网,可以到有免费wifi
的cafe 去。

问:free wifi 是真的免费吗?
答:在很多cafe 或 McD 都有free wifi。但是这都是 secured wifi。意识说,你还是需要密码才可以使用免费wifi。所以你必须是他们的顾客,方可索取密码。

问:容易找到复印机或photostate 文件吗?
答:比起大马, 1:50 ,非常难找。 别想翻版书本。一般上图书馆里会有。当然不是免费。

问:我喜欢打篮球
答:篮球场不多,而且都被踢足球的给占了。

问:我喝不惯牛奶,喜欢喝豆浆。
答:可以在超市 (tesco) 找到进口的罐装豆浆。

问:中餐馆好吃吗?
答:还可以。大多数是煮给‘鬼’吃。咖喱可以是甜而不辣。

问:发烧感冒咳嗽如何是好?
答:看医生,医生问你一两句后,就踢你回去,简直是浪费时间。一般都是自行到 farmacy (boots) 买药。

问:英国有种族歧视吗?
答:法律不允许。虽然如此, 到时你还是会感应到。

问:英国圣诞节热闹吗?
答:死城。

问:英国天气好吗?
答:一年下两次雨,一次四个月,一次八个月。哈哈!基本上除了短短的夏天,最好有件风衣/雨衣防身。

问:英国有高楼大厦吗?
答:少。

问:英国人一日三餐吃什么?
答:英国人吃很多面包和土豆,加奶的红茶,煎蛋、炒蛋、煮荷包蛋或白煮蛋(配吐司吃),三明治, baguette, panini, 香肠 等等。

问:英国的甜品好吃吗?
答:非常甜。

问:有机会看到皇室吗?
答:电视。或者去buckingham palace 碰碰运气吧。

问:英国有夜生活吗?
答:酒吧,没了。晚上没有 pasar malam. 没有mamak档。

问:英国有盗版软件/游戏吗?
答:你会很想念 imbi, lowyat plaza.

问:英国同性恋多吗?
答:如果你是,你不会寂寞的。

问:英国电视好看吗?
答:一共五个台,较教育兴。没得看英超,除非你有sky (像Astro) 另收费。不过,如果安装 freeview or freesat, 那么就有额外百多两百电台可以收看。

问:WeChat 微信流行吗?
答:大多数人用 whatsapp.

问:英国人数学好吗?
答:买东西,找钱时,记得要在他面前数一数。有时会少一两英镑!不晓得是不是故意的。

问:英国是岛国,海鲜很好吗?
答:不是每个超市都有鱼卖。

问:博物馆值得去吗?
答:免费,而且非常值得参观。London National Gallerry, British Musuem, Naturual History Musuem 都很不错。

问:英国水果蔬菜种类多吗?
答:用不到脚趾

问:剑桥和牛津哪个好?
答:本土人说剑桥要聪明的,牛津要成绩好的。一般来说,牛津比较出名于文学,音乐,戏剧等。

问:我的电器在英国可以用吗?
答:英国的标准电源是220/240伏特,插头是方行3插。在大马用的都可以在英国用。

问:我要看卫兵换岗?
答:可以到Buckingham Palace or Windsor Castle。但是,最好是先检查换岗日期及时间。在白金汉宫 (Buckingham Palace), 11:13便开始。
http://www.royal.gov.uk/RoyalEventsandCeremonies/ChangingtheGuard/Overview.aspx

问:那里可以买到价格便宜,而且品质还不错的衣服,裤子,。。。
答:Primark, Next

How to run unit test for your Xamarin Application in AppCenter?

How to run unit test for your Xamarin application in AppCenter?  When we talk about Building and Distributing your Xamarin app, you m...