├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── NOTICES.md ├── README.md ├── app ├── .gitignore ├── build.gradle ├── dailyBuild.gradle ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── microsoft │ │ │ └── office365 │ │ │ └── msgraphsnippetapp │ │ │ ├── BaseActivity.java │ │ │ ├── BaseFragment.java │ │ │ ├── ServiceConstants.java │ │ │ ├── SignInActivity.java │ │ │ ├── SnippetDetailActivity.java │ │ │ ├── SnippetDetailFragment.java │ │ │ ├── SnippetListActivity.java │ │ │ ├── SnippetListAdapter.java │ │ │ ├── SnippetListFragment.java │ │ │ ├── application │ │ │ └── SnippetApp.java │ │ │ ├── inject │ │ │ ├── AppModule.java │ │ │ ├── AzureModule.java │ │ │ └── ObjectGraphInjector.java │ │ │ ├── snippet │ │ │ ├── AbstractSnippet.java │ │ │ ├── ContactsSnippets.java │ │ │ ├── DrivesSnippets.java │ │ │ ├── EventsSnippets.java │ │ │ ├── GroupsSnippets.java │ │ │ ├── MeSnippets.java │ │ │ ├── MessageSnippets.java │ │ │ ├── SnippetCategory.java │ │ │ ├── SnippetContent.java │ │ │ └── UsersSnippets.java │ │ │ └── util │ │ │ └── SharedPrefsUtil.java │ └── res │ │ ├── drawable │ │ ├── bkgrnd_rect.xml │ │ └── border_red.xml │ │ ├── layout │ │ ├── activity_signin.xml │ │ ├── activity_snippet_detail.xml │ │ ├── activity_snippet_list.xml │ │ ├── fragment_snippet_detail.xml │ │ ├── list_element.xml │ │ └── list_segment.xml │ │ ├── menu │ │ └── snippet_list_menu.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── drives_snippets.xml │ │ ├── me_events_snippets.xml │ │ ├── me_messages_snippets.xml │ │ ├── me_snippets.xml │ │ ├── myorganization_contact_snippets.xml │ │ ├── myorganization_groups_snippets.xml │ │ ├── myorganization_user_snippets.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── microsoft │ └── office365 │ └── msgraphsnippetapp │ └── SnippetsUnitTests.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── microsoftgraphapi ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── microsoft │ └── office365 │ └── msgraphapiservices │ ├── MSGraphContactService.java │ ├── MSGraphDrivesService.java │ ├── MSGraphEventsService.java │ ├── MSGraphGroupsService.java │ ├── MSGraphMailService.java │ ├── MSGraphMeService.java │ └── MSGraphUserService.java ├── microsoftgraphvos ├── .gitignore ├── build.gradle ├── dailyBuild.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── microsoft │ └── office365 │ └── microsoftgraphvos │ ├── Attendee.java │ ├── Base.java │ ├── DateTimeTimeZone.java │ ├── DriveItem.java │ ├── EmailAddress.java │ ├── Envelope.java │ ├── Event.java │ ├── Folder.java │ ├── Group.java │ ├── ItemBody.java │ ├── Location.java │ ├── Message.java │ ├── MessageWrapper.java │ ├── PasswordProfile.java │ ├── RecipientVO.java │ └── User.java ├── o365-auth ├── .gitignore ├── build.gradle ├── dailyBuild.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── microsoft │ └── office365 │ └── auth │ ├── AuthenticationManager.java │ ├── AzureADModule.java │ └── AzureAppCompatActivity.java ├── readme-images ├── aad-application-id.PNG ├── aad-portal-app-registrations.png ├── aad-redirect-uri-public-client.PNG └── aad-register-an-app.PNG └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.ap_ 2 | *.apk 3 | *.class 4 | *.dex 5 | *.iml 6 | *.ipr 7 | *.iws 8 | .DS_Store 9 | .classpath 10 | .gradle 11 | .idea 12 | .project 13 | /.idea/libraries 14 | /.idea/workspace.xml 15 | /build 16 | /captures 17 | /local.properties 18 | Thumbs.db 19 | bin/ 20 | build/ 21 | gen/ 22 | out/ 23 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribute to this documentation 2 | 3 | Thank you for your interest in our documentation! 4 | 5 | * [Ways to contribute](#ways-to-contribute) 6 | * [Contribute using GitHub](#contribute-using-github) 7 | * [Contribute using Git](#contribute-using-git) 8 | * [How to use Markdown to format your topic](#how-to-use-markdown-to-format-your-topic) 9 | * [FAQ](#faq) 10 | * [More resources](#more-resources) 11 | 12 | ## Ways to contribute 13 | 14 | Here are some ways you can contribute to this documentation: 15 | 16 | * To make small changes to an article, [Contribute using GitHub](#contribute-using-github). 17 | * To make large changes, or changes that involve code, [Contribute using Git](#contribute-using-git). 18 | * Report documentation bugs via GitHub Issues 19 | * Request new documentation at the [Office Developer Platform UserVoice](http://officespdev.uservoice.com) site. 20 | 21 | ## Contribute using GitHub 22 | 23 | Use GitHub to contribute to this documentation without having to clone the repo to your desktop. This is the easiest way to create a pull request in this repository. Use this method to make a minor change that doesn't involve code changes. 24 | 25 | **Note** Using this method allows you to contribute to one article at a time. 26 | 27 | ### To Contribute using GitHub 28 | 29 | 1. Find the article you want to contribute to on GitHub. 30 | 31 | If the article is in MSDN, choose the **suggest and submit changes** link in the **Contribute to this content** section and you'll be taken to the same article on GitHub. 32 | 2. Once you are on the article in GitHub, sign in to GitHub (get a free account [Join GitHub](https://github.com/join). 33 | 3. Choose the **pencil icon** (edit the file in your fork of this project) and make your changes in the **<>Edit file** window. 34 | 4. Scroll to the bottom and enter a description. 35 | 5. Choose **Propose file change**>**Create pull request**. 36 | 37 | You now have successfully submitted a pull request. Pull requests are typically reviewed within 10 business days. 38 | 39 | 40 | ## Contribute using Git 41 | 42 | Use Git to contribute substantive changes, such as: 43 | 44 | * Contributing code. 45 | * Contributing changes that affect meaning. 46 | * Contributing large changes to text. 47 | * Adding new topics. 48 | 49 | ### To Contribute using Git 50 | 51 | 1. If you don't have a GitHub account, set one up at [GitHub](https://github.com/join). 52 | 2. After you have an account, install Git on your computer. Follow the steps in [Setting up Git Tutorial](https://help.github.com/articles/set-up-git/). 53 | 3. To submit a pull request using Git, follow the steps in [Use GitHub, Git, and this repository](#use-github-git-and-this-repository). 54 | 4. You will be asked to sign the Contributor's License Agreement if you are: 55 | 56 | * A member of the Microsoft Open Technologies group. 57 | * A contributors who doesn't work for Microsoft. 58 | 59 | As a community member, you must sign the Contribution License Agreement (CLA) before you can contribute large submissions to a project. You only need to complete and submit the documentation once. Carefully review the document. You may be required to have your employer sign the document. 60 | 61 | Signing the CLA does not grant you rights to commit to the main repository, but it does mean that the Office Developer and Office Developer Content Publishing teams will be able to review and approve your contributions. You will be credited for your submissions. 62 | 63 | Pull requests are typically reviewed within 10 business days. 64 | 65 | ## Use GitHub, Git, and this repository 66 | 67 | **Note:** Most of the information in this section can be found in [GitHub Help] articles. If you're familiar with Git and GitHub, skip to the **Contribute and edit content** section for the specifics of the code/content flow of this repository. 68 | 69 | ### To set up your fork of the repository 70 | 71 | 1. Set up a GitHub account so you can contribute to this project. If you haven't done this, go to [GitHub](https://github.com/join) and do it now. 72 | 2. Install Git on your computer. Follow the steps in the [Setting up Git Tutorial] [Set Up Git]. 73 | 3. Create your own fork of this repository. To do this, at the top of the page, choose the **Fork** button. 74 | 4. Copy your fork to your computer. To do this, open Git Bash. At the command prompt enter: 75 | 76 | git clone https://github.com//.git 77 | 78 | Next, create a reference to the root repository by entering these commands: 79 | 80 | cd 81 | git remote add upstream https://github.com/microsoftgraph/.git 82 | git fetch upstream 83 | 84 | Congratulations! You've now set up your repository. You won't need to repeat these steps again. 85 | 86 | ### Contribute and edit content 87 | 88 | To make the contribution process as seamless as possible, follow these steps. 89 | 90 | #### To contribute and edit content 91 | 92 | 1. Create a new branch. 93 | 2. Add new content or edit existing content. 94 | 3. Submit a pull request to the main repository. 95 | 4. Delete the branch. 96 | 97 | **Important** Limit each branch to a single concept/article to streamline the work flow and reduce the chance of merge conflicts. Content appropriate for a new branch includes: 98 | 99 | * A new article. 100 | * Spelling and grammar edits. 101 | * Applying a single formatting change across a large set of articles (for example, applying a new copyright footer). 102 | 103 | #### To create a new branch 104 | 105 | 1. Open Git Bash. 106 | 2. At the Git Bash command prompt, type `git pull upstream master:`. This creates a new branch locally that is copied from the latest MicrosoftGraph master branch. 107 | 3. At the Git Bash command prompt, type `git push origin `. This alerts GitHub to the new branch. You should now see the new branch in your fork of the repository on GitHub. 108 | 4. At the Git Bash command prompt, type `git checkout ` to switch to your new branch. 109 | 110 | #### Add new content or edit existing content 111 | 112 | You navigate to the repository on your computer by using File Explorer. The repository files are in `C:\Users\\`. 113 | 114 | To edit files, open them in an editor of your choice and modify them. To create a new file, use the editor of your choice and save the new file in the appropriate location in your local copy of the repository. While working, save your work frequently. 115 | 116 | The files in `C:\Users\\` are a working copy of the new branch that you created in your local repository. Changing anything in this folder doesn't affect the local repository until you commit a change. To commit a change to the local repository, type the following commands in GitBash: 117 | 118 | git add . 119 | git commit -v -a -m "" 120 | 121 | The `add` command adds your changes to a staging area in preparation for committing them to the repository. The period after the `add` command specifies that you want to stage all of the files that you added or modified, checking subfolders recursively. (If you don't want to commit all of the changes, you can add specific files. You can also undo a commit. For help, type `git add -help` or `git status`.) 122 | 123 | The `commit` command applies the staged changes to the repository. The switch `-m` means you are providing the commit comment in the command line. The -v and -a switches can be omitted. The -v switch is for verbose output from the command, and -a does what you already did with the add command. 124 | 125 | You can commit multiple times while you are doing your work, or you can commit once when you're done. 126 | 127 | #### Submit a pull request to the main repository 128 | 129 | When you're finished with your work and are ready to have it merged into the main repository, follow these steps. 130 | 131 | #### To submit a pull request to the main repository 132 | 133 | 1. In the Git Bash command prompt, type `git push origin `. In your local repository, `origin` refers to your GitHub repository that you cloned the local repository from. This command pushes the current state of your new branch, including all commits made in the previous steps, to your GitHub fork. 134 | 2. On the GitHub site, navigate in your fork to the new branch. 135 | 3. Choose the **Pull Request** button at the top of the page. 136 | 4. Verify the Base branch is `microsoftgraph/@master` and the Head branch is `/@`. 137 | 5. Choose the **Update Commit Range** button. 138 | 6. Add a title to your pull request, and describe all the changes you're making. 139 | 7. Submit the pull request. 140 | 141 | One of the site administrators will process your pull request. Your pull request will surface on the microsoftgraph/ site under Issues. When the pull request is accepted, the issue will be resolved. 142 | 143 | #### Create a new branch after merge 144 | 145 | After a branch is successfully merged (that is, your pull request is accepted), don't continue working in that local branch. This can lead to merge conflicts if you submit another pull request. To do another update, create a new local branch from the successfully merged upstream branch, and then delete your initial local branch. 146 | 147 | For example, if your local branch X was successfully merged into the OfficeDev/microsoft-graph-docs master branch and you want to make additional updates to the content that was merged. Create a new local branch, X2, from the OfficeDev/microsoft-graph-docs master branch. To do this, open GitBash and execute the following commands: 148 | 149 | cd microsoft-graph-docs 150 | git pull upstream master:X2 151 | git push origin X2 152 | 153 | You now have local copies (in a new local branch) of the work that you submitted in branch X. The X2 branch also contains all the work other writers have merged, so if your work depends on others' work (for example, shared images), it is available in the new branch. You can verify that your previous work (and others' work) is in the branch by checking out the new branch... 154 | 155 | git checkout X2 156 | 157 | ...and verifying the content. (The `checkout` command updates the files in `C:\Users\\microsoft-graph-docs` to the current state of the X2 branch.) Once you check out the new branch, you can make updates to the content and commit them as usual. However, to avoid working in the merged branch (X) by mistake, it's best to delete it (see the following **Delete a branch** section). 158 | 159 | #### Delete a branch 160 | 161 | Once your changes are successfully merged into the main repository, delete the branch you used because you no longer need it. Any additional work should be done in a new branch. 162 | 163 | #### To delete a branch 164 | 165 | 1. In the Git Bash command prompt, type `git checkout master`. This ensures that you aren't in the branch to be deleted (which isn't allowed). 166 | 2. Next, at the command prompt, type `git branch -d `. This deletes the branch on your computer only if it has been successfully merged to the upstream repository. (You can override this behavior with the `–D` flag, but first be sure you want to do this.) 167 | 3. Finally, type `git push origin :` at the command prompt (a space before the colon and no space after it). This will delete the branch on your github fork. 168 | 169 | Congratulations, you have successfully contributed to the project! 170 | 171 | ## How to use Markdown to format your topic 172 | 173 | ### Article template 174 | 175 | The [markdown template](/articles/0-markdown-template-for-new-articles.md) contains the basic Markdown for a topic that includes a table of contents, sections with subheadings, links to other Office developer topics, links to other sites, bold text, italic text, numbered and bulleted lists, code snippets, and images. 176 | 177 | 178 | ### Standard Markdown 179 | 180 | All of the articles in this repository use Markdown. A complete introduction (and listing of all the syntax) can be found at [Markdown Home] []. 181 | 182 | ## FAQ 183 | 184 | ### How do I get a GitHub account? 185 | 186 | Fill out the form at [Join GitHub](https://github.com/join) to open a free GitHub account. 187 | 188 | ### Where do I get a Contributor's License Agreement? 189 | 190 | You will automatically be sent a notice that you need to sign the Contributor's License Agreement (CLA) if your pull request requires one. 191 | 192 | As a community member, **you must sign the Contribution License Agreement (CLA) before you can contribute large submissions to this project**. You only need complete and submit the documentation once. Carefully review the document. You may be required to have your employer sign the document. 193 | 194 | ### What happens with my contributions? 195 | 196 | When you submit your changes, via a pull request, our team will be notified and will review your pull request. You will receive notifications about your pull request from GitHub; you may also be notified by someone from our team if we need more information. We reserve the right to edit your submission for legal, style, clarity, or other issues. 197 | 198 | ### Can I become an approver for this repository's GitHub pull requests? 199 | 200 | Currently, we are not allowing external contributors to approve pull requests in this repository. 201 | 202 | ### How soon will I get a response about my change request or issue? 203 | 204 | We typically review pull requests and respond to issues within 10 business days. 205 | 206 | ## More resources 207 | 208 | * To learn more about Markdown, go to the Git creator's site [Daring Fireball]. 209 | * To learn more about using Git and GitHub, first check out the [GitHub Help section] [GitHub Help]. 210 | 211 | [GitHub Home]: http://github.com 212 | [GitHub Help]: http://help.github.com/ 213 | [Set Up Git]: http://help.github.com/win-set-up-git/ 214 | [Markdown Home]: http://daringfireball.net/projects/markdown/ 215 | [Daring Fireball]: http://daringfireball.net/ 216 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Microsoft. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /NOTICES.md: -------------------------------------------------------------------------------- 1 | #Third Party Notices for Office 365 Android Microsoft Graph Snippets 2 | 3 | This project incorporates material from the project(s) listed below (collectively, "Third Party Code"). Microsoft is not the original author of the Third Party Code. The original copyright notices and licenses, under which Microsoft received such Third Party Code, are set out below together with the full text of such licenses. These notices and licenses are provided for informational purposes only. This Third Party Code is licensed to you under the terms set forth in the licenses set forth below. Microsoft reserves all other rights not expressly granted under this agreement, whether by implication, estoppel or otherwise. 4 | 5 | - Android SDK, which is provided by the Android Open Source Project and is used according to terms described in the [Creative Commons 2.5 Attribution License](http://creativecommons.org/licenses/by/2.5). The Android SDK is available [here](http://developer.android.com/sdk/index.html). 6 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 27 5 | 6 | defaultConfig { 7 | applicationId "com.microsoft.o365_android_microsoft_graph_snippets" 8 | minSdkVersion 21 9 | targetSdkVersion 27 10 | versionCode 1 11 | versionName "1.0" 12 | javaCompileOptions { 13 | annotationProcessorOptions { 14 | includeCompileClasspath true 15 | } 16 | } 17 | } 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | packagingOptions { 25 | exclude 'META-INF/LICENSE.txt' 26 | exclude 'META-INF/NOTICE.txt' 27 | exclude 'META-INF/jersey-module-version' 28 | } 29 | testOptions { 30 | unitTests.returnDefaultValues = true 31 | } 32 | } 33 | 34 | dependencies { 35 | // Project modules 36 | implementation(project(':o365-auth')) 37 | implementation(project(':microsoftgraphapi')) 38 | 39 | // Dagger compiler for DI annotation support 40 | compileOnly('com.squareup.dagger:dagger-compiler:1.2.5') { 41 | exclude group: 'com.google.guava' 42 | } 43 | annotationProcessor 'com.squareup.dagger:dagger-compiler:1.2.5' 44 | 45 | // Butterknife 46 | implementation 'com.jakewharton:butterknife:8.4.0' 47 | annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0' 48 | 49 | // Timber 50 | implementation 'com.jakewharton.timber:timber:4.1.2' 51 | 52 | // Apache Commons 53 | implementation 'commons-io:commons-io:2.5' 54 | 55 | implementation 'com.google.guava:guava:19.0' 56 | 57 | // Test 58 | testImplementation 'junit:junit:4.12' 59 | // Retrofit + custom HTTP 60 | implementation 'com.squareup.okhttp3:okhttp:3.4.1' 61 | implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1' 62 | } 63 | -------------------------------------------------------------------------------- /app/dailyBuild.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 27 5 | buildToolsVersion "23.0.3" 6 | 7 | defaultConfig { 8 | applicationId "com.microsoft.o365_android_microsoft_graph_snippets" 9 | minSdkVersion 21 10 | targetSdkVersion 27 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | packagingOptions { 21 | exclude 'META-INF/LICENSE.txt' 22 | exclude 'META-INF/NOTICE.txt' 23 | exclude 'META-INF/jersey-module-version' 24 | } 25 | testOptions { 26 | unitTests.returnDefaultValues = true 27 | } 28 | } 29 | 30 | dependencies { 31 | // Azure AD 32 | implementation(project(':o365-auth')) 33 | implementation(project(':microsoftgraphapi')) 34 | 35 | // Dagger compiler for DI annotation support 36 | compileOnly('com.squareup.dagger:dagger-compiler:+') { 37 | exclude group: 'com.google.guava' 38 | } 39 | annotationProcessor 'com.squareup.dagger:dagger-compiler:1.2.5' 40 | 41 | // Butterknife 42 | implementation 'com.jakewharton:butterknife:8.4.0' 43 | annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0' 44 | 45 | // Timber 46 | implementation 'com.jakewharton.timber:timber:+' 47 | 48 | // Apache Commons 49 | implementation 'commons-io:commons-io:+' 50 | 51 | implementation 'com.google.guava:guava:+' 52 | 53 | // Test 54 | testimplementation 'junit:junit:4.12' 55 | // Retrofit + custom HTTP 56 | implementation 'com.squareup.okhttp3:okhttp:+' 57 | implementation 'com.squareup.okhttp3:logging-interceptor:+' 58 | } 59 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/johnaustin/AndroidSDK/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | 29 | 30 | 32 | 33 | 34 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/BaseActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp; 6 | 7 | import com.microsoft.office365.auth.AzureADModule; 8 | import com.microsoft.office365.auth.AzureAppCompatActivity; 9 | import com.microsoft.office365.msgraphsnippetapp.application.SnippetApp; 10 | import com.microsoft.office365.msgraphsnippetapp.inject.AzureModule; 11 | import com.microsoft.office365.msgraphsnippetapp.inject.ObjectGraphInjector; 12 | 13 | import dagger.ObjectGraph; 14 | 15 | public abstract class BaseActivity 16 | extends AzureAppCompatActivity 17 | implements ObjectGraphInjector { 18 | 19 | @Override 20 | protected AzureADModule getAzureADModule() { 21 | AzureADModule.Builder builder = new AzureADModule.Builder(this); 22 | builder.validateAuthority(true) 23 | .authorityUrl(ServiceConstants.AUTHORITY_URL) 24 | .clientId(ServiceConstants.CLIENT_ID) 25 | .scopes(ServiceConstants.SCOPES); 26 | return builder.build(); 27 | } 28 | 29 | @Override 30 | protected Object[] getModules() { 31 | return new Object[]{new AzureModule()}; 32 | } 33 | 34 | @Override 35 | protected ObjectGraph getRootGraph() { 36 | return SnippetApp.getApp().mObjectGraph; 37 | } 38 | 39 | @Override 40 | public void inject(Object target) { 41 | mObjectGraph.inject(target); 42 | } 43 | } -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/BaseFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp; 6 | 7 | import android.os.Bundle; 8 | import android.support.annotation.Nullable; 9 | import android.support.v4.app.Fragment; 10 | 11 | public class BaseFragment extends Fragment { 12 | 13 | @Override 14 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 15 | super.onActivityCreated(savedInstanceState); 16 | ((BaseActivity) getActivity()).inject(this); 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/ServiceConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp; 6 | 7 | public class ServiceConstants { 8 | public static final String AUTHENTICATION_RESOURCE_ID = "https://graph.microsoft.com"; 9 | public static final String AUTHORITY_URL = "https://login.microsoftonline.com/common"; 10 | public static final String CLIENT_ID = "ENTER_YOUR_CLIENT_ID"; 11 | public static final String[] SCOPES = {"openid", "Directory.ReadWrite.All","Calendars.ReadWrite","Files.ReadWrite","Mail.ReadWrite","Mail.Send","User.ReadBasic.All", "Group.ReadWrite.All", "profile"}; 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/SignInActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp; 6 | 7 | import android.content.Intent; 8 | import android.os.Bundle; 9 | import android.util.Log; 10 | import android.view.View; 11 | import android.widget.TextView; 12 | import android.widget.Toast; 13 | 14 | import com.microsoft.identity.client.AuthenticationResult; 15 | import com.microsoft.identity.client.IAccount; 16 | import com.microsoft.identity.client.Logger; 17 | import com.microsoft.identity.client.PublicClientApplication; 18 | import com.microsoft.identity.client.exception.MsalClientException; 19 | import com.microsoft.identity.client.exception.MsalException; 20 | import com.microsoft.identity.client.exception.MsalServiceException; 21 | import com.microsoft.identity.client.exception.MsalUiRequiredException; 22 | import com.microsoft.identity.client.AuthenticationCallback; 23 | import com.microsoft.office365.msgraphsnippetapp.util.SharedPrefsUtil; 24 | 25 | import java.util.List; 26 | import java.util.UUID; 27 | 28 | import butterknife.BindView; 29 | import butterknife.ButterKnife; 30 | import butterknife.OnClick; 31 | 32 | import static android.view.View.INVISIBLE; 33 | import static android.view.View.VISIBLE; 34 | import static com.microsoft.office365.msgraphsnippetapp.R.id.layout_diagnostics; 35 | import static com.microsoft.office365.msgraphsnippetapp.R.id.o365_signin; 36 | import static com.microsoft.office365.msgraphsnippetapp.R.id.view_diagnosticsdata; 37 | import static com.microsoft.office365.msgraphsnippetapp.R.layout.activity_signin; 38 | import static com.microsoft.office365.msgraphsnippetapp.R.string.signin_err; 39 | import static com.microsoft.office365.msgraphsnippetapp.R.string.warning_clientid_redirecturi_incorrect; 40 | 41 | public class SignInActivity 42 | extends BaseActivity 43 | implements AuthenticationCallback { 44 | 45 | private boolean mEnablePiiLogging = false; 46 | private static final String TAG = "SignInActivity"; 47 | 48 | @BindView(layout_diagnostics) 49 | protected View mDiagnosticsLayout; 50 | 51 | @BindView(view_diagnosticsdata) 52 | protected TextView mDiagnosticsTxt; 53 | 54 | @Override 55 | protected void onCreate(Bundle savedInstanceState) { 56 | super.onCreate(savedInstanceState); 57 | setContentView(activity_signin); 58 | 59 | ButterKnife.bind(this); 60 | } 61 | 62 | @OnClick(o365_signin) 63 | public void onSignInO365Clicked() { 64 | try { 65 | authenticate(); 66 | } catch (IllegalArgumentException exception) { 67 | warnBadClient(); 68 | } 69 | } 70 | 71 | @Override 72 | public void onSuccess(AuthenticationResult authenticationResult) { 73 | // reset anything that may have gone wrong... 74 | mDiagnosticsLayout.setVisibility(INVISIBLE); 75 | mDiagnosticsTxt.setText(""); 76 | 77 | // get rid of this Activity so that users can't 'back' into it 78 | finish(); 79 | 80 | // save our auth token to use later 81 | SharedPrefsUtil.persistAuthToken(authenticationResult); 82 | 83 | // get the user display name 84 | final String userDisplayableId = 85 | authenticationResult 86 | .getAccount() 87 | .getUsername(); 88 | 89 | // get the index of their '@' in the name (to determine domain) 90 | final int at = userDisplayableId.indexOf("@"); 91 | 92 | // parse-out the tenant 93 | final String tenant = userDisplayableId.substring(at + 1); 94 | 95 | SharedPrefsUtil.persistUserTenant(tenant); 96 | SharedPrefsUtil.persistUserID(authenticationResult); 97 | 98 | // go to our main activity 99 | start(); 100 | } 101 | 102 | @Override 103 | public void onError(MsalException exception) { 104 | exception.printStackTrace(); 105 | 106 | //Show the localized message supplied with the exception or 107 | //or a default message from the string resources if a 108 | //localized message cannot be obtained 109 | String msg; 110 | if (null == (msg = exception.getLocalizedMessage())) { 111 | msg = getString(signin_err); 112 | Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); 113 | } else { 114 | mDiagnosticsTxt.setText(msg); 115 | mDiagnosticsLayout.setVisibility(VISIBLE); 116 | } 117 | if (exception instanceof MsalClientException) { 118 | // This means errors happened in the sdk itself, could be network, Json parse, etc. Check MsalError.java 119 | // for detailed list of the errors. 120 | 121 | Toast.makeText(this, exception.getMessage(), Toast.LENGTH_SHORT).show(); 122 | 123 | } else if (exception instanceof MsalServiceException) { 124 | // This means something is wrong when the sdk is communication to the service, mostly likely it's the client 125 | // configuration. 126 | Toast.makeText(this, exception.getMessage(), Toast.LENGTH_SHORT).show(); 127 | 128 | } else if (exception instanceof MsalUiRequiredException) { 129 | // This explicitly indicates that developer needs to prompt the user, it could be refresh token is expired, revoked 130 | // or user changes the password; or it could be that no token was found in the token cache. 131 | 132 | mAuthenticationManager.callAcquireToken( this); 133 | } 134 | } 135 | 136 | private void warnBadClient() { 137 | Toast.makeText(this, 138 | warning_clientid_redirecturi_incorrect, 139 | Toast.LENGTH_LONG) 140 | .show(); 141 | } 142 | 143 | private void authenticate() throws IllegalArgumentException { 144 | validateOrganizationArgs(); 145 | connect(); 146 | } 147 | 148 | private void connect() { 149 | 150 | // The sample app is having the PII enable setting on the MainActivity. Ideally, app should decide to enable Pii or not, 151 | // if it's enabled, it should be the setting when the application is onCreate. 152 | if (mEnablePiiLogging) { 153 | Logger.getInstance().setEnablePII(true); 154 | } else { 155 | Logger.getInstance().setEnablePII(false); 156 | } 157 | 158 | /* Attempt to get a user and acquireTokenSilent 159 | * If this fails we do an interactive request 160 | */ 161 | List users = null; 162 | 163 | try { 164 | users = mAuthenticationManager.getPublicClient().getAccounts(); 165 | 166 | if (users != null && users.size() == 1) { 167 | /* We have 1 user */ 168 | mUser = users.get(0); 169 | mAuthenticationManager.callAcquireTokenSilent( 170 | mUser, 171 | true, 172 | this); 173 | } else { 174 | /* We have no user */ 175 | 176 | /* Let's do an interactive request */ 177 | mAuthenticationManager.callAcquireToken( 178 | this); 179 | } 180 | } 181 | catch (IndexOutOfBoundsException exception) { 182 | Log.d(TAG, "User at this position does not exist: " + exception.toString()); 183 | Toast.makeText(this, exception.getMessage(), Toast.LENGTH_SHORT).show(); 184 | 185 | } catch (IllegalStateException exception) { 186 | Log.d(TAG, "MSAL Exception Generated: " + exception.toString()); 187 | Toast.makeText(this, exception.getMessage(), Toast.LENGTH_SHORT).show(); 188 | 189 | } catch (Exception exception) { 190 | Toast.makeText(this, exception.getMessage(), Toast.LENGTH_SHORT).show(); 191 | } 192 | } 193 | 194 | private void validateOrganizationArgs() throws IllegalArgumentException { 195 | UUID.fromString(ServiceConstants.CLIENT_ID); 196 | } 197 | 198 | private void start() { 199 | Intent appLaunch = new Intent(this, SnippetListActivity.class); 200 | startActivity(appLaunch); 201 | } 202 | 203 | public IAccount mUser; 204 | 205 | @Override 206 | public void onCancel() { 207 | Toast.makeText(this, "User cancelled the flow.", Toast.LENGTH_SHORT).show(); 208 | } 209 | /** 210 | * Handles redirect response from https://login.microsoftonline.com/common and 211 | * notifies the MSAL library that the user has completed the authentication 212 | * dialog 213 | * @param requestCode 214 | * @param resultCode 215 | * @param data 216 | */ 217 | @Override 218 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 219 | super.onActivityResult(requestCode, resultCode, data); 220 | 221 | PublicClientApplication client = mAuthenticationManager.getPublicClient(); 222 | if (client != null) { 223 | mAuthenticationManager 224 | .getPublicClient() 225 | .handleInteractiveRequestRedirect(requestCode, resultCode, data); 226 | } 227 | } 228 | } -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/SnippetDetailActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp; 6 | 7 | import android.content.Intent; 8 | import android.os.Bundle; 9 | import android.support.v4.app.NavUtils; 10 | import android.view.MenuItem; 11 | 12 | public class SnippetDetailActivity extends BaseActivity { 13 | 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | setContentView(R.layout.activity_snippet_detail); 18 | if (null != getSupportActionBar()) { 19 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 20 | } 21 | if (savedInstanceState == null) { 22 | Bundle arguments = new Bundle(); 23 | arguments.putInt(SnippetDetailFragment.ARG_ITEM_ID, 24 | getIntent().getIntExtra(SnippetDetailFragment.ARG_ITEM_ID, 0)); 25 | SnippetDetailFragment fragment = new SnippetDetailFragment(); 26 | fragment.setArguments(arguments); 27 | getSupportFragmentManager().beginTransaction() 28 | .add(R.id.snippet_detail_container, fragment) 29 | .commit(); 30 | } 31 | } 32 | 33 | @Override 34 | public boolean onOptionsItemSelected(MenuItem item) { 35 | int id = item.getItemId(); 36 | if (id == android.R.id.home) { 37 | NavUtils.navigateUpTo(this, new Intent(this, SnippetListActivity.class)); 38 | return true; 39 | } 40 | return super.onOptionsItemSelected(item); 41 | } 42 | } -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/SnippetDetailFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp; 6 | 7 | import android.annotation.TargetApi; 8 | import android.content.ClipData; 9 | import android.content.Context; 10 | import android.content.Intent; 11 | import android.net.Uri; 12 | import android.os.Build; 13 | import android.os.Bundle; 14 | import android.support.annotation.Nullable; 15 | import android.support.v7.app.AppCompatActivity; 16 | import android.text.ClipboardManager; 17 | import android.view.LayoutInflater; 18 | import android.view.View; 19 | import android.view.ViewGroup; 20 | import android.widget.Button; 21 | import android.widget.ProgressBar; 22 | import android.widget.TextView; 23 | import android.widget.Toast; 24 | 25 | import com.microsoft.office365.msgraphsnippetapp.snippet.AbstractSnippet; 26 | import com.microsoft.office365.msgraphsnippetapp.snippet.SnippetContent; 27 | 28 | import org.json.JSONException; 29 | import org.json.JSONObject; 30 | 31 | import java.io.IOException; 32 | import java.io.PrintWriter; 33 | import java.io.StringWriter; 34 | 35 | import butterknife.ButterKnife; 36 | import butterknife.BindView; 37 | import butterknife.OnClick; 38 | import okhttp3.Headers; 39 | import okhttp3.ResponseBody; 40 | import retrofit2.Call; 41 | import retrofit2.Callback; 42 | import retrofit2.Response; 43 | import timber.log.Timber; 44 | 45 | import static android.view.View.GONE; 46 | import static android.view.View.VISIBLE; 47 | import static com.microsoft.office365.msgraphsnippetapp.R.color.code_1xx; 48 | import static com.microsoft.office365.msgraphsnippetapp.R.color.code_3xx; 49 | import static com.microsoft.office365.msgraphsnippetapp.R.color.code_4xx; 50 | import static com.microsoft.office365.msgraphsnippetapp.R.color.transparent; 51 | import static com.microsoft.office365.msgraphsnippetapp.R.id.btn_run; 52 | import static com.microsoft.office365.msgraphsnippetapp.R.id.progressbar; 53 | import static com.microsoft.office365.msgraphsnippetapp.R.id.txt_desc; 54 | import static com.microsoft.office365.msgraphsnippetapp.R.id.txt_hyperlink; 55 | import static com.microsoft.office365.msgraphsnippetapp.R.id.txt_request_url; 56 | import static com.microsoft.office365.msgraphsnippetapp.R.id.txt_response_body; 57 | import static com.microsoft.office365.msgraphsnippetapp.R.id.txt_response_headers; 58 | import static com.microsoft.office365.msgraphsnippetapp.R.id.txt_status_code; 59 | import static com.microsoft.office365.msgraphsnippetapp.R.id.txt_status_color; 60 | import static com.microsoft.office365.msgraphsnippetapp.R.string.clippy; 61 | import static com.microsoft.office365.msgraphsnippetapp.R.string.req_url; 62 | import static com.microsoft.office365.msgraphsnippetapp.R.string.response_body; 63 | import static com.microsoft.office365.msgraphsnippetapp.R.string.response_headers; 64 | 65 | public class SnippetDetailFragment 66 | extends BaseFragment implements Callback { 67 | 68 | public static final String ARG_ITEM_ID = "item_id"; 69 | 70 | private static final int UNSET = -1; 71 | private static final String STATUS_COLOR = "STATUS_COLOR"; 72 | 73 | private AbstractSnippet mItem; 74 | 75 | // 76 | // UI component bindings 77 | // 78 | 79 | /** 80 | * Displays the status code of the service call 81 | */ 82 | @BindView(txt_status_code) 83 | protected TextView mStatusCode; 84 | 85 | /** 86 | * Displays the status code as color 'stoplight' 87 | */ 88 | @BindView(txt_status_color) 89 | protected View mStatusColor; 90 | 91 | /** 92 | * On-screen description of the current snippet 93 | */ 94 | @BindView(txt_desc) 95 | protected TextView mSnippetDescription; 96 | 97 | /** 98 | * The request url of the current snippet 99 | */ 100 | @BindView(txt_request_url) 101 | protected TextView mRequestUrl; 102 | 103 | /** 104 | * The response headers of the current snippet's request 105 | */ 106 | @BindView(txt_response_headers) 107 | protected TextView mResponseHeaders; 108 | 109 | /** 110 | * The response body of the snippet's request 111 | */ 112 | @BindView(txt_response_body) 113 | protected TextView mResponseBody; 114 | 115 | /** 116 | * Barber's pole progress bar (indeterminate) 117 | */ 118 | @BindView(progressbar) 119 | protected ProgressBar mProgressbar; 120 | 121 | /** 122 | * The 'run-snippet' button 123 | */ 124 | @BindView(btn_run) 125 | protected Button mRunButton; 126 | 127 | /** 128 | * Fragment default constructor 129 | */ 130 | public SnippetDetailFragment() { 131 | // unimplemented 132 | } 133 | 134 | // 135 | // UI event bindings 136 | // 137 | @OnClick(txt_request_url) 138 | public void onRequestUrlClicked(TextView tv) { 139 | // copy to clip 140 | clipboard(tv); 141 | } 142 | 143 | @OnClick(txt_response_headers) 144 | public void onResponseHeadersClicked(TextView tv) { 145 | // copy to clip 146 | clipboard(tv); 147 | } 148 | 149 | @OnClick(txt_response_body) 150 | public void onResponseBodyClicked(TextView tv) { 151 | // copy to clip 152 | clipboard(tv); 153 | } 154 | 155 | @OnClick(btn_run) 156 | public void onRunClicked(Button btn) { 157 | // disable the button while the snippet is running 158 | mRunButton.setEnabled(false); 159 | 160 | // clear the old request url 161 | mRequestUrl.setText(""); 162 | 163 | // clear any old headers 164 | mResponseHeaders.setText(""); 165 | 166 | // clear any old response body 167 | mResponseBody.setText(""); 168 | 169 | // reset the status 'stoplight' 170 | displayStatusCode("", 171 | getResources() 172 | .getColor(transparent) 173 | ); 174 | 175 | // show the indeterminate spinner 176 | mProgressbar.setVisibility(VISIBLE); 177 | 178 | // actually make the request 179 | mItem.request(mItem.mService, this); 180 | } 181 | 182 | @OnClick(txt_hyperlink) 183 | public void onDocsLinkClicked(TextView textView) { 184 | launchUrl(Uri.parse(mItem.getUrl())); 185 | } 186 | 187 | // 188 | // Lifecycle hooks 189 | // 190 | @Override 191 | public void onCreate(Bundle savedInstanceState) { 192 | super.onCreate(savedInstanceState); 193 | if (getArguments().containsKey(ARG_ITEM_ID)) { 194 | mItem = (AbstractSnippet) 195 | SnippetContent.ITEMS.get(getArguments().getInt(ARG_ITEM_ID)); 196 | } 197 | } 198 | 199 | @Override 200 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 201 | Bundle savedInstanceState) { 202 | View rootView = inflater.inflate(R.layout.fragment_snippet_detail, container, false); 203 | ButterKnife.bind(this, rootView); 204 | mSnippetDescription.setText(mItem.getDescription()); 205 | return rootView; 206 | } 207 | 208 | @Override 209 | public void onSaveInstanceState(Bundle outState) { 210 | super.onSaveInstanceState(outState); 211 | if (null != mStatusColor.getTag()) { 212 | outState.putInt(STATUS_COLOR, (Integer) mStatusColor.getTag()); 213 | } 214 | } 215 | 216 | @Override 217 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 218 | super.onActivityCreated(savedInstanceState); 219 | if (null != getActivity() && getActivity() instanceof AppCompatActivity) { 220 | AppCompatActivity activity = (AppCompatActivity) getActivity(); 221 | if (null != activity.getSupportActionBar()) { 222 | activity.getSupportActionBar().setTitle(mItem.getName()); 223 | } 224 | } 225 | if (null != savedInstanceState && savedInstanceState.containsKey(STATUS_COLOR)) { 226 | int statusColor = savedInstanceState.getInt(STATUS_COLOR, UNSET); 227 | if (UNSET != statusColor) { 228 | mStatusColor.setBackgroundColor(statusColor); 229 | mStatusColor.setTag(statusColor); 230 | } 231 | } 232 | } 233 | 234 | // 235 | // Custom event bindings 236 | // 237 | @Override 238 | public void onResponse(Call call, Response response) { 239 | if (response.isSuccessful()) { 240 | if (!isAdded()) { 241 | // the user has left... 242 | return; 243 | } 244 | mRunButton.setEnabled(true); 245 | mProgressbar.setVisibility(GONE); 246 | displayResponse(response); 247 | } else { 248 | Timber.e(response.errorBody().toString(), this); 249 | mRunButton.setEnabled(true); 250 | mProgressbar.setVisibility(GONE); 251 | 252 | if (null != response.errorBody()) { 253 | displayResponse(response); 254 | } 255 | } 256 | } 257 | 258 | @Override 259 | public void onFailure(Call call, Throwable t) { 260 | Timber.e(t.getMessage(), this); 261 | displayThrowable(t); 262 | } 263 | 264 | // 265 | // Private methods 266 | // 267 | private void clipboard(TextView tv) { 268 | // which view are we copying to the clipboard? 269 | int which; 270 | 271 | switch (tv.getId()) { 272 | case txt_request_url: // the url field 273 | which = req_url; 274 | break; 275 | 276 | case txt_response_headers: // the display headers 277 | which = response_headers; 278 | break; 279 | 280 | case txt_response_body: // the response body 281 | which = response_body; 282 | break; 283 | 284 | default: 285 | which = UNSET; // don't assign a prefix 286 | } 287 | 288 | // if we know which view we're copying, prefix it with useful info 289 | String what = which == UNSET ? "" : getString(which) + " "; 290 | 291 | // concat the clipboard data to this String 292 | what += getString(clippy); 293 | 294 | // inform the user that data was added to the clipboard 295 | Toast.makeText( 296 | getActivity(), 297 | what, 298 | Toast.LENGTH_SHORT 299 | ).show(); 300 | 301 | // depending on our API, do it one way or another... 302 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { 303 | // old way 304 | ClipboardManager clipboardManager = (ClipboardManager) 305 | getActivity().getSystemService(Context.CLIPBOARD_SERVICE); 306 | clipboardManager.setText(tv.getText()); 307 | } else { 308 | clipboard11(tv); 309 | } 310 | } 311 | 312 | @TargetApi(11) 313 | private void clipboard11(TextView tv) { 314 | android.content.ClipboardManager clipboardManager = 315 | (android.content.ClipboardManager) getActivity() 316 | .getSystemService(Context.CLIPBOARD_SERVICE); 317 | ClipData clipData = ClipData.newPlainText("RESTSnippets", tv.getText()); 318 | clipboardManager.setPrimaryClip(clipData); 319 | } 320 | 321 | private void launchUrl(Uri uri) { 322 | Intent viewDocs = new Intent(Intent.ACTION_VIEW, uri); 323 | startActivity(viewDocs); 324 | } 325 | 326 | private void displayResponse(Response response) { 327 | int color = getColor(response); 328 | displayStatusCode(Integer.toString(response.code()), getResources().getColor(color)); 329 | displayRequestUrl(response); 330 | maybeDisplayResponseHeaders(response); 331 | maybeDisplayResponseBody(response); 332 | } 333 | 334 | private void maybeDisplayResponseBody(Response response) { 335 | if (null != response.body()) { 336 | String body = null; 337 | try { 338 | body = ((ResponseBody) response.body()).string(); 339 | String formattedJson = new JSONObject(body).toString(2); 340 | mResponseBody.setText(formattedJson); 341 | } catch (JSONException e) { 342 | if (null != body) { 343 | // body wasn't JSON 344 | mResponseBody.setText(body); 345 | } else { 346 | // set the stack trace as the response body 347 | displayThrowable(e); 348 | } 349 | } catch (IOException ioe) { 350 | displayThrowable(ioe); 351 | } 352 | } 353 | } 354 | 355 | private void maybeDisplayResponseHeaders(Response response) { 356 | if (null != response.headers()) { 357 | Headers headers = response.headers(); 358 | String headerText = ""; 359 | 360 | for(int i = 0; i < headers.size(); i++){ 361 | headerText += headers.name(i) + " : " + headers.value(i) + "\n"; 362 | } 363 | 364 | mResponseHeaders.setText(headerText); 365 | } 366 | } 367 | 368 | private void displayRequestUrl(Response response) { 369 | String requestUrl = response.raw().request().url().toString(); 370 | mRequestUrl.setText(requestUrl); 371 | } 372 | 373 | private void displayStatusCode(String text, int color) { 374 | mStatusCode.setText(text); 375 | mStatusColor.setBackgroundColor(color); 376 | mStatusColor.setTag(color); 377 | } 378 | 379 | private void displayThrowable(Throwable t) { 380 | StringWriter sw = new StringWriter(); 381 | PrintWriter pw = new PrintWriter(sw); 382 | t.printStackTrace(pw); 383 | String trace = sw.toString(); 384 | mResponseBody.setText(trace); 385 | } 386 | 387 | private int getColor(Response response) { 388 | int color; 389 | switch (response.code() / 100) { 390 | case 1: 391 | case 2: 392 | color = code_1xx; 393 | break; 394 | case 3: 395 | color = code_3xx; 396 | break; 397 | case 4: 398 | case 5: 399 | color = code_4xx; 400 | break; 401 | default: 402 | color = transparent; 403 | } 404 | return color; 405 | } 406 | } 407 | -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/SnippetListActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp; 6 | 7 | import android.content.Context; 8 | import android.content.Intent; 9 | import android.os.Bundle; 10 | 11 | import com.microsoft.office365.msgraphsnippetapp.inject.AppModule; 12 | 13 | public class SnippetListActivity extends BaseActivity 14 | implements SnippetListFragment.Callbacks { 15 | 16 | private boolean mTwoPane; 17 | 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | setContentView(R.layout.activity_snippet_list); 22 | 23 | if (findViewById(R.id.snippet_detail_container) != null) { 24 | // The detail container view will be present only in the 25 | // large-screen layouts (res/values-large and 26 | // res/values-sw600dp). If this view is present, then the 27 | // activity should be in two-pane mode. 28 | mTwoPane = true; 29 | 30 | // In two-pane mode, list items should be given the 31 | // 'activated' state when touched. 32 | ((SnippetListFragment) getSupportFragmentManager() 33 | .findFragmentById(R.id.snippet_list)) 34 | .setActivateOnItemClick(true); 35 | } 36 | } 37 | 38 | @Override 39 | public void onItemSelected(int position) { 40 | if (mTwoPane) { 41 | // In two-pane mode, show the detail view in this activity by 42 | // adding or replacing the detail fragment using a 43 | // fragment transaction. 44 | Bundle arguments = new Bundle(); 45 | arguments.putInt(SnippetDetailFragment.ARG_ITEM_ID, position); 46 | SnippetDetailFragment fragment = new SnippetDetailFragment(); 47 | fragment.setArguments(arguments); 48 | getSupportFragmentManager().beginTransaction() 49 | .replace(R.id.snippet_detail_container, fragment) 50 | .commit(); 51 | } else { 52 | // In single-pane mode, simply start the detail activity 53 | // for the selected item ID. 54 | Intent detailIntent = new Intent(this, SnippetDetailActivity.class); 55 | detailIntent.putExtra(SnippetDetailFragment.ARG_ITEM_ID, position); 56 | startActivity(detailIntent); 57 | } 58 | } 59 | 60 | @Override 61 | public void onDisconnectClicked() { 62 | finish(); 63 | // drop the application shared preferences to clear any old auth tokens 64 | getSharedPreferences(AppModule.PREFS, Context.MODE_PRIVATE) 65 | .edit() // get the editor 66 | .clear() // clear it 67 | .apply(); // asynchronously apply 68 | mAuthenticationManager.disconnect(); 69 | Intent login = new Intent(this, SignInActivity.class); 70 | login.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 71 | startActivity(login); 72 | } 73 | } -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/SnippetListAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp; 6 | 7 | import android.content.Context; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.BaseAdapter; 12 | import android.widget.TextView; 13 | 14 | import com.microsoft.office365.msgraphsnippetapp.snippet.AbstractSnippet; 15 | import com.microsoft.office365.msgraphsnippetapp.snippet.SnippetContent; 16 | 17 | public class SnippetListAdapter extends BaseAdapter { 18 | 19 | private Context mContext; 20 | private LayoutInflater mLayoutInflater; 21 | 22 | @Override 23 | public int getCount() { 24 | return SnippetContent.ITEMS.size(); 25 | } 26 | 27 | @Override 28 | public AbstractSnippet getItem(int position) { 29 | return (AbstractSnippet) SnippetContent.ITEMS.get(position); 30 | } 31 | 32 | @Override 33 | public long getItemId(int position) { 34 | return 0; 35 | } 36 | 37 | @Override 38 | public boolean isEnabled(int position) { 39 | return null != getItem(position).getDescription(); 40 | } 41 | 42 | @Override 43 | public View getView(int position, View convertView, ViewGroup parent) { 44 | if (null == mContext) { 45 | mContext = parent.getContext(); 46 | mLayoutInflater = LayoutInflater.from(mContext); 47 | } 48 | 49 | AbstractSnippet clickedSnippet = getItem(position); 50 | boolean isSegment = (null == clickedSnippet.getDescription()); 51 | 52 | final int id = isSegment ? R.layout.list_segment : R.layout.list_element; 53 | if (null == convertView || isWrongViewType(isSegment, convertView)) { 54 | convertView = mLayoutInflater.inflate(id, parent, false); 55 | } 56 | 57 | TextView name = (TextView) convertView.findViewById(R.id.txt_snippet_name); 58 | name.setText(clickedSnippet.getName()); 59 | 60 | //Set text to indicate if Admin account is required to run the snippet 61 | if (!isSegment) { 62 | TextView adminIndicator = (TextView) convertView.findViewById(R.id.admin_indicator); 63 | if (adminIndicator != null) { 64 | if (clickedSnippet.getIsAdminRequiredAdmin()) { 65 | //Admin account required 66 | adminIndicator.setText(R.string.admin); 67 | adminIndicator.setVisibility(View.VISIBLE); 68 | } else { 69 | //Admin account not required 70 | adminIndicator.setVisibility(View.GONE); 71 | } 72 | } 73 | } 74 | 75 | //Set text to indicate if this is a beta version snippet 76 | if (!isSegment) { 77 | if (clickedSnippet.isBeta()) { 78 | TextView betaIndicator = (TextView) convertView.findViewById(R.id.beta_indicator); 79 | betaIndicator.setText(R.string.beta); 80 | betaIndicator.setVisibility(View.VISIBLE); 81 | } else { 82 | TextView betaIndicator = (TextView) convertView.findViewById(R.id.beta_indicator); 83 | betaIndicator.setVisibility(View.GONE); 84 | } 85 | } 86 | 87 | 88 | return convertView; 89 | } 90 | 91 | private boolean isWrongViewType(boolean isSegment, View convertView) { 92 | View v = convertView.findViewById(R.id.admin_indicator); 93 | return !isSegment && null == v || (isSegment && null != v); 94 | } 95 | 96 | } -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/SnippetListFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp; 6 | 7 | import android.content.Context; 8 | import android.os.Bundle; 9 | import android.support.v4.app.ListFragment; 10 | import android.view.Menu; 11 | import android.view.MenuInflater; 12 | import android.view.MenuItem; 13 | import android.view.View; 14 | import android.widget.ListView; 15 | 16 | public class SnippetListFragment extends ListFragment { 17 | 18 | private static final String STATE_ACTIVATED_POSITION = "activated_position"; 19 | private static Callbacks sDummyCallbacks = new Callbacks() { 20 | @Override 21 | public void onItemSelected(int position) { 22 | } 23 | 24 | @Override 25 | public void onDisconnectClicked() { 26 | } 27 | }; 28 | private Callbacks mCallbacks = sDummyCallbacks; 29 | private int mActivatedPosition = ListView.INVALID_POSITION; 30 | 31 | public SnippetListFragment() { 32 | } 33 | 34 | @Override 35 | public void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | setHasOptionsMenu(true); 38 | setListAdapter(new SnippetListAdapter()); 39 | } 40 | 41 | @Override 42 | public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 43 | inflater.inflate(R.menu.snippet_list_menu, menu); 44 | super.onCreateOptionsMenu(menu, inflater); 45 | } 46 | 47 | @Override 48 | public boolean onOptionsItemSelected(MenuItem item) { 49 | if (R.id.disconnect == item.getItemId()) { 50 | mCallbacks.onDisconnectClicked(); 51 | return true; 52 | } 53 | return super.onOptionsItemSelected(item); 54 | } 55 | 56 | @Override 57 | public void onViewCreated(View view, Bundle savedInstanceState) { 58 | super.onViewCreated(view, savedInstanceState); 59 | 60 | // Restore the previously serialized activated item position. 61 | if (savedInstanceState != null 62 | && savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) { 63 | setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION)); 64 | } 65 | } 66 | 67 | @Override 68 | public void onAttach(Context context) { 69 | super.onAttach(context); 70 | 71 | // Activities containing this fragment must implement its callbacks. 72 | if (!(context instanceof Callbacks)) { 73 | throw new IllegalStateException("Activity must implement fragment's callbacks."); 74 | } 75 | 76 | mCallbacks = (Callbacks) context; 77 | } 78 | 79 | @Override 80 | public void onDetach() { 81 | super.onDetach(); 82 | 83 | // Reset the active callbacks interface to the dummy implementation. 84 | mCallbacks = sDummyCallbacks; 85 | } 86 | 87 | @Override 88 | public void onListItemClick(ListView listView, View view, int position, long id) { 89 | super.onListItemClick(listView, view, position, id); 90 | mCallbacks.onItemSelected(position); 91 | } 92 | 93 | @Override 94 | public void onSaveInstanceState(Bundle outState) { 95 | super.onSaveInstanceState(outState); 96 | if (mActivatedPosition != ListView.INVALID_POSITION) { 97 | // Serialize and persist the activated item position. 98 | outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition); 99 | } 100 | } 101 | 102 | public void setActivateOnItemClick(boolean activateOnItemClick) { 103 | // When setting CHOICE_MODE_SINGLE, ListView will automatically 104 | // give items the 'activated' state when touched. 105 | getListView().setChoiceMode(activateOnItemClick 106 | ? ListView.CHOICE_MODE_SINGLE 107 | : ListView.CHOICE_MODE_NONE); 108 | } 109 | 110 | private void setActivatedPosition(int position) { 111 | if (position == ListView.INVALID_POSITION) { 112 | getListView().setItemChecked(mActivatedPosition, false); 113 | } else { 114 | getListView().setItemChecked(position, true); 115 | } 116 | 117 | mActivatedPosition = position; 118 | } 119 | 120 | public interface Callbacks { 121 | void onItemSelected(int position); 122 | 123 | void onDisconnectClicked(); 124 | } 125 | } -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/application/SnippetApp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp.application; 6 | 7 | import android.app.Application; 8 | 9 | import com.microsoft.office365.msgraphsnippetapp.BuildConfig; 10 | import com.microsoft.office365.msgraphsnippetapp.inject.AppModule; 11 | 12 | import javax.inject.Inject; 13 | 14 | import dagger.ObjectGraph; 15 | import okhttp3.Interceptor; 16 | import okhttp3.OkHttpClient; 17 | import okhttp3.logging.HttpLoggingInterceptor; 18 | import retrofit2.Retrofit; 19 | import retrofit2.converter.gson.GsonConverterFactory; 20 | import timber.log.Timber; 21 | 22 | public class SnippetApp extends Application { 23 | private static SnippetApp sSnippetApp; 24 | /** 25 | * The {@link dagger.ObjectGraph} used by Dagger to fulfill @inject annotations 26 | * 27 | * @see javax.inject.Inject 28 | * @see dagger.Provides 29 | * @see javax.inject.Singleton 30 | */ 31 | public ObjectGraph mObjectGraph; 32 | 33 | @Inject 34 | protected String endpoint; 35 | 36 | @Inject 37 | protected HttpLoggingInterceptor.Level logLevel; 38 | 39 | @Inject 40 | protected Interceptor interceptor; 41 | 42 | public static SnippetApp getApp() { 43 | return sSnippetApp; 44 | } 45 | 46 | @Override 47 | public void onCreate() { 48 | super.onCreate(); 49 | sSnippetApp = this; 50 | mObjectGraph = ObjectGraph.create(new AppModule()); 51 | mObjectGraph.inject(this); 52 | if (BuildConfig.DEBUG) { 53 | Timber.plant(new Timber.DebugTree()); 54 | } 55 | } 56 | 57 | public Retrofit getRetrofit() { 58 | HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); 59 | logging.setLevel(logLevel); 60 | 61 | OkHttpClient client = new OkHttpClient.Builder() 62 | .addInterceptor(interceptor) 63 | .addInterceptor(logging) 64 | .build(); 65 | 66 | return new Retrofit.Builder() 67 | .baseUrl(endpoint) 68 | .client(client) 69 | .addConverterFactory(GsonConverterFactory.create()) 70 | .build(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/inject/AppModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp.inject; 6 | 7 | import android.content.Context; 8 | import android.content.SharedPreferences; 9 | 10 | import com.microsoft.office365.msgraphsnippetapp.ServiceConstants; 11 | import com.microsoft.office365.msgraphsnippetapp.application.SnippetApp; 12 | import com.microsoft.office365.msgraphsnippetapp.util.SharedPrefsUtil; 13 | 14 | import java.io.IOException; 15 | 16 | import dagger.Module; 17 | import dagger.Provides; 18 | import okhttp3.Interceptor; 19 | import okhttp3.Request; 20 | import okhttp3.Response; 21 | import okhttp3.logging.HttpLoggingInterceptor.Level; 22 | 23 | @Module(library = true, 24 | injects = {SnippetApp.class} 25 | ) 26 | public class AppModule { 27 | 28 | public static final String PREFS = "com.microsoft.o365_android_unified_API_REST_snippets"; 29 | 30 | @Provides 31 | @SuppressWarnings("unused") // not actually unused -- used by Dagger 32 | public String providesRestEndpoint() { 33 | return ServiceConstants.AUTHENTICATION_RESOURCE_ID; 34 | } 35 | 36 | @Provides 37 | @SuppressWarnings("unused") // not actually unused -- used by Dagger 38 | public Level providesLogLevel() { 39 | return Level.BODY; 40 | } 41 | 42 | @Provides 43 | @SuppressWarnings("unused") // not actually unused -- used by Dagger 44 | public Interceptor providesRequestInterceptor() { 45 | return new Interceptor() { 46 | @Override 47 | public Response intercept(Chain chain) throws IOException { 48 | // apply the Authorization header if we had a token... 49 | final SharedPreferences preferences 50 | = SnippetApp.getApp().getSharedPreferences(PREFS, Context.MODE_PRIVATE); 51 | final String token = 52 | preferences.getString(SharedPrefsUtil.PREF_AUTH_TOKEN, null); 53 | 54 | Request request = chain.request(); 55 | request = request.newBuilder() 56 | .addHeader("Authorization", "Bearer " + token) 57 | // This header has been added to identify this sample in the Microsoft Graph service. 58 | // If you're using this code for your project please remove the following line. 59 | .addHeader("SampleID", "android-java-snippets-rest-sample") 60 | .build(); 61 | 62 | Response response = chain.proceed(request); 63 | return response; 64 | } 65 | }; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/inject/AzureModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp.inject; 6 | 7 | import com.microsoft.office365.auth.AzureADModule; 8 | import com.microsoft.office365.msgraphsnippetapp.SignInActivity; 9 | import com.microsoft.office365.msgraphsnippetapp.SnippetDetailActivity; 10 | import com.microsoft.office365.msgraphsnippetapp.SnippetDetailFragment; 11 | import com.microsoft.office365.msgraphsnippetapp.SnippetListActivity; 12 | 13 | import dagger.Module; 14 | 15 | @Module(includes = AzureADModule.class, 16 | complete = false, 17 | injects = { 18 | SignInActivity.class, 19 | SnippetDetailActivity.class, 20 | SnippetListActivity.class, 21 | SnippetDetailFragment.class 22 | } 23 | ) 24 | public class AzureModule {} -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/inject/ObjectGraphInjector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp.inject; 6 | 7 | public interface ObjectGraphInjector { 8 | 9 | void inject(Object target); 10 | 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/snippet/AbstractSnippet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp.snippet; 6 | 7 | import com.microsoft.office365.msgraphsnippetapp.application.SnippetApp; 8 | 9 | import retrofit2.Callback; 10 | 11 | import static com.microsoft.office365.msgraphsnippetapp.R.string.beta; 12 | 13 | public abstract class AbstractSnippet { 14 | 15 | private static final int mNameIndex = 0; 16 | private static final int mDescIndex = 1; 17 | private static final int mUrlIndex = 2; 18 | private static final int mO365VersionIndex = 3; 19 | private static final int mIsAdminRequiredIndex = 4; 20 | 21 | public final Service mService; 22 | boolean mIsAdminRequired; 23 | private String mName, mDesc, mUrl, mO365Version; 24 | 25 | /** 26 | * Snippet constructor 27 | * 28 | * @param category Snippet category as corresponds to UI displayed sections (organization, me, groups, etc...) 29 | * @param descriptionArray The String array for the specified snippet 30 | */ 31 | public AbstractSnippet( 32 | SnippetCategory category, 33 | Integer descriptionArray) { 34 | //Get snippet configuration information from the 35 | //XML configuration for the snippet 36 | getSnippetArrayContent(category, descriptionArray); 37 | 38 | mService = category.mService; 39 | } 40 | 41 | 42 | /** 43 | * Gets the items from the specified snippet XML string array and stores the values 44 | * in private class fields 45 | * 46 | * @param category Snippet category as corresponds to UI displayed sections (organization, me, groups, etc...) 47 | * @param descriptionArray The String array for the specified snippet 48 | */ 49 | private void getSnippetArrayContent(SnippetCategory category, Integer descriptionArray) { 50 | if (null != descriptionArray) { 51 | String[] params = SnippetApp.getApp().getResources().getStringArray(descriptionArray); 52 | 53 | try { 54 | mName = params[mNameIndex]; 55 | mDesc = params[mDescIndex]; 56 | mUrl = params[mUrlIndex]; 57 | mO365Version = params[mO365VersionIndex]; 58 | String isAdminRequired = params[mIsAdminRequiredIndex]; 59 | mIsAdminRequired = isAdminRequired.equalsIgnoreCase("true"); 60 | } catch (IndexOutOfBoundsException ex) { 61 | throw new RuntimeException( 62 | "Invalid array in " 63 | + category.mSection 64 | + " snippet XML file" 65 | , ex); 66 | } 67 | } else { 68 | mName = category.mSection; 69 | mDesc = mUrl = null; 70 | mO365Version = null; 71 | 72 | } 73 | } 74 | 75 | /** 76 | * Returns the version segment of the endpoint url with input from 77 | * XML snippet description 78 | * 79 | * @return Which version of the endpoint to use (beta, v1, etc...) 80 | */ 81 | protected String getVersion() { 82 | return mO365Version; 83 | } 84 | 85 | public boolean isBeta() { 86 | String betaString = SnippetApp.getApp().getString(beta); 87 | return mO365Version.equalsIgnoreCase(betaString); 88 | } 89 | 90 | public String getName() { 91 | return mName; 92 | } 93 | 94 | public String getDescription() { 95 | return mDesc; 96 | } 97 | 98 | public String getUrl() { 99 | return mUrl; 100 | } 101 | 102 | public boolean getIsAdminRequiredAdmin() { 103 | return mIsAdminRequired; 104 | } 105 | 106 | public abstract void request(Service service, Callback callback); 107 | 108 | } 109 | -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/snippet/ContactsSnippets.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp.snippet; 6 | 7 | import com.microsoft.office365.msgraphapiservices.MSGraphContactService; 8 | 9 | import okhttp3.ResponseBody; 10 | import retrofit2.Callback; 11 | 12 | import static com.microsoft.office365.msgraphsnippetapp.R.array.get_all_contacts; 13 | 14 | public abstract class ContactsSnippets extends AbstractSnippet { 15 | 16 | public ContactsSnippets(Integer descriptionArray) { 17 | super(SnippetCategory.contactSnippetCategory, descriptionArray); 18 | } 19 | 20 | 21 | static ContactsSnippets[] getContactsSnippets() { 22 | return new ContactsSnippets[]{ 23 | // Marker element 24 | new ContactsSnippets(null) { 25 | @Override 26 | public void request(MSGraphContactService service, Callback callback) { 27 | // Not implemented 28 | } 29 | }, 30 | // Snippets 31 | 32 | /* Get all of the user's contacts 33 | * HTTP GET https://graph.microsoft.com/{version}/myOrganization/contacts 34 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/api/user_list_contacts 35 | */ 36 | new ContactsSnippets(get_all_contacts) { 37 | @Override 38 | public void request(MSGraphContactService service, Callback callback) { 39 | service.getContacts(getVersion()).enqueue(callback); 40 | } 41 | } 42 | }; 43 | } 44 | 45 | @Override 46 | public abstract void request(MSGraphContactService service, Callback callback); 47 | 48 | } -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/snippet/EventsSnippets.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp.snippet; 6 | 7 | import com.microsoft.office365.microsoftgraphvos.Attendee; 8 | import com.microsoft.office365.microsoftgraphvos.DateTimeTimeZone; 9 | import com.microsoft.office365.microsoftgraphvos.EmailAddress; 10 | import com.microsoft.office365.microsoftgraphvos.Event; 11 | import com.microsoft.office365.microsoftgraphvos.ItemBody; 12 | import com.microsoft.office365.microsoftgraphvos.Location; 13 | import com.microsoft.office365.msgraphapiservices.MSGraphEventsService; 14 | 15 | import org.joda.time.DateTime; 16 | import org.json.JSONException; 17 | import org.json.JSONObject; 18 | 19 | import java.io.IOException; 20 | 21 | import okhttp3.ResponseBody; 22 | import retrofit2.Call; 23 | import retrofit2.Callback; 24 | import retrofit2.Response; 25 | 26 | import static com.microsoft.office365.msgraphsnippetapp.R.array.create_event; 27 | import static com.microsoft.office365.msgraphsnippetapp.R.array.delete_event; 28 | import static com.microsoft.office365.msgraphsnippetapp.R.array.get_user_events; 29 | import static com.microsoft.office365.msgraphsnippetapp.R.array.update_event; 30 | 31 | public abstract class EventsSnippets extends AbstractSnippet { 32 | 33 | public EventsSnippets(Integer descriptionArray) { 34 | super(SnippetCategory.eventsSnippetCategory, descriptionArray); 35 | } 36 | 37 | static EventsSnippets[] getEventsSnippets() { 38 | return new EventsSnippets[]{ 39 | // Marker element 40 | new EventsSnippets(null) { 41 | 42 | @Override 43 | public void request(MSGraphEventsService o, Callback callback) { 44 | //No implementation 45 | } 46 | }, 47 | //Snippets 48 | 49 | /* 50 | * Get all events for the signed in user. 51 | * GET https://graph.microsoft.com/{version}/me/events 52 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/api/user_list_events 53 | */ 54 | new EventsSnippets(get_user_events) { 55 | 56 | @Override 57 | public void request( 58 | MSGraphEventsService MSGraphEventsService, 59 | Callback callback) { 60 | MSGraphEventsService.getEvents(getVersion()).enqueue(callback); 61 | } 62 | }, 63 | 64 | /* 65 | * Adds an event to the signed-in user\'s calendar. 66 | * POST https://graph.microsoft.com/{version}/me/events 67 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/api/user_post_events 68 | */ 69 | new EventsSnippets(create_event) { 70 | 71 | @Override 72 | public void request( 73 | MSGraphEventsService MSGraphEventsService, 74 | Callback callback) { 75 | MSGraphEventsService.createNewEvent(getVersion(), createEvent()).enqueue(callback); 76 | } 77 | 78 | }, 79 | /* 80 | * Update an event 81 | * PATCH https://graph.microsoft.com/{version}/me/events/{Event.Id} 82 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/api/event_update 83 | */ 84 | new EventsSnippets(update_event) { 85 | 86 | @Override 87 | public void request( 88 | final MSGraphEventsService MSGraphEventsService, 89 | final Callback callback) { 90 | // create a new event to update 91 | MSGraphEventsService.createNewEvent( 92 | getVersion(), 93 | createEvent()).enqueue( 94 | new Callback() { 95 | @Override 96 | public void onResponse(Call call, Response response) { 97 | try { 98 | String eventId = new JSONObject(response.body().string()).getString("id"); 99 | // now that the event has been created, 100 | // let's change the subject 101 | Event amended = new Event(); 102 | amended.subject = "Weekly Sync Meeting"; 103 | 104 | MSGraphEventsService.updateEvent( 105 | getVersion(), 106 | eventId, 107 | amended).enqueue(callback); 108 | } catch(JSONException | IOException e) { 109 | callback.onFailure(call, e); 110 | } 111 | } 112 | 113 | @Override 114 | public void onFailure(Call call, Throwable t) { 115 | callback.onFailure(call, t); 116 | } 117 | } 118 | ); 119 | } 120 | 121 | }, 122 | /* 123 | * Delete an event 124 | * DELETE https://graph.microsoft.com/{version}/me/events/{Event.Id} 125 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/api/event_delete 126 | */ 127 | new EventsSnippets(delete_event) { 128 | 129 | @Override 130 | public void request( 131 | final MSGraphEventsService MSGraphEventsService, 132 | final Callback callback) { 133 | // create a new event to delete 134 | Event event = createEvent(); 135 | MSGraphEventsService.createNewEvent( 136 | getVersion(), 137 | event).enqueue( 138 | new Callback() { 139 | @Override 140 | public void onResponse(Call call, Response response) { 141 | try { 142 | String eventId = new JSONObject(response.body().string()).getString("id"); 143 | // event created, now let's delete it 144 | MSGraphEventsService.deleteEvent( 145 | getVersion(), 146 | eventId).enqueue(callback); 147 | } catch(JSONException | IOException e) { 148 | callback.onFailure(call, e); 149 | } 150 | } 151 | 152 | @Override 153 | public void onFailure(Call call, Throwable t) { 154 | callback.onFailure(call, t); 155 | } 156 | } 157 | ); 158 | } 159 | } 160 | }; 161 | } 162 | 163 | public abstract void request(MSGraphEventsService service, Callback callback); 164 | 165 | public static Event createEvent() { 166 | Event event = new Event(); 167 | event.subject = "Microsoft Graph API Discussion"; 168 | 169 | // set start time to now 170 | DateTimeTimeZone start = new DateTimeTimeZone(); 171 | start.dateTime = DateTime.now().toString(); 172 | event.start = start; 173 | 174 | // and end in 1 hr 175 | DateTimeTimeZone end = new DateTimeTimeZone(); 176 | end.dateTime = DateTime.now().plusHours(1).toString(); 177 | event.end = end; 178 | 179 | // set the timezone 180 | start.timeZone = end.timeZone = "UTC"; 181 | 182 | // set a location 183 | Location location = new Location(); 184 | location.displayName = "Bill's Office"; 185 | event.location = location; 186 | 187 | // add attendees 188 | Attendee attendee = new Attendee(); 189 | attendee.type = Attendee.TYPE_REQUIRED; 190 | attendee.emailAddress = new EmailAddress(); 191 | attendee.emailAddress.address = "mara@fabrikam.com"; 192 | event.attendees = new Attendee[]{attendee}; 193 | 194 | // add a msg 195 | ItemBody msg = new ItemBody(); 196 | msg.content = "Let's discuss the power of the Office 365 unified API."; 197 | msg.contentType = ItemBody.CONTENT_TYPE_TEXT; 198 | event.body = msg; 199 | 200 | return event; 201 | } 202 | 203 | } -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/snippet/GroupsSnippets.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp.snippet; 6 | 7 | import com.microsoft.office365.microsoftgraphvos.Group; 8 | import com.microsoft.office365.msgraphapiservices.MSGraphGroupsService; 9 | 10 | import org.json.JSONException; 11 | import org.json.JSONObject; 12 | 13 | import java.io.IOException; 14 | import java.util.HashMap; 15 | import java.util.Map; 16 | import java.util.UUID; 17 | 18 | import okhttp3.ResponseBody; 19 | import retrofit2.Call; 20 | import retrofit2.Callback; 21 | import retrofit2.Response; 22 | import timber.log.Timber; 23 | 24 | import static com.microsoft.office365.msgraphsnippetapp.R.array.delete_a_group; 25 | import static com.microsoft.office365.msgraphsnippetapp.R.array.get_a_group; 26 | import static com.microsoft.office365.msgraphsnippetapp.R.array.get_all_groups; 27 | import static com.microsoft.office365.msgraphsnippetapp.R.array.get_group_members; 28 | import static com.microsoft.office365.msgraphsnippetapp.R.array.get_group_owners; 29 | import static com.microsoft.office365.msgraphsnippetapp.R.array.insert_a_group; 30 | import static com.microsoft.office365.msgraphsnippetapp.R.array.update_a_group; 31 | 32 | public abstract class GroupsSnippets extends AbstractSnippet { 33 | 34 | public GroupsSnippets(Integer descriptionArray) { 35 | super(SnippetCategory.groupSnippetCategory, descriptionArray); 36 | } 37 | 38 | static GroupsSnippets[] getGroupsSnippets() { 39 | return new GroupsSnippets[]{ 40 | // Marker element 41 | new GroupsSnippets(null) { 42 | @Override 43 | public void request(MSGraphGroupsService service, Callback callback) { 44 | // Not implemented 45 | } 46 | }, 47 | // Snippets 48 | 49 | /* 50 | * Get a group by id 51 | * GET https://graph.microsoft.com/{version}/myOrganization/groups/{Group.objectId} 52 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/api/group_get 53 | */ 54 | new GroupsSnippets(get_a_group) { 55 | @Override 56 | public void request(final MSGraphGroupsService service, 57 | final Callback callback) { 58 | // create a group then query it 59 | service.createGroup(getVersion(), createGroup()).enqueue(new Callback() { 60 | @Override 61 | public void onResponse(Call call, Response response) { 62 | try { 63 | String groupId = new JSONObject(response.body().string()).getString("id"); 64 | // request the newly created group 65 | service.getGroup(getVersion(), groupId).enqueue(callback); 66 | } catch(JSONException | IOException e) { 67 | callback.onFailure(call, e); 68 | } 69 | } 70 | 71 | @Override 72 | public void onFailure(Call call, Throwable t) { 73 | callback.onFailure(call, t); 74 | } 75 | }); 76 | } 77 | }, 78 | /* Get all of the members of a newly created organization group 79 | * GET https://graph.microsoft.com/{version}/myOrganization/groups/{Group.objectId}/members 80 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/api/group_list_members 81 | */ 82 | new GroupsSnippets(get_group_members) { 83 | @Override 84 | public void request(final MSGraphGroupsService service, 85 | final Callback callback) { 86 | // create a group then ask for its members 87 | service.createGroup(getVersion(), createGroup()).enqueue(new Callback() { 88 | @Override 89 | public void onResponse(Call call, Response response) { 90 | try { 91 | String groupId = new JSONObject(response.body().string()).getString("id"); 92 | service.getGroupEntities( 93 | getVersion(), 94 | groupId, 95 | "members").enqueue(callback); 96 | } catch(JSONException | IOException e) { 97 | callback.onFailure(call, e); 98 | } 99 | } 100 | 101 | @Override 102 | public void onFailure(Call call, Throwable t) { 103 | Timber.e(t.getMessage(), this); 104 | } 105 | }); 106 | } 107 | }, 108 | 109 | /* Get all of a group's owners 110 | * GET https://graph.microsoft.com/{version}/myOrganization/groups/{Group.objectId}/owners 111 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/api/group_list_owners 112 | */ 113 | new GroupsSnippets(get_group_owners) { 114 | @Override 115 | public void request(final MSGraphGroupsService service, 116 | final Callback callback) { 117 | // create a group and then request its owner 118 | service.createGroup(getVersion(), createGroup()).enqueue(new Callback() { 119 | @Override 120 | public void onResponse(Call call, Response response) { 121 | try { 122 | String groupId = new JSONObject(response.body().string()).getString("id"); 123 | service.getGroupEntities( 124 | getVersion(), 125 | groupId, 126 | "owners").enqueue(callback); 127 | } catch(JSONException | IOException e) { 128 | callback.onFailure(call, e); 129 | } 130 | 131 | } 132 | 133 | @Override 134 | public void onFailure(Call call, Throwable t) { 135 | Timber.e(t.getMessage(), this); 136 | } 137 | }); 138 | } 139 | }, 140 | /* List all organization groups 141 | * GET https://graph.microsoft.com/v1.0/groups 142 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/api/group_list 143 | */ 144 | new GroupsSnippets(get_all_groups) { 145 | @Override 146 | public void request(MSGraphGroupsService service, 147 | Callback callback) { 148 | Map filters = new HashMap<>(); 149 | service.getGroups(getVersion(), filters).enqueue(callback); 150 | } 151 | }, 152 | 153 | /* Create a new group with a random name 154 | * POST https://graph.microsoft.com/{version}/myOrganization/groups 155 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/resources/group 156 | */ 157 | new GroupsSnippets(insert_a_group) { 158 | 159 | @Override 160 | public void request(final MSGraphGroupsService service, 161 | Callback callback) { 162 | service.createGroup(getVersion(), createGroup()).enqueue(callback); 163 | } 164 | }, 165 | 166 | /* Update a group 167 | * PATCH https://graph.microsoft.com/{version}/myOrganization/groups/{Group.objectId} 168 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/api/group_update 169 | */ 170 | new GroupsSnippets(update_a_group) { 171 | 172 | @Override 173 | public void request(final MSGraphGroupsService service, 174 | final Callback callback) { 175 | //Create a group that we will update 176 | service.createGroup(getVersion(), createGroup()).enqueue(new Callback() { 177 | 178 | @Override 179 | public void onResponse(Call call, Response response) { 180 | try { 181 | String groupId = new JSONObject(response.body().string()).getString("id"); 182 | Group amended = new Group(); 183 | amended.displayName = "A renamed group"; 184 | //Update the group we created 185 | service.updateGroup( 186 | getVersion(), 187 | groupId, 188 | amended).enqueue(callback); 189 | } catch(JSONException | IOException e) { 190 | callback.onFailure(call, e); 191 | } 192 | } 193 | 194 | @Override 195 | public void onFailure(Call call, Throwable t) { 196 | //pass along error to original callback 197 | Timber.e(t.getMessage(), this); 198 | } 199 | }); 200 | } 201 | }, 202 | 203 | /* Delete a group 204 | * DELETE https://graph.microsoft.com/{version}/myOrganization/groups/{Group.objectId} 205 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/api/group_delete 206 | */ 207 | new GroupsSnippets(delete_a_group) { 208 | 209 | @Override 210 | public void request(final MSGraphGroupsService service, 211 | final Callback callback) { 212 | //Create a group that we will delete 213 | service.createGroup(getVersion(), createGroup()).enqueue(new Callback() { 214 | 215 | @Override 216 | public void onResponse(Call call, Response response) { 217 | try { 218 | String groupId = new JSONObject(response.body().string()).getString("id"); 219 | //Delete the group we created 220 | service.deleteGroup(getVersion(), groupId).enqueue(callback); 221 | } catch(JSONException | IOException e) { 222 | callback.onFailure(call, e); 223 | } 224 | } 225 | 226 | @Override 227 | public void onFailure(Call call, Throwable t) { 228 | //pass along error to original callback 229 | Timber.e(t.getMessage(), this); 230 | } 231 | }); 232 | } 233 | } 234 | }; 235 | } 236 | 237 | @Override 238 | public abstract void request(MSGraphGroupsService service, Callback callback); 239 | 240 | public static Group createGroup() { 241 | Group group = new Group(); 242 | group.displayName = group.mailNickname = UUID.randomUUID().toString(); 243 | return group; 244 | } 245 | 246 | } -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/snippet/MeSnippets.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp.snippet; 6 | 7 | import com.microsoft.office365.msgraphapiservices.MSGraphMeService; 8 | import com.microsoft.office365.msgraphsnippetapp.R; 9 | import com.microsoft.office365.msgraphsnippetapp.application.SnippetApp; 10 | 11 | import okhttp3.ResponseBody; 12 | import retrofit2.Callback; 13 | 14 | import static com.microsoft.office365.msgraphsnippetapp.R.array.get_me; 15 | import static com.microsoft.office365.msgraphsnippetapp.R.array.get_me_direct_reports; 16 | import static com.microsoft.office365.msgraphsnippetapp.R.array.get_me_group_membership; 17 | import static com.microsoft.office365.msgraphsnippetapp.R.array.get_me_manager; 18 | import static com.microsoft.office365.msgraphsnippetapp.R.array.get_me_photo; 19 | import static com.microsoft.office365.msgraphsnippetapp.R.array.get_me_responsibilities; 20 | 21 | public abstract class MeSnippets extends AbstractSnippet { 22 | /** 23 | * Snippet constructor 24 | * 25 | * @param descriptionArray The String array for the specified snippet 26 | */ 27 | public MeSnippets(Integer descriptionArray) { 28 | super(SnippetCategory.meSnippetCategory, descriptionArray); 29 | } 30 | 31 | static MeSnippets[] getMeSnippets() { 32 | return new MeSnippets[]{ 33 | // Marker element 34 | new MeSnippets(null) { 35 | @Override 36 | public void request(MSGraphMeService service, Callback callback) { 37 | // Not implemented 38 | } 39 | }, 40 | // Snippets 41 | 42 | /* Get information about signed in user 43 | * HTTP GET https://graph.microsoft.com/{version}/me 44 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/api/user_get 45 | */ 46 | new MeSnippets(get_me) { 47 | @Override 48 | public void request(MSGraphMeService service, Callback callback) { 49 | service.getMe(getVersion()).enqueue(callback); 50 | } 51 | }, 52 | 53 | /* Get responsibilities of signed in user 54 | * HTTP GET https://graph.microsoft.com/{version}/me?$select=AboutMe,Responsibilities,Tags 55 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/resources/user 56 | */ 57 | new MeSnippets(get_me_responsibilities) { 58 | @Override 59 | public void request(MSGraphMeService service, Callback callback) { 60 | service.getMeResponsibilities( 61 | getVersion(), 62 | SnippetApp.getApp().getString(R.string.meResponsibility) 63 | ).enqueue(callback); 64 | } 65 | }, 66 | 67 | /* Get the user's manager 68 | * HTTP GET https://graph.microsoft.com/{version}/me/manager 69 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/resources/user 70 | */ 71 | new MeSnippets(get_me_manager) { 72 | @Override 73 | public void request(MSGraphMeService service, Callback callback) { 74 | service.getMeEntities( 75 | getVersion(), 76 | SnippetApp.getApp().getString(R.string.manager) 77 | ).enqueue(callback); 78 | } 79 | }, 80 | 81 | /* Get the user's direct reports 82 | * HTTP GET https://graph.microsoft.com/{version}/me/directReports 83 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/resources/user 84 | */ 85 | new MeSnippets(get_me_direct_reports) { 86 | @Override 87 | public void request(MSGraphMeService service, Callback callback) { 88 | service.getMeEntities(getVersion(), 89 | SnippetApp.getApp().getString(R.string.directReports) 90 | ).enqueue(callback); 91 | } 92 | }, 93 | 94 | /* Get the group membership of the user 95 | * HTTP GET https://graph.microsoft.com/{version}/me/memberOf 96 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/resources/user 97 | */ 98 | new MeSnippets(get_me_group_membership) { 99 | @Override 100 | public void request(MSGraphMeService service, Callback callback) { 101 | service.getMeEntities( 102 | getVersion(), 103 | SnippetApp.getApp().getString(R.string.memberOf) 104 | ).enqueue(callback); 105 | } 106 | }, 107 | 108 | /* Get the photo of the user 109 | * HTTP GET https://graph.microsoft.com/{version}/me/userPhoto 110 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/resources/user 111 | */ 112 | new MeSnippets(get_me_photo) { 113 | @Override 114 | public void request(MSGraphMeService service, Callback callback) { 115 | service.getMeEntities( 116 | getVersion(), 117 | SnippetApp.getApp().getString(R.string.userPhoto) 118 | ).enqueue(callback); 119 | } 120 | } 121 | }; 122 | } 123 | 124 | @Override 125 | public abstract void request(MSGraphMeService service, Callback callback); 126 | 127 | } 128 | -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/snippet/MessageSnippets.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp.snippet; 6 | 7 | import android.content.SharedPreferences; 8 | 9 | import com.microsoft.office365.microsoftgraphvos.EmailAddress; 10 | import com.microsoft.office365.microsoftgraphvos.ItemBody; 11 | import com.microsoft.office365.microsoftgraphvos.Message; 12 | import com.microsoft.office365.microsoftgraphvos.MessageWrapper; 13 | import com.microsoft.office365.microsoftgraphvos.RecipientVO; 14 | import com.microsoft.office365.msgraphapiservices.MSGraphMailService; 15 | import com.microsoft.office365.msgraphsnippetapp.R; 16 | import com.microsoft.office365.msgraphsnippetapp.application.SnippetApp; 17 | import com.microsoft.office365.msgraphsnippetapp.util.SharedPrefsUtil; 18 | 19 | import okhttp3.ResponseBody; 20 | import retrofit2.Callback; 21 | 22 | import static com.microsoft.office365.msgraphsnippetapp.R.array.get_user_messages; 23 | import static com.microsoft.office365.msgraphsnippetapp.R.array.send_an_email_message; 24 | 25 | public abstract class MessageSnippets extends AbstractSnippet { 26 | /** 27 | * Snippet constructor 28 | * 29 | * @param descriptionArray The String array for the specified snippet 30 | */ 31 | public MessageSnippets(Integer descriptionArray) { 32 | super(SnippetCategory.mailSnippetCategory, descriptionArray); 33 | } 34 | 35 | static MessageSnippets[] getMessageSnippets() { 36 | return new MessageSnippets[]{ 37 | // Marker element 38 | new MessageSnippets(null) { 39 | @Override 40 | public void request(MSGraphMailService service, Callback callback) { 41 | // Not implemented 42 | } 43 | }, 44 | // Snippets 45 | 46 | /* Get messages from mailbox for signed in user 47 | * HTTP GET https://graph.microsoft.com/{version}/me/messages 48 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/api/user_list_messages 49 | */ 50 | new MessageSnippets(get_user_messages) { 51 | @Override 52 | public void request(MSGraphMailService service, Callback callback) { 53 | service.getMail(getVersion()).enqueue(callback); 54 | } 55 | }, 56 | 57 | /* Sends an email message on behalf of the signed in user 58 | * HTTP POST https://graph.microsoft.com/{version}/me/messages/sendMail 59 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/api/user_post_messages 60 | */ 61 | new MessageSnippets(send_an_email_message) { 62 | @Override 63 | public void request(MSGraphMailService service, Callback callback) { 64 | // Get a context so we can interrogate Resources & SharedPreferences 65 | SnippetApp app = SnippetApp.getApp(); 66 | SharedPreferences prefs = SharedPrefsUtil.getSharedPreferences(); 67 | 68 | // load the contents 69 | String subject = app.getString(R.string.mailSubject); 70 | String body = app.getString(R.string.mailBody); 71 | String recipient = prefs.getString(SharedPrefsUtil.PREF_USER_ID, ""); 72 | 73 | // make it 74 | MessageWrapper msgWrapper = createMessage(subject, body, recipient); 75 | 76 | // send it 77 | service.createNewMail(getVersion(), msgWrapper).enqueue(callback); 78 | } 79 | } 80 | }; 81 | } 82 | 83 | @Override 84 | public abstract void request(MSGraphMailService service, Callback callback); 85 | 86 | public static MessageWrapper createMessage( 87 | String msgSubject, 88 | String msgBody, 89 | String... msgRecipients) { 90 | Message msg = new Message(); 91 | 92 | // add the recipient 93 | RecipientVO recipient; 94 | for (int ii = 0; ii < msgRecipients.length; ii++) { 95 | // if the recipient array does not exist, new one up 96 | if (null == msg.toRecipients) { 97 | msg.toRecipients = new RecipientVO[msgRecipients.length]; 98 | } 99 | // allocate a new recipient 100 | recipient = new RecipientVO(); 101 | // give them an email address 102 | recipient.emailAddress = new EmailAddress(); 103 | // set that address to be the currently iterated-upon recipient string 104 | recipient.emailAddress.address = msgRecipients[ii]; 105 | // add it to the array at the position 106 | msg.toRecipients[ii] = recipient; 107 | } 108 | 109 | // set the subject 110 | msg.subject = msgSubject; 111 | 112 | // create the body 113 | ItemBody body = new ItemBody(); 114 | body.contentType = ItemBody.CONTENT_TYPE_TEXT; 115 | body.content = msgBody; 116 | msg.body = body; 117 | 118 | MessageWrapper wrapper = new MessageWrapper(); 119 | wrapper.message = msg; 120 | wrapper.saveToSentItems = true; 121 | return wrapper; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/snippet/SnippetCategory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp.snippet; 6 | 7 | import com.microsoft.office365.msgraphapiservices.MSGraphContactService; 8 | import com.microsoft.office365.msgraphapiservices.MSGraphDrivesService; 9 | import com.microsoft.office365.msgraphapiservices.MSGraphEventsService; 10 | import com.microsoft.office365.msgraphapiservices.MSGraphGroupsService; 11 | import com.microsoft.office365.msgraphapiservices.MSGraphMailService; 12 | import com.microsoft.office365.msgraphapiservices.MSGraphMeService; 13 | import com.microsoft.office365.msgraphapiservices.MSGraphUserService; 14 | import com.microsoft.office365.msgraphsnippetapp.application.SnippetApp; 15 | 16 | import static com.microsoft.office365.msgraphsnippetapp.R.string.section_contacts; 17 | import static com.microsoft.office365.msgraphsnippetapp.R.string.section_drives; 18 | import static com.microsoft.office365.msgraphsnippetapp.R.string.section_events; 19 | import static com.microsoft.office365.msgraphsnippetapp.R.string.section_groups; 20 | import static com.microsoft.office365.msgraphsnippetapp.R.string.section_me; 21 | import static com.microsoft.office365.msgraphsnippetapp.R.string.section_messages; 22 | import static com.microsoft.office365.msgraphsnippetapp.R.string.section_user; 23 | 24 | public class SnippetCategory { 25 | static final SnippetCategory contactSnippetCategory 26 | = new SnippetCategory<>(section_contacts, create(MSGraphContactService.class)); 27 | 28 | static final SnippetCategory eventsSnippetCategory 29 | = new SnippetCategory<>(section_events, create(MSGraphEventsService.class)); 30 | 31 | static final SnippetCategory groupSnippetCategory 32 | = new SnippetCategory<>(section_groups, create(MSGraphGroupsService.class)); 33 | 34 | static final SnippetCategory userSnippetCategory 35 | = new SnippetCategory<>(section_user, create(MSGraphUserService.class)); 36 | 37 | static final SnippetCategory mailSnippetCategory 38 | = new SnippetCategory<>(section_messages, create(MSGraphMailService.class)); 39 | 40 | static final SnippetCategory meSnippetCategory 41 | = new SnippetCategory<>(section_me, create(MSGraphMeService.class)); 42 | 43 | static final SnippetCategory drivesSnippetCategory 44 | = new SnippetCategory<>(section_drives, create(MSGraphDrivesService.class)); 45 | 46 | final String mSection; 47 | final T mService; 48 | 49 | SnippetCategory(int sectionId, T service) { 50 | mSection = SnippetApp.getApp().getString(sectionId); 51 | mService = service; 52 | } 53 | 54 | private static T create(Class clazz) { 55 | return SnippetApp.getApp().getRetrofit().create(clazz); 56 | } 57 | } -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/snippet/SnippetContent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp.snippet; 6 | 7 | import java.util.ArrayList; 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | import static com.microsoft.office365.msgraphsnippetapp.snippet.ContactsSnippets.getContactsSnippets; 12 | import static com.microsoft.office365.msgraphsnippetapp.snippet.DrivesSnippets.getDrivesSnippets; 13 | import static com.microsoft.office365.msgraphsnippetapp.snippet.EventsSnippets.getEventsSnippets; 14 | import static com.microsoft.office365.msgraphsnippetapp.snippet.GroupsSnippets.getGroupsSnippets; 15 | import static com.microsoft.office365.msgraphsnippetapp.snippet.MeSnippets.getMeSnippets; 16 | import static com.microsoft.office365.msgraphsnippetapp.snippet.MessageSnippets.getMessageSnippets; 17 | import static com.microsoft.office365.msgraphsnippetapp.snippet.UsersSnippets.getUsersSnippets; 18 | 19 | public class SnippetContent { 20 | 21 | 22 | public static final List> ITEMS = new ArrayList<>(); 23 | 24 | static { 25 | AbstractSnippet[][] baseSnippets = new AbstractSnippet[][]{ 26 | getContactsSnippets(), 27 | getGroupsSnippets(), 28 | getEventsSnippets(), 29 | getMeSnippets(), 30 | getMessageSnippets(), 31 | getUsersSnippets(), 32 | getDrivesSnippets() 33 | }; 34 | 35 | for (AbstractSnippet[] snippetArray : baseSnippets) { 36 | Collections.addAll(ITEMS, snippetArray); 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/snippet/UsersSnippets.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp.snippet; 6 | 7 | import android.content.SharedPreferences; 8 | 9 | import com.microsoft.office365.microsoftgraphvos.PasswordProfile; 10 | import com.microsoft.office365.microsoftgraphvos.User; 11 | import com.microsoft.office365.msgraphapiservices.MSGraphUserService; 12 | import com.microsoft.office365.msgraphsnippetapp.util.SharedPrefsUtil; 13 | 14 | import java.util.UUID; 15 | 16 | import okhttp3.ResponseBody; 17 | import retrofit2.Callback; 18 | 19 | import static com.microsoft.office365.msgraphsnippetapp.R.array.get_organization_filtered_users; 20 | import static com.microsoft.office365.msgraphsnippetapp.R.array.get_organization_users; 21 | import static com.microsoft.office365.msgraphsnippetapp.R.array.insert_organization_user; 22 | import static com.microsoft.office365.msgraphsnippetapp.util.SharedPrefsUtil.PREF_USER_TENANT; 23 | 24 | public abstract class UsersSnippets extends AbstractSnippet { 25 | 26 | public UsersSnippets(Integer descriptionArray) { 27 | super(SnippetCategory.userSnippetCategory, descriptionArray); 28 | } 29 | 30 | static UsersSnippets[] getUsersSnippets() { 31 | return new UsersSnippets[]{ 32 | // Marker element 33 | new UsersSnippets(null) { 34 | 35 | @Override 36 | public void request(MSGraphUserService msGraphUserService, Callback callback) { 37 | } 38 | }, 39 | 40 | /* 41 | * Gets all of the users in your tenant\'s directory. 42 | * HTTP GET https://graph.microsoft.com/{version}/myOrganization/users 43 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/api/user_list 44 | */ 45 | new UsersSnippets(get_organization_users) { 46 | @Override 47 | public void request( 48 | MSGraphUserService msGraphUserService, 49 | Callback callback) { 50 | msGraphUserService.getUsers(getVersion()).enqueue(callback); 51 | } 52 | }, 53 | 54 | /* 55 | * Gets all of the users in your tenant's directory who are from the United States, using $filter. 56 | * HTTP GET https://graph.microsoft.com/{version}/myOrganization/users?$filter=country eq \'United States\' 57 | * @see http://graph.microsoft.io/docs/overview/query_parameters 58 | */ 59 | new UsersSnippets(get_organization_filtered_users) { 60 | @Override 61 | public void request( 62 | MSGraphUserService msGraphUserService, 63 | Callback callback) { 64 | msGraphUserService.getFilteredUsers( 65 | getVersion(), 66 | "country eq 'United States'" 67 | ).enqueue(callback); 68 | } 69 | }, 70 | 71 | /* 72 | * Adds a new user to the tenant's directory 73 | * HTTP POST https://graph.microsoft.com/{version}/myOrganization/users 74 | * @see https://graph.microsoft.io/docs/api-reference/v1.0/api/user_post_users 75 | */ 76 | new UsersSnippets(insert_organization_user) { 77 | @Override 78 | public void request( 79 | MSGraphUserService msGraphUserService, 80 | Callback callback) { 81 | //Use a random UUID for the user name 82 | String randomUserName = UUID.randomUUID().toString(); 83 | // get the tenant from preferences 84 | SharedPreferences prefs = SharedPrefsUtil.getSharedPreferences(); 85 | String tenant = prefs.getString(PREF_USER_TENANT, ""); 86 | 87 | // create the user 88 | User user = createUser( 89 | "SAMPLE " + randomUserName, 90 | randomUserName, 91 | randomUserName + "@" + tenant 92 | ); 93 | 94 | msGraphUserService.createNewUser(getVersion(), user).enqueue(callback); 95 | } 96 | } 97 | }; 98 | } 99 | 100 | public abstract void request(MSGraphUserService msGraphUserService, Callback callback); 101 | 102 | public static User createUser(String displayName, String mailNickname, String userPrincipalName) { 103 | User user = new User(); 104 | user.accountEnabled = true; 105 | user.displayName = displayName; 106 | user.mailNickname = mailNickname; 107 | 108 | user.userPrincipalName = userPrincipalName; 109 | 110 | // initialize a password & say whether or not the user must change it 111 | PasswordProfile password = new PasswordProfile(); 112 | password.password = UUID.randomUUID().toString().substring(0, 16); 113 | password.forceChangePasswordNextSignIn = false; 114 | 115 | user.passwordProfile = password; 116 | 117 | return user; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /app/src/main/java/com/microsoft/office365/msgraphsnippetapp/util/SharedPrefsUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | package com.microsoft.office365.msgraphsnippetapp.util; 6 | 7 | import android.content.Context; 8 | import android.content.SharedPreferences; 9 | 10 | import com.microsoft.identity.client.AuthenticationResult; 11 | import com.microsoft.office365.msgraphsnippetapp.application.SnippetApp; 12 | import com.microsoft.office365.msgraphsnippetapp.inject.AppModule; 13 | 14 | public class SharedPrefsUtil { 15 | 16 | public static final String PREF_AUTH_TOKEN = "PREF_AUTH_TOKEN"; 17 | public static final String PREF_USER_TENANT = "PREF_USER_TENANT"; 18 | public static final String PREF_USER_ID = "PREF_USER_ID"; 19 | 20 | public static SharedPreferences getSharedPreferences() { 21 | return SnippetApp.getApp().getSharedPreferences(AppModule.PREFS, Context.MODE_PRIVATE); 22 | } 23 | 24 | public static void persistUserID(AuthenticationResult result) { 25 | setPreference(PREF_USER_ID, result.getAccount().getUsername()); 26 | } 27 | 28 | public static void persistAuthToken(AuthenticationResult result) { 29 | setPreference(PREF_AUTH_TOKEN, result.getAccessToken()); 30 | } 31 | 32 | public static void persistUserTenant(String tenant) { 33 | getSharedPreferences().edit().putString(PREF_USER_TENANT, tenant).commit(); 34 | } 35 | 36 | private static void setPreference(String key, String accessToken) { 37 | getSharedPreferences().edit().putString(key, accessToken).commit(); 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/bkgrnd_rect.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/border_red.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_signin.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 17 | 18 | 22 | 23 |