In this lab, you will create a Android app using the Xamarin support in Visual Studio. You will also go through the process of adding a Connected Service so that you can program your app using the Office 365 APIs.
- You must have an Office 365 tenant and Windows Azure subscription to complete this lab. If you do not have one, the lab for O3651-7 Setting up your Developer environment in Office 365 shows you how to obtain a trial. You must also have access to an Exchange inbox within an Office 365 developer tenancy.
- You must have Visual Studio 2013 installed with Update 3.
- You must have the Office 365 API Tools version 1.1.728 installed in Visual Studio 2013.
- You must have installed Xamarin using a valid subscription or using a free trial: https://xamarin.com/download.
- You must configure an Android emulator for debugging that runs at Android API Level 19.
- Using the browser, navigate to https://outlook.office365.com/owa and log into your OWA mailbox.
- In the top navigation bar, click the People link to navigate to the page which shows you your contacts.
- Make sure there are a few contacts for testing. If you have no contacts or less then 10 contacts, use OWA to enter a few sample contacts so you have at least 10.
- Once you have verified that you have a set of contacts for testing, you can move on to the next exercise where you will create and test your first app that programs against this contacts list.
In this exercise, you will create a new Visual Studio project for a Xamarin app.
-
Launch Visual Studio 2013 as administrator.
-
In Visual Studio select File/New/Project.
-
In the New Project dialog, select Templates > Visual C# > Android and click Blank App (Android). Name the project XamarinLab and click OK.
-
Inspect the high-level structure of the new project that has just been created. Note that the source file at the root of the project named MainActivity.cs contains the code which initializes the app's user interface. You should also understand that the source file in the Resources/layouts folder named Main.axml provides a layout of controls that is used by the app's user interface.
-
Right-click on the XamarinLab project and select Properties to display the project property dialog. On the Application tab, you should see that are three settings named (1) Compile using Android version, (2) Minimum Android to target, and (3) Target Android version. Configure each of these three settings with a value of API Level 19 (Xamarin.Android v4.4 support).
-
Navigate to the Android Manifest tab and update the Application name from XamarinLab to Xamarin Lab.
-
Navigate to the Android Option tab and take a quick look at the default settings. There is no need to actually change anything.
-
Save your changes and close the project properties dialog.
-
Locate the Android layout file named Main.axml in the Resources/layouts folder.
-
Double-click on Main.axml to open it in the Xamarin Android layout designer.
-
Select the button in the layout designer and then display the Visual Studio property sheet so you can view the button's properties. using the property sheet, update the id property of the button to @+id/cmdGetContacts and also update the text property to Get Contacts as shown in the following screenshot.
-
Press the {F5} key to begin a debugging session. The app should take a bit to start but then it should begin to run in the Ripple Android emulator which runs inside the Chrome browser.
-
Click the Get Contacts button and make sure you see the "hello world" message.
-
Switch over to code view in the Android layout designer. The final AXML code that has been generated should match the AXML in the following code listing.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:id="@+id/cmdGetContacts" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Get Contacts" /> <TextView android:text="Hello World!" android:textAppearance="?android:attr/textAppearanceLarge" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/txtStatus" /> </LinearLayout>
-
Save and close Main.axml.
-
Open MainActivity.cs on a code editor and take note that the MainActivty class is defined with the Activity attribute. Update the Label parameter of the Activity attribute from XamarinLab to Xamarin Lab.
-
Update the code in MainActivity class to match the following code listing.
using System; using Android.App; using Android.Content; using Android.Runtime; using Android.Views; using Android.Widget; using Android.OS; namespace XamarinLab { [Activity(Label = "Xamarin Lab", MainLauncher = true, Icon = "@drawable/icon")] public class MainActivity : Activity { protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); SetContentView(Resource.Layout.Main); Button button = FindViewById<Button>(Resource.Id.cmdGetContacts); button.Click += delegate { // add event handler code for button TextView status = FindViewById<TextView>(Resource.Id.txtStatus); status.Text = "Hello from C#!"; }; } } }
-
Now it's time to test out your work. Press {F5} to start a debugging session with the Android emulator. After a bit, you should be able to see the app running in Android emulator. You should see the Hello World message on the screen.
-
When you click the Get Contacts button you should see the message Hello from C#.
-
Close the Android emulator, return to Visual Studio and make sure the debugging session has been terminated.
In this exercise, you will work with the Activity-based UI model that is the foundation of Android development platform. More specifically, you will create a new adapter class which uses an Android layout as an item template. You will then use this item template to display a collection of contact items.
-
In the Solution Explorer, expand the project node to show Resources/layouts.
-
Right-click and the layouts node and select Add > New Item. In the Add New Item dialog, select the Android Layout item template and give it a name of ContactListItem.axml. Click OK to add the new layout into the layouts folder.
-
In the Android layout designer for ContactListItem.axml, switch to code view and copy and paste the XAML code below to create the new layout.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="?android:attr/listPreferredItemHeight" android:padding="6dip"> <TextView android:id="@+id/ContactName" android:textAppearance="?android:attr/textAppearanceLarge" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_toRightOf="@id/ContactPicture" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_above="@id/ContactEmail" android:layout_alignWithParentIfMissing="true" android:gravity="center_vertical" /> <TextView android:id="@+id/ContactEmail" android:layout_width="fill_parent" android:layout_height="26dip" android:layout_toRightOf="@id/ContactPicture" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:singleLine="true" android:ellipsize="marquee" /> </RelativeLayout>
-
Save and close the Android layout ContactListItem.axml.
-
In the Solution Explorer, create a new top-level folder named Model.
-
Right-click the Model folder and add a class named MyContacts.
-
Implement the MyContacts class using the class definition shown in the following code listing.
namespace XamarinLab.Model { class MyContact { public string Id { get; set; } public string Name { get; set; } public string Email { get; set; } } }
-
Right-click the Model folder and add a second class named MyContactsAdapter.
-
Copy-and-paste the following code listing into MyContactsAdapter.cs to provide the boilerplate starting point for an Android adapter class.
public class MyContactsAdapter : ArrayAdapter<MyContact> { public MyContactsAdapter(Activity activity, List<MyContact> myContacts) : base(activity, Resource.Layout.ContactListItem, myContacts) { } public override View GetView(int position, View contactItemView, ViewGroup parent) { } }
-
Implement the GetView function using the following implementation.
public override View GetView(int position, View contactItemView, ViewGroup parent) { MyContact myContactItem = this.GetItem(position); if (contactItemView == null) { contactItemView = LayoutInflater.FromContext(this.Context) .Inflate(Resource.Layout.ContactListItem, parent, false); } var contactNameElement = contactItemView.FindViewById<TextView>(Resource.Id.ContactName); contactNameElement.Text = myContactItem.Name; var contactEmailElement = contactItemView.FindViewById<TextView>(Resource.Id.ContactEmail); contactEmailElement.Text = myContactItem.Email; return contactItemView; }
-
Save and close MyContactsAdapter.cs.
-
Open the Android layout named Main.axml and switch over to code view. Replace the existing AXML code with the code listing below in order to add a ListView control named ContactsListView.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:id="@+id/cmdGetContacts" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Get Contacts" /> <ListView android:id="@+id/ContactsListView" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout>
-
Save and close Main.axml.
-
Open MainActivity.cs in a code editor window.
-
Add the following import statements at the top of MainActivity.cs.
using System.Collections.Generic; using XamarinLab.Model;
-
Replace the existing class definition with the following code listing.
namespace XamarinLab { [Activity(Label = "Xamarin Lab", MainLauncher = true, Icon = "@drawable/icon")] public class MainActivity : Activity { ListView contactsListView; List<MyContact> myContacts = new List<MyContact>(); MyContactsAdapter myContactsAdapter; protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); SetContentView(Resource.Layout.Main); contactsListView = FindViewById<ListView>(Resource.Id.ContactsListView); myContactsAdapter = new MyContactsAdapter(this, myContacts); contactsListView.Adapter = myContactsAdapter; Button button = FindViewById<Button>(Resource.Id.cmdGetContacts); button.Click += delegate { // add event handler code for button myContacts.Clear(); myContacts.Add(new MyContact { Name = "Mike Fitzmaurice", Email = "Mike@fitz.net" }); myContacts.Add(new MyContact { Name = "Chris Sells", Email = "chris@sellsbrothers.com" }); myContacts.Add(new MyContact { Name = "Brian Cox", Email = "bc@adventureworks.com" }); myContactsAdapter.AddAll(myContacts); myContactsAdapter.NotifyDataSetChanged(); }; } } }
-
Test out your work by pressing {F5} and starting a debugging session with the Android emulator. You should be able to click the Get Contacts button and see the three sample contacts that were added to the adapter in MainActivity.cs.
-
Close the Android emulator, return to Visual Studio and make sure the debugging session has been terminated.
In this exercise, you will add a Connected Service to the project in order to program against the Office 365 APIs.
- In the Solution Explorer, right click the XamarinLab project and select Add/Connected Service.
- In the Services Manager dialog, click Register Your App.
- When prompted, login with your Organizational Account. After you have logged in, you should be able to see services for which you can configure permission requests.
- Select Contacts and then click Permissions.
- Check both check boxes and then click Apply.
- Click OK to save your changes and dismiss the Services Manager dialog.
- Inspect the Office 365 API assembly references that were automatically been added to your project when you added the Connected Service.
- You will also notice a C# file named ContactsApiSample.cs has been added to your project. Open that file and inspect the C# code inside to get an idea of how to program against the Office 365 APIs to authenticate and retrieve Office 365 contacts.
- When you are done, close ContactsApiSample.cs and move on to the next exercise.
In this final exercise, you will make use of the Connected Service you added in the previous exercise by writing code against the .NET libraries of the Office 365 APIs.
-
In Solution Explorer, right-click on the XamarinLab project node and click Add > Class. Name the new class Office365Service and click OK.
-
Copy-and-paste the following code listing to provide the impelementation for the Office365Service class.
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Android.Content; using Microsoft.Office365.OAuth; using Microsoft.Office365.Exchange; using XamarinLab.Model; namespace XamarinLab { public static class Office365Service { static ExchangeClient exchangeClient; static string userId; const string ExchangeResourceId = "https://outlook.office365.com"; const string ExchangeServiceRoot = "https://outlook.office365.com/ews/odata"; public static async Task EnsureClientCreated(Context context) { Authenticator authenticator = new Authenticator(context); var authInfo = await authenticator.AuthenticateAsync(ExchangeResourceId); userId = authInfo.IdToken.UPN; exchangeClient = new ExchangeClient(new Uri(ExchangeServiceRoot), authInfo.GetAccessToken); } public static void SignOut(Context context) { new Authenticator(context).ClearCache(); } public static async Task<IEnumerable<IContact>> GetContacts() { var contactsResults = await exchangeClient.Me.Contacts.OrderBy(c => c.Surname).ExecuteAsync(); return contactsResults.CurrentPage; } public static async Task<IContact> GetContact(string contactId) { var contact = await exchangeClient.Me.Contacts.Where(c => c.Id == contactId).ExecuteSingleAsync(); return contact; } public static async Task<List<MyContact>> GetMyContacts() { List<MyContact> contactItems = new List<MyContact>(); var contacts = await GetContacts(); if (contacts != null) { foreach (var contact in contacts) { contactItems.Add(new MyContact() { Id = contact.Id, Name = contact.DisplayName, Email = contact.EmailAddress1 }); } } return contactItems; } } }
-
Return to the code editor window for MainActivity.cs. Modify the code which registers the delegate as the button's event handler by adding the async keyword just before the delegate keyword.
button.Click += async delegate { // event handler code }
-
Replace the existing event handler code using the code shown in the following listing.
Button button = FindViewById<Button>(Resource.Id.cmdGetContacts); button.Click += async delegate { // add event handler code for button await Office365Service.EnsureClientCreated(this); myContacts = await Office365Service.GetMyContacts(); myContactsAdapter.AddAll(myContacts); myContactsAdapter.NotifyDataSetChanged(); };
-
Now it's time to test your work by pressing the {F5} key to start a debugging session in the Android emulator. Wait until the app has initialized and then click the Get Contacts button. After a few second, you should be prompted to sign into Office 365 with your organization account credentials.
-
Once you have signed in using your credentials, you should be prompted with a page that shows you the requested permissions and asks you to confirm that you trust the app. Click OK to continue.
-
At this point, you should see a set of contacts from Office 365 account. Congratulations! You have completed a simple hybrid app project using Xamarin and the Office 365 APIs.