共用方式為


Create a Cordova App using O365 Outlook Services and Ionic

在此教學課程中,您將了解如何使用 O365 Outlook 服務和 Ionic 架構建立郵件、行事曆和聯絡人用戶端。 此應用程式可讓使用者透過 O365 Outlook 服務 API 存取他們的郵件、行事曆和連絡人。 這個範例使用 JavaScript 程式碼,但您也可以使用 TypeScript 撰寫 Cordova 應用程式。

在本教學課程中,您將遵循下列步驟:

  1. 建立專案

  2. 在專案中加入 Ionic 架構

  3. 在專案中加入 NProgress

  4. 在應用程式中加入 O365 服務

  5. 為 O365 郵件、行事曆和連絡人租用戶設定權限,以授與適當的應用程式存取權

  6. 使用 Ionic 控制項建立應用程式資料夾結構、UI 路由以及版面配置

  7. 使用 AngularJS factory 取得存取權杖和 Outlook 服務用戶端

  8. 使用 O365 API 擷取 Outlook 服務資料:

    • 在郵件應用程式中,將郵件標示為重要、未讀郵件和所有郵件

    • 在行事曆應用程式中,擷取今天的會議 (事件開始日期等於今天)、明天的會議 (事件開始日期等於明天),以及開始日期大於或等於今天的所有事件

    • 在連絡人應用程式中,取得所有連絡人

  9. 使用 O365 API 建立及刪除資料:

    • 刪除郵件、行事曆事件

    • 建立新的行事曆事件和聯絡人

  10. 執行應用程式

以下螢幕擷取畫面顯示行事曆應用程式執行完畢的樣貌。

以下螢幕擷取畫面顯示郵件應用程式執行完畢的樣貌。

以下螢幕擷取畫面顯示連絡人應用程式執行完畢的樣貌。

必要條件

建立新專案前,請先確認您符合所有系統需求,並安裝 Visual Studio 的 Visual Studio Tools for Apache Cordova 擴充功能。 如需詳細資訊,請參閱安裝 Visual Studio Tools for Apache Cordova

建立專案

依序選擇 [檔案]、[新專案]、[JavaScript]、[Apache Cordova 應用程式],以及 [空白應用程式] 範本,在 Visual Studio 中建立新的 Cordova 專案。

在專案中加入 Ionic 架構

加入 Ionic 架構

  1. 在 Ionic 架構網站上,選擇 [下載 beta]。

  2. 將 zip 檔案解壓縮。

  3. 前往 Visual Studio 的 [方案總管],在您的 Cordova 專案下建立名為 lib 的新資料夾,然後複製 lib 資料夾底下的解壓縮內容。

  4. 更新指令碼參考。

    在 index.html 中,在 Cordova 和 platformOverrides 指令碼參考後面的 <head> 元素中加入下列 Ionic 參考。

    <script src="lib/ionic/js/ionic.bundle.min.js"></script>
    

    在 index.html 中,加入下列 Ionic 的 CSS 參考。

    <link href="lib/ionic/css/ionic.min.css" rel="stylesheet" />
    

在專案中加入 NProgress

從 O365 擷取郵件、行事曆和連絡人時,NProgress 將能用來顯示進度列。

在專案中加入 NProgress

  1. 在 NProgress 網站上,選擇 [下載]。

  2. 將 zip 檔案解壓縮。

  3. 在 [方案總管] 中的 lib 資料夾底下,建立名為 nprogress 的資料夾,然後將 nprogress.js 複製到資料夾中。

  4. 複製 css 資料夾底下的 nprogress.css

  5. 在 index.html 中,在 < head > 元素中加入下列 NProgress 參考。

    <link href="css/nprogress.css" rel="stylesheet" />
    <script src="lib/nprogress/nprogress.js"></script>
    

在應用程式中加入 O365 服務

註冊 Office 365 開發人員網站,然後依照設定 Office 365 開發環境的指示,設定開發人員網站的 Azure Active Directory 存取權。

開發人員網站設定完畢後,依照以下步驟操作,使用 Visual Studio 中的服務管理員來新增和設定 Office 365 API。

加入和設定 Office 365 API

  1. 從 Visual Studio 組件庫下載並安裝 Office 365 API 工具

  2. 在專案節點的捷徑功能表中,依序選擇 [新增] 和 [已連接服務]。

  3. 從頂端的 [服務管理員] 對話方塊中,選擇 Office 365 連結,然後選擇 [註冊應用程式]。

    使用 Office 365 開發人員組織的租用戶管理員帳戶登入。

設定 O365 郵件、行事曆和連絡人租用戶的權限,以授與適當的應用程式存取權

登入 O365 帳戶後,您會在租用戶帳戶下看見 O365 服務清單,例如郵件、行事曆、連絡人和檔案。 選取您要在應用程式中使用的服務,然後設定您希望的應用程式存取權,各個應用程式的權限設定詳述如下。

Dn911025.collapse_all(zh-tw,VS.120).gif郵件應用程式

選取 [郵件],然後按一下右窗格中的 [權限...] 連結。 接著,選擇讀取和寫入使用者的郵件,因為應用程式必須執行讀取和刪除郵件作業。 同樣地,如果您希望應用程式傳送郵件,則選取郵件做為使用者選項。

Dn911025.collapse_all(zh-tw,VS.120).gif行事曆應用程式

選取 [行事曆],按一下右窗格中的 [權限...] 連結,然後選取 [完整存取使用者的行事曆]。 同樣地,如果您只想賦與應用程式讀取權限,則選取 [讀取使用者的行事曆]。

Dn911025.collapse_all(zh-tw,VS.120).gif連絡人應用程式

選取 [連絡人],按一下右窗格中的 [權限...] 連結,然後選取 [完整存取使用者的連絡人]。 同樣地,如果您只想賦與應用程式讀取權限,則選取 [讀取使用者的連絡人]。

Dn911025.collapse_all(zh-tw,VS.120).gif套用變更及更新參考

套用變更及更新參考

  1. 按一下 [套用] 和 [確定] 即可設定權限,並將 O365 API 加入您的專案。

    服務管理員會在您的專案中加入服務資料夾。

  2. 在 index.html 中,在 < head > 元素中加入下列 O365 參考。

    <script src="services/office365/scripts/o365loader.js"></script>
    <script src="services/office365/settings/settings.js"></script>
    

使用 Ionic 控制項和導覽功能建立應用程式資料夾結構、UI 路由以及版面配置

依照下列步驟以建立應用程式 UI 及 JavaScript 節點的結構。

在專案根目錄節點下建立名為 app 的資料夾。 應用程式資料夾將包含應用程式的特定檔案。 每個會擷取資料並將其繫結至 UI 的 UI 元件會有相對應的控制項 (以 UI 後面附加程式碼的模式呈現)。 例如,mail-list.html 會顯示用來顯示使用者郵件的清單控制項,而 mail-list-ctrl.js 則會包含以 O365 API 擷取使用者郵件的程式碼。

以下是一些專案中資料夾和檔案的詳細資料。

  • auth 資料夾包含登入和登出的 UI 及程式碼。

  • layout 資料夾包含會顯示應用程式內容和導覽功能的 UI (例如 Ionic 窗格、Ionic 側功能表、Ionic 導覽列),以及用來繫結使用者名稱的程式碼。

  • app.js 包含導覽至不同頁面的 UI 路由。

  • service-o365.js 包含用以取得存取權杖、建立 Outlook 服務用戶端物件、登出,以及取得使用者名稱的公用程式函式。 這會實作為 AngularJS 處理站,使這些函式能在不同頁面公開為公用程式函式。

使用 AngularJS 路由導覽至不同頁面。 例如,以下是郵件應用程式的路由。

// Layout page
    .state('app', {
        abstract: true,
        url: "/app",
        templateUrl: "app/layout/layout.html"
    })

    // Sign-in page
     .state('sign-in', {
         url: "/sign-in",
         templateUrl: "app/auth/sign-in.html"
     })

    // Sign-out page
        .state('app.sign-out', {
            url: "/sign-out",
            views: {
                'mainContent': {
                    templateUrl: "app/auth/sign-out.html"
                }
            }
        })   

    // Mail list page
    .state('app.mail', {
        url: "/mail",
        views: {
            'mainContent': {
                templateUrl: "app/mail/mail-tabs.html"
            }
        }
    })

    // Mail list containing mails flagged as important
    .state('app.mail.imp', {
        url: "/imp/id:important",
        views: {
            "tab-imp-mail": {
                templateUrl: "app/mail/mail-list.html"
            }
        }
    })

    // Mail detail page
    .state('app.mail-detail', {
        url: "/mail/:id",
        views: {
            'mainContent': {
                templateUrl: "app/mail/mail-detail.html"
            }
        }
    })

    // Unread mail list page
    .state('app.mail.unread', {
        url: "/unread/id:unread",
        views: {
            "tab-unread-mail": {
                templateUrl: "app/mail/mail-list.html"
            }
        }
    })

    // All mail list page
    .state('app.mail.all', {
        url: "/all/id:all",
        views: {
            "tab-all-mail": {
                templateUrl: "app/mail/mail-list.html"
            }
        }
    });

    // Navigate to sign-in page when app starts.
    $urlRouterProvider.otherwise('sign-in');

若為應用程式版面配置 (功能表、導覽列),請使用 Ionic 側功能表和窗格。

<ion-side-menus ng-controller="layoutCtrl as vm">

    <ion-pane ion-side-menu-content>
        <ion-nav-bar class="bar-positive">
            <ion-nav-back-button class="button-clear icon ion-ios7-arrow-back"></ion-nav-back-button>
            <button menu-toggle="left" class="button button-icon icon ion-navicon"></button>
        </ion-nav-bar>
        <ion-nav-view name="mainContent" animation="slide-left-right"></ion-nav-view>
    </ion-pane>

    <ion-side-menu side="left">
        <header class="bar bar-header bar-positive">
            <h1 class="title">{{vm.userName}}</h1>
        </header>
        <ion-content class="has-header">
            <ion-list>                            
                <ion-item nav-clear menu-close ui-sref="app.sign-out">Sign-out</ion-item>
            </ion-list>
    </ion-side-menu>

</ion-side-menus>

使用 Ionic 索引標籤可顯示個別索引標籤中的不同內容。 例如,您可使用下列 Ionic 控制項來建立郵件索引標籤頁面,藉此在不同索引標籤下顯示重要郵件、未讀郵件和所有郵件。

<ion-view>
    <ion-tabs class="tabs-positive tabs-icon-top">
        <ion-tab title="Imp" icon="ion-star" ui-sref="app.mail.imp">
            <ion-nav-view name="tab-imp-mail"></ion-nav-view>
        </ion-tab>

        <ion-tab title="Unread" icon="ion-ios7-email-outline" ui-sref="app.mail.unread">
            <ion-nav-view name="tab-unread-mail"></ion-nav-view>
        </ion-tab>

        <ion-tab title="All" icon="ion-email" ui-sref="app.mail.all">
            <ion-nav-view name="tab-all-mail"></ion-nav-view>
        </ion-tab>
    </ion-tabs>
</ion-view>

郵件索引標籤頁面如下圖所示。

使用 AngularJS 處理站取得存取權杖和 Outlook 服務用戶端

建立公開 O365 API 的 AngularJS 處理站,以取得存取權杖、建立 Outlook 服務用戶端、登出,以及執行應用程式中不同控制器所使用的公用程式函式。

用以取得存取權杖的程式碼如下。

var authContext = new O365Auth.Context();
authContext.getIdToken("https://outlook.office365.com/")
.then((function (token) {
     // Get auth token
     authtoken = token;
     // Get user name from token object.
     userName = token.givenName + " " + token.familyName;
    }), function (error) {
      // Log sign-in error message.
      console.log('Failed to login. Error = ' + error.message);
 });

用以建立 Outlook 服務用戶端物件的程式碼如下。

var outlookClient = new Microsoft.OutlookServices.Client('https://outlook.office365.com/api/v1.0', authtoken.getAccessTokenFn('https://outlook.office365.com'));

用以公開 O365 API 的完整 AngularJS 處理站程式碼如下。

(function () {
    'use strict';
    angular.module('app365').factory('app365api', [app365api]);

    function app365api() {

        var authContext;
        var authtoken;
        var outlookClient;      
        var userName;

        // Login to O365
        function login(callback) {
            if (!authContext) {
                authContext = new O365Auth.Context();
            }

            authContext.getIdToken("https://outlook.office365.com/")
           .then((function (token) {
               // Get auth token
               authtoken = token;
               // Get user name from token object.
               userName = token.givenName + " " + token.familyName;
               // Create Outlook client object.
               outlookClient = new Microsoft.OutlookServices.Client('https://outlook.office365.com/api/v1.0', authtoken.getAccessTokenFn('https://outlook.office365.com'));
               // Callback without parameter to indicate successful sign-in.
               callback();
           }), function (error) {
               // Log sign-in error message.
               console.log('Failed to login. Error = ' + error.message);
               callback(error.message);
           });
        };

        // Logout
        function logout() {
            if (!authContext) {
                authContext = new O365Auth.Context();
            }

            authContext.logOut();
        };

        // Get signed-in user name.
        function getUserName() {
            return userName;
        };

        return {
            login: login,
            logout: logout,
            getUserName: getUserName,        
            exchangeClientObj: function () { return outlookClient; }
        };
    };
})();

使用 Outlook 用戶端物件來存取 O365 服務,例如郵件、行事曆和連絡人

您可以使用 Outlook 用戶端物件,在郵件、行事曆和連絡人上執行讀取和寫入作業。

Dn911025.collapse_all(zh-tw,VS.120).gif使用 Outlook 用戶端物件來讀取郵件、行事曆和連絡人

下列程式碼會讀取所有標示為重要的郵件。

// Get all mails flagged as important.
function getImpMails() {
   NProgress.start();
   // Filter to fetch all important mails received after 2000-10-20
   var filterQuery = "Importance eq 'High' and DateTimeReceived gt 2000-10-20";
   outlookClient.me.folders.getFolder("Inbox").fetch()
   .then(function (folder) {
   // Fetch all important mails sorted by DateTimeReceived.
      folder.messages.getMessages().filter(filterQuery).orderBy('Importance,DateTimeReceived desc').fetch()
.then(function (mails) {
// Get current page. Use getNextPage() to fetch next set of mails.
vm.mails = mails.currentPage;
$scope.$apply();
NProgress.done();
}, function (error) {
    console.log("Error encountered while fetching mails. Error: " + error.message);
 });
}, function (error) {
    console.log("Error encountered while fetching inbox folder. Error: " + error.message);
  });
};

下列程式碼會讀取開始日期等於今天的所有事件。

var filterQuery = 'start gt ' + today.toISOString() + ' and start lt ' + tomorrow.toISOString();
NProgress.start();
// Get events with filter.
outlookClient.me.calendar.events.getEvents().filter(filterQuery).fetch()
.then(function (events) {
// Get current page. Use getNextPage() to fetch next set of events.
    vm.events = events.currentPage;
    $scope.$apply();
    NProgress.done();
});

下列程式碼會讀取所有連絡人。

function getContacts() {
NProgress.start();

// Fetch all the contacts.
outlookClient.me.contacts.getContacts().fetch()
.then(function (contacts) {
// Get the current page. Use getNextPage() to fetch next set of contacts.
    vm.contacts = contacts.currentPage;
    $scope.$apply();
    NProgress.done();
  });
};

Dn911025.collapse_all(zh-tw,VS.120).gif使用 Outlook 用戶端物件來刪除郵件和行事曆事件

Outlook 用戶端物件可用來刪除郵件。 若要刪除郵件,請使用郵件 ID 取得您要刪除的郵件,然後在郵件物件上呼叫 delete() 即可刪除特定郵件。

注意事項注意事項

delete() 可永遠刪除郵件。若要將郵件移到 [已刪除項目],請改用 move()。

用以刪除郵件的程式碼如下。

// Fetch the mail with specified mail id.                    outlookClient.me.folders.getFolder("Inbox").messages.getMessage(mail.id).fetch()
.then(function (mail) {
    // Delete the mail.
    mail.delete()
    .then((function (response) {
         // mail deleted successfully.                
     }), function (error) {                            
         // Log the error message when error is encountered while deleting the mail.
         console.log('fail to delete mail. Error = ' + error.message);
 });

用以刪除事件的程式碼如下。

// Fetch event with specified event id.
outlookClient.me.calendar.events.getEvent(event.id).fetch()
.then(function (event) {
    // Delete event.
    event.delete()
    .then((function (response) {                            
     // Refresh event list.
     }).bind(this), function (reason) {
     // Log delete event error.
     console.log('Fail to delete event. Error = ' + reason.message);
});

Dn911025.collapse_all(zh-tw,VS.120).gif使用 Outlook 用戶端物件來建立新的連絡人和行事曆事件

Outlook 用戶端物件可用來建立新的連絡人、行事曆事件及傳送郵件。

用以加入新行事曆事件的程式碼如下。

// Event body content
var eventBody = new Microsoft.OutlookServices.ItemBody();
eventBody.contentType = Microsoft.OutlookServices.BodyType.HTML;
eventBody.content = $scope.newEvent.body;
// Event attendee.
var attendee = new Microsoft.OutlookServices.Attendee();
// Attendee email address.
var emailAddress = new Microsoft.OutlookServices.EmailAddress();
emailAddress.address = $scope.newEvent.toRecipients;
attendee.emailAddress = emailAddress;
// Event object.
var event = new Microsoft.OutlookServices.Event();
// Event start date.
event.start = new Date($scope.newEvent.start).toISOString();
// Event end date time
event.end = new Date($scope.newEvent.end).toISOString();
// Event subject.
event.subject = $scope.newEvent.subject;
// Event body.
event.body = eventBody;
// Add event attendee.
event.attendees.push(attendee);
// Event location.
event.location = new Microsoft.OutlookServices.Location();
event.location.displayName = 'Sample Location';
// Add event
outlookClient.me.calendar.events.addEvent(event)
.then((function (response) {
// New event created successfully.
})
.bind(this), function (reason) {
// Log the error message encountered while adding the event.
console.log('Fail to add event. Error = ' + reason.message);
});

用以加入新連絡人的程式碼如下。

// Contact object
var contact = new Microsoft.OutlookServices.Contact();

// First and last name
contact.givenName = $scope.newContact.firstname;
contact.surname = $scope.newContact.lastname;

// Mobile phone
contact.mobilePhone1 = $scope.newContact.phone;

// Email address
var emailAddress = new Microsoft.OutlookServices.EmailAddress();
emailAddress.address = $scope.newContact.email;
contact.emailAddresses.push(emailAddress);

// Add Contact
outlookClient.me.contacts.addContact(contact)
.then((function (response) {
// Contact added successfully.

})
.bind(this), function (reason) {
// Log the error message when add contact fails.
console.log('Fail to add contact. Error = ' + reason.message);
});

執行應用程式

選取 Android 做為目標 OS,並將其部署至 Android 模擬器或 Android 裝置。

注意事項注意事項

O365 驗證功能目前不支援 Ripple。

按下 F5 即可執行應用程式。

如需在各種不同平台上執行 Cordova 應用程式的詳細資訊,請參閱部署和執行由 Visual Studio Tools for Apache Cordova 建置的應用程式

試試看

完整應用程式可從 Github 取得。 請下載並試用範例應用程式後,將您的意見反應告訴我們。 無論是新的 O365 API 或 Visual Studio 中的 Cordova 工具支援,我們都希望您能提供寶貴意見!

應用程式

描述

Cordova 行事曆應用程式

使用 Ionic 建立的範例 Cordova 應用程式,主要示範如何使用 O365 行事曆 API 來讀取、篩選、刪除和新增事件。 應用程式會將事件分類成三個群組:(1) 今天的事件、(2) 明天的事件,以及 (3) 開始日期 > = 今天的所有事件。

Cordova 郵件應用程式

使用 Ionic 建立的範例 Cordova 應用程式,主要示範如何使用 O365 郵件 API 來讀取、篩選和刪除郵件。 應用程式會將使用者的郵件分類成三個群組:(1) 重要郵件、(2) 未讀郵件,以及 (3) 所有郵件。

Cordova 連絡人應用程式

使用 Ionic 建立的範例 Cordova 應用程式,主要示範如何使用 O365 連絡人 API 來讀取和新增連絡人。