Coder Social home page Coder Social logo

microsoftgraph / msgraph-sample-android Goto Github PK

View Code? Open in Web Editor NEW
38.0 10.0 17.0 19.37 MB

This sample demonstrates how to use the Microsoft Graph Java SDK to access data in Office 365 from native mobile Android applications.

License: MIT License

Java 100.00%
android java microsoft-graph devxsample

msgraph-sample-android's Introduction

page_type description products languages
sample
This sample demonstrates how to use the Microsoft Graph Java SDK to access data in Office 365 from Android apps.
ms-graph
microsoft-graph-calendar-api
office-exchange-online
java

Microsoft Graph sample Android app

Android CI License.

This sample demonstrates how to use the Microsoft Graph Java SDK to access data in Office 365 from native mobile Android applications.

NOTE: This sample was originally built from a tutorial published on the Microsoft Graph tutorials page. That tutorial has been removed.

Prerequisites

To run the completed project in this folder, you need the following:

  • Android Studio installed on your development machine.
  • Either a personal Microsoft account with a mailbox on Outlook.com, or a Microsoft work or school account.

If you don't have a Microsoft account, there are a couple of options to get a free account:

Register a web application with the Azure Active Directory admin center

  1. Open a browser and navigate to the Azure Active Directory admin center and login using a personal account (aka: Microsoft Account) or Work or School Account.

  2. Select Azure Active Directory in the left-hand navigation, then select App registrations under Manage.

  3. Select New registration. On the Register an application page, set the values as follows.

    • Set Name to Android Graph Sample.
    • Set Supported account types to Accounts in any organizational directory and personal Microsoft accounts.
    • Under Redirect URI, set the dropdown to Public client/native (mobile & desktop) and set the value to msauth://com.example.graphsample/callback.
  4. Select Register. On the Android Graph Sample page, copy the value of the Application (client) ID and save it, you will need it in the next step.

Configure the sample

  1. Rename the msal_config.json.example file to msal_config.json and move the file into the src/app/src/main/res/raw directory.
  2. Edit the msal_config.json file and make the following changes.
    1. Replace YOUR_APP_ID_HERE with the Application (client) Id you got from the Azure portal.
    2. Replace com.example.graphsample with your package name.

Run the sample

In Android Studio, select Run 'app' on the Run menu.

Code of conduct

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

Disclaimer

THIS CODE IS PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.

msgraph-sample-android's People

Contributors

andrewconnell avatar baywet avatar dependabot[bot] avatar github-actions[bot] avatar jasonjoh avatar jthake avatar microsoft-github-policy-service[bot] avatar vikyding avatar yinaa avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

msgraph-sample-android's Issues

Issues running tutorial

Reported by @nmetulev

Using Android Studio 3.5.1

In Create an Android app

  • When creating a new project, by default, the Use androidx.* artifacts checkbox is checked. If Android 10 SDK is installed, the checkbox can't be unchecked. The docs should call this out and ask the developer to uncheck the checkbox. This caused some headache to figure out as we had a lot of folks run into issues because of it.
  • Add fragments section, step 12. The code doesn't contain the import statements

In Get calendar data

  • First section, step 6. change "Override the onCreate function in the GraphHelper..." to "Override the onCreate function in the CalendarFragment..."

About using Microsoft graph to build Android apps, the class in the example was not found

According to official documents( https://docs.microsoft.com/zh-cn/graph/tutorials/android?context=outlook%2Fcontext )Use Microsoft graph to build Android applications.

However, when I write code according to the examples in the document, I find that some classes cannot be found in the corresponding packages, such as com.microsoft.graph.authentication.baseauthenticationprovider, which cannot be found in packages that depend on Microsoft graph: 3.1.0, and com.microsoft.graph.options cannot be found.

Is there a problem with the document sample code? Or do I rely on the wrong package? (I checked other versions of packages on GitHub and found no relevant classes)

Integrate Azure Ad B2c UserFlows in this

First of all Thanks for putting this tutorial. it really helps me a lot after spending two days in search of appropriate sample. there is no such sample i found anywhere which is as complete as this one.

Thanks!!!!!!. Now i want to integrate Azure ad b2c using msal. and want to execute azure ad b2c user flows like SignUpandSignIn for login into the android app

What changes i need to do if i want to in integrate azure ad B2C user flows like SignUpAndSignIn.
can you please share any sample with azure ad b2c user flows.

Trust anchor for certification path not found in Microsoft Graph API

I have been using the Microsoft Graph API in my android application to get the calendar events etc... The Authentication and events data retrieval were all working fine, but Microsoft Graph is not working properly on devices under 4.4 lately, when I try to get user data or calendar events, an exception occurs. I run the same codes on 2 android SDK versions, on 6.0, I can get all the data I want but on 4.4, it fails with the exception :

Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

(The Microsoft Graph were working fine on devices under 4.4 till last December but it stopped giving the following exception)

These are the libraries that are used now

implementation 'com.microsoft.identity.client:msal:2.0.5'
implementation 'com.microsoft.graph:microsoft-graph:2.5.0'

implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation("com.squareup.retrofit2:retrofit:2.9.0")

implementation("com.squareup.okhttp3:okhttp:3.12.8") {
force = true
}

implementation "com.squareup.okhttp3:logging-interceptor:3.12.8"

Microsoft Graph API, Client error authenticating

I visited this below link to start sample android app for using graph api for microsoft teams.

https://developer.microsoft.com/en-us/graph/quick-start?appID=1790d094-XXXX-XXXX-b55a-XXXXXXX39e7&appName=My%20Android%20App&redirectUrl=http://localhost:8000&platform=option-android

But I am getting below error when i am trying to sign in.

2020-09-22 16:49:34.322 31281-31281/com.example.graphtutorial E/AUTH: Client error authenticating
com.microsoft.identity.client.exception.MsalClientException:
at com.microsoft.identity.client.SingleAccountPublicClientApplication.signIn(SingleAccountPublicClientApplication.java:188)
at com.example.graphtutorial.AuthenticationHelper.acquireTokenInteractively(AuthenticationHelper.java:63)
at com.example.graphtutorial.MainActivity.doInteractiveSignIn(MainActivity.java:243)
at com.example.graphtutorial.MainActivity.access$500(MainActivity.java:33)
at com.example.graphtutorial.MainActivity$2.onError(MainActivity.java:277)
at com.microsoft.identity.client.SingleAccountPublicClientApplication$3.onError(SingleAccountPublicClientApplication.java:245)
at com.microsoft.identity.client.SingleAccountPublicClientApplication$3.onError(SingleAccountPublicClientApplication.java:213)
at com.microsoft.identity.common.internal.controllers.CommandDispatcher$2.run(CommandDispatcher.java:184)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7520)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

README.md

The links to your screenshots are not working. They are showing a 404 page.

Issues Upon Change of Configuration (e.g. Device Rotation)

Hi Jason,

Many thanks for implementing my previous suggestions.

The following is just for enhancement of the app

The app - as it stands - does a lot more than its intended purpose: that is to provide a solid introduction to the Microsoft Graph api for android, especially to beginners like me. I learnt quite a few neat tricks and conventions along the way, so thank you for that.

However, from an android-app operational point of view there are some issues, which you may very well be aware of. You may have chosen to ignore these issues to let each developer deal with them in their own preferred style. If this is the case, then please ignore this feedback and close it.

Issues:

  1. The app loses its state upon changes of configuration (e.g. when the device is rotated)
  2. The app does not remember that it is signed in when it is launched. Ideally if a silent signin can be performed then it should be signed in when the user opens it.
  3. More seriously, when CalendarFragment is visible and the device is rotated, the app actually crashes. This is because the code that is implemented in onCreate method should really be implemented in onCreateView method instead.

To deal with these issues, I made a few changes in MainActivity.java and CalendarFragment.java that you can check below.

Again this feedback is just for completeness as the Graph api code works perfectly.

All the best,

Mohamed

MainActivity.java

package com.example.graphtutorial;

import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;

import com.google.android.material.navigation.NavigationView;
import com.microsoft.graph.concurrency.ICallback;
import com.microsoft.graph.core.ClientException;
import com.microsoft.graph.models.extensions.User;
import com.microsoft.identity.client.AuthenticationCallback;
import com.microsoft.identity.client.IAuthenticationResult;
import com.microsoft.identity.client.exception.MsalClientException;
import com.microsoft.identity.client.exception.MsalException;
import com.microsoft.identity.client.exception.MsalServiceException;
import com.microsoft.identity.client.exception.MsalUiRequiredException;

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
//start of change 1*****************************
// These vars are to save the state of the app
// (used in onSaveState and onCreate)
// See change 4
    private static final String SAVED_IS_SIGNED_IN = "isSignedIn";
    private static final String SAVED_USER_NAME = "userName";
    private static final String SAVED_USER_EMAIL = "userEmail";
//end of change 1*******************************

    private DrawerLayout mDrawer;
    private NavigationView mNavigationView;
    private View mHeaderView;
    private boolean mIsSignedIn = false;
    private String mUserName = null;
    private String mUserEmail = null;

    private AuthenticationHelper mAuthHelper = null;

//start of change 2*****************************
// When the app first loads it should run doSilentSignin(). However,
// If this fails, then it should NOT run doInteractiveSignin(). It should
// simply keep the state as signed-out.
// See changes 3, 5 & 6
    private boolean mAttemptInteractiveSignin = false;
//end of change 2*******************************

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Set the toolbar
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        mDrawer = findViewById(R.id.drawer_layout);

        // Add the hamburger menu icon
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, mDrawer, toolbar,
                R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        mDrawer.addDrawerListener(toggle);
        toggle.syncState();

        mNavigationView = findViewById(R.id.nav_view);

        // Set user name and email
        mHeaderView = mNavigationView.getHeaderView(0);
        setSignedInState(mIsSignedIn);

        // Listen for item select events on menu
        mNavigationView.setNavigationItemSelectedListener(this);

//change ***************************************
// Rearrangement: The assignment of mAuthHelper must be before doSilentSignIn
        // Get the authentication helper
        mAuthHelper = AuthenticationHelper.getInstance(getApplicationContext());

        // Load the home fragment by default on startup
        if (savedInstanceState == null) {
            openHomeFragment(mUserName);
//start of change 3*****************************
// see comment of change 2
            doSilentSignIn();
        }
        mAttemptInteractiveSignin = true;
//end of change 3*******************************

//start of change 4*****************************
// see comment of change 1
        if (savedInstanceState != null) {
            mIsSignedIn = savedInstanceState.getBoolean(SAVED_IS_SIGNED_IN);
            mUserName = savedInstanceState.getString(SAVED_USER_NAME);
            mUserEmail = savedInstanceState.getString(SAVED_USER_EMAIL);
            setSignedInState(mIsSignedIn);
        }
    }

    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean(SAVED_IS_SIGNED_IN, mIsSignedIn);
        outState.putString(SAVED_USER_NAME, mUserName);
        outState.putString(SAVED_USER_EMAIL, mUserEmail);
    }
//end of change 4*******************************

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
        // Load the fragment that corresponds to the selected item
        switch (menuItem.getItemId()) {
            case R.id.nav_home:
                openHomeFragment(mUserName);
                break;
            case R.id.nav_calendar:
                openCalendarFragment();
                break;
            case R.id.nav_signin:
                signIn();
                break;
            case R.id.nav_signout:
                signOut();
                break;
        }

        mDrawer.closeDrawer(GravityCompat.START);

        return true;
    }

    @Override
    public void onBackPressed() {
        if (mDrawer.isDrawerOpen(GravityCompat.START)) {
            mDrawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }


    public void showProgressBar() {
        FrameLayout container = findViewById(R.id.fragment_container);
        ProgressBar progressBar = findViewById(R.id.progressbar);
        container.setVisibility(View.GONE);
        progressBar.setVisibility(View.VISIBLE);
    }

    public void hideProgressBar() {
        FrameLayout container = findViewById(R.id.fragment_container);
        ProgressBar progressBar = findViewById(R.id.progressbar);
        progressBar.setVisibility(View.GONE);
        container.setVisibility(View.VISIBLE);
    }

    // Update the menu and get the user's name and email
    private void setSignedInState(boolean isSignedIn) {
        mIsSignedIn = isSignedIn;

        Menu menu = mNavigationView.getMenu();

        // Hide/show the Sign in, Calendar, and Sign Out buttons
        menu.findItem(R.id.nav_signin).setVisible(!isSignedIn);
        menu.findItem(R.id.nav_calendar).setVisible(isSignedIn);
        menu.findItem(R.id.nav_signout).setVisible(isSignedIn);

        // Set the user name and email in the nav drawer
        TextView userName = mHeaderView.findViewById(R.id.user_name);
        TextView userEmail = mHeaderView.findViewById(R.id.user_email);

        if (isSignedIn) {
            userName.setText(mUserName);
            userEmail.setText(mUserEmail);
        } else {
            mUserName = null;
            mUserEmail = null;

            userName.setText("Please sign in");
            userEmail.setText("");
        }
    }

    // Load the "Home" fragment
    public void openHomeFragment(String userName) {
        HomeFragment fragment = HomeFragment.createInstance(userName);
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.fragment_container, fragment)
                .commit();
        mNavigationView.setCheckedItem(R.id.nav_home);
    }

    // Load the "Calendar" fragment
    private void openCalendarFragment() {
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.fragment_container, new CalendarFragment())
                .commit();
        mNavigationView.setCheckedItem(R.id.nav_calendar);
    }

    private void signIn() {
        showProgressBar();
        // Attempt silent sign in first
        // if this fails, the callback will handle doing
        // interactive sign in
        doSilentSignIn();
        //doInteractiveSignIn();
    }

    private void signOut() {
        //mAuthHelper.signOut();
        mAuthHelper.signOut();

        setSignedInState(false);
        openHomeFragment(mUserName);
    }

    // Silently sign in - used if there is already a
    // user account in the MSAL cache
    private void doSilentSignIn() {
        //mAuthHelper.acquireTokenSilently(getAuthCallback());
        mAuthHelper.acquireTokenSilently(getAuthCallback());
    }

    // Prompt the user to sign in
    private void doInteractiveSignIn() {
        //mAuthHelper.acquireTokenInteractively(this, getAuthCallback());
        mAuthHelper.acquireTokenInteractively(this, getAuthCallback());
    }

    // Handles the authentication result
    public AuthenticationCallback getAuthCallback() {
        return new AuthenticationCallback() {

            @Override
            public void onSuccess(IAuthenticationResult authenticationResult) {
                // Log the token for debug purposes
                String accessToken = authenticationResult.getAccessToken();
                Log.d("AUTH", String.format("Access token: %s", accessToken));

                // Get Graph client and get user
                GraphHelper graphHelper = GraphHelper.getInstance();
                graphHelper.getUser(accessToken, getUserCallback());
            }

            @Override
            public void onError(MsalException exception) {
                // Check the type of exception and handle appropriately
                if (exception instanceof MsalUiRequiredException) {
                    Log.d("AUTH", "Interactive login required");
//start of change 5*****************************
// see comment of change 2
                    if (mAttemptInteractiveSignin) { doInteractiveSignIn(); }
//end of change 5*******************************

                } else if (exception instanceof MsalClientException) {
                    if (exception.getErrorCode() == "no_current_account") {
                        Log.d("AUTH", "No current account, interactive login required");
//start of change 6*****************************
// see comment of change 2
                        if (mAttemptInteractiveSignin) { doInteractiveSignIn(); }
//end of change 6*******************************
                    } else {
                        // Exception inside MSAL, more info inside MsalError.java
                        Log.e("AUTH", "Client error authenticating", exception);
                    }
                } else if (exception instanceof MsalServiceException) {
                    // Exception when communicating with the auth server, likely config issue
                    Log.e("AUTH", "Service error authenticating", exception);
                }
                hideProgressBar();
            }

            @Override
            public void onCancel() {
                // User canceled the authentication
                Log.d("AUTH", "Authentication canceled");
                hideProgressBar();
            }
        };
    }

    private ICallback<User> getUserCallback() {
        return new ICallback<User>() {
            @Override
            public void success(User user) {
                Log.d("AUTH", "User: " + user.displayName);

                mUserName = user.displayName;
                mUserEmail = user.mail == null ? user.userPrincipalName : user.mail;

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        hideProgressBar();

                        setSignedInState(true);
                        openHomeFragment(mUserName);
                    }
                });

            }

            @Override
            public void failure(ClientException ex) {
                Log.e("AUTH", "Error getting /me", ex);
                mUserName = "ERROR";
                mUserEmail = "ERROR";

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        hideProgressBar();

                        setSignedInState(true);
                        openHomeFragment(mUserName);
                    }
                });
            }
        };
    }
}

CalendarFragment.java

package com.example.graphtutorial;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.ProgressBar;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.microsoft.graph.concurrency.ICallback;
import com.microsoft.graph.core.ClientException;
import com.microsoft.graph.models.extensions.Event;
import com.microsoft.graph.requests.extensions.IEventCollectionPage;
import com.microsoft.identity.client.AuthenticationCallback;
import com.microsoft.identity.client.IAuthenticationResult;
import com.microsoft.identity.client.exception.MsalException;

import java.util.List;

public class CalendarFragment extends Fragment {
    private static final String TAG = "CalendarFragment";

    private List<Event> mEventList = null;
    private ProgressBar mProgress = null;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//start of change 1*****************************
// All the code that was in onCreate method should be moved in this method
// as it caused the app to crash upon configuration changes (e.g. rotation of the device)
        View view = inflater.inflate(R.layout.fragment_calendar, container, false);

        mProgress = getActivity().findViewById(R.id.progressbar);
        Log.d(TAG, "onCreate: mProgress = " + mProgress);
        showProgressBar();

        // Get a current access token
        AuthenticationHelper.getInstance()
                .acquireTokenSilently(new AuthenticationCallback() {
                    @Override
                    public void onSuccess(IAuthenticationResult authenticationResult) {
                        final GraphHelper graphHelper = GraphHelper.getInstance();

                        // Get the user's events
                        graphHelper.getEvents(authenticationResult.getAccessToken(),
                                getEventsCallback());
                    }

                    @Override
                    public void onError(MsalException exception) {
                        Log.e("AUTH", "Could not get token silently", exception);
                        hideProgressBar();
                    }

                    @Override
                    public void onCancel() {
                        hideProgressBar();
                    }
                });

        return view;
//end of change 1*******************************
    }


    private void showProgressBar() {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mProgress.setVisibility(View.VISIBLE);
            }
        });
    }

    private void hideProgressBar() {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mProgress.setVisibility(View.GONE);
            }
        });
    }

    private ICallback<IEventCollectionPage> getEventsCallback() {
        return new ICallback<IEventCollectionPage>() {
            @Override
            public void success(IEventCollectionPage iEventCollectionPage) {
                mEventList = iEventCollectionPage.getCurrentPage();
                addEventsToList();

                // Temporary for debugging
                String jsonEvents = GraphHelper.getInstance().serializeObject(mEventList);
                Log.d("GRAPH:", jsonEvents);

                hideProgressBar();
            }

            @Override
            public void failure(ClientException ex) {
                Log.e("GRAPH", "Error getting events", ex);
                hideProgressBar();
            }
        };
    }

    private void addEventsToList() {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                ListView eventListView = getView().findViewById(R.id.eventlist);

                EventListAdapter listAdapter = new EventListAdapter(getActivity(),
                        R.layout.event_list_item, mEventList);

                eventListView.setAdapter(listAdapter);
            }
        });
    }
}

Method not allowed

When calling this api to update user in android.

IGraphServiceClient graphClient = GraphServiceClient.builder().authenticationProvider( authProvider ).buildClient();

User user = new User();
LinkedList businessPhonesList = new LinkedList();
businessPhonesList.add("businessPhones-value");
user.businessPhones = businessPhonesList;
user.officeLocation = "city-value";

graphClient.me()
.buildRequest()
.patch(user);

I am getting this response, but i have provided admin consent to every scopes.

Returning DeclinedScopeException as not all requested scopes are granted, Requested scopes: [User.Read, Calendars.Read, Directory.ReadWrite.All, User.ReadWrite, User.ReadWrite.All] Granted scopes:[Calendars.Read, User.ReadWrite, User.Read, openid, profile] Android 29
Screen Shot 2020-09-23 at 2 04 36 PM

Lack of correct proguard rules in guide for minifyEnabled=true case

Dependencies:
From example 1.4.0 compile dependencies:
+--- com.microsoft.graph:microsoft-graph:1.4.0
| +--- org.apache.commons:commons-math3:3.6.1
| +--- com.google.code.gson:gson:2.8.2 -> 2.8.4
| --- com.sun.jersey:jersey-server:1.19.4
| --- com.sun.jersey:jersey-core:1.19.4
| --- javax.ws.rs:jsr311-api:1.1.1

Latest 1.6.0 compile dependencies:
+--- com.microsoft.graph:microsoft-graph:1.6.0
| +--- org.apache.commons:commons-math3:3.6.1
| +--- com.google.code.gson:gson:2.8.2 -> 2.8.4
| +--- com.sun.jersey:jersey-server:1.19.4
| | --- com.sun.jersey:jersey-core:1.19.4
| | --- javax.ws.rs:jsr311-api:1.1.1
| --- com.microsoft.graph:microsoft-graph-core:1.0.0
| +--- org.apache.commons:commons-math3:3.6.1
| +--- com.squareup.okhttp3:okhttp:3.12.1
| | --- com.squareup.okio:okio:1.15.0
| --- com.googlecode.json-simple:json-simple:1.1

Stack trace without proguard rules:
E/global: DefaultHttpProvider[sendRequestInternal] - 370Error during http request
E/global: Throwable detail: com.microsoft.graph.core.ClientException: Error during http request
I/global: Starting foreground task, current active count:0, with exception com.microsoft.graph.core.ClientException: Error during http request
E/AUTH: Error getting /me
com.microsoft.graph.core.ClientException: Error during http request
at com.microsoft.graph.http.DefaultHttpProvider.sendRequestInternal(DefaultHttpProvider.java:368)
at com.microsoft.graph.http.DefaultHttpProvider.access$000(DefaultHttpProvider.java:53)
at com.microsoft.graph.http.DefaultHttpProvider$1.run(DefaultHttpProvider.java:155)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: com.sun.ws.rs.ext.RuntimeDelegateImpl
at javax.ws.rs.ext.RuntimeDelegate.findDelegate(RuntimeDelegate.java:122)
at javax.ws.rs.ext.RuntimeDelegate.getInstance(RuntimeDelegate.java:91)
at javax.ws.rs.core.UriBuilder.newInstance(UriBuilder.java:69)
at javax.ws.rs.core.UriBuilder.fromUri(UriBuilder.java:80)
at com.microsoft.graph.http.BaseRequest.getRequestUrl(BaseRequest.java:147)
at com.microsoft.graph.http.DefaultHttpProvider.sendRequestInternal(DefaultHttpProvider.java:239)
at com.microsoft.graph.http.DefaultHttpProvider.access$000(DefaultHttpProvider.java:53) 
at com.microsoft.graph.http.DefaultHttpProvider$1.run(DefaultHttpProvider.java:155) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) 
at java.lang.Thread.run(Thread.java:764) 
Caused by: java.lang.ClassNotFoundException: com.sun.ws.rs.ext.RuntimeDelegateImpl
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:453)
at java.lang.Class.forName(Class.java:378)
at javax.ws.rs.ext.FactoryFinder.newInstance(FactoryFinder.java:62)
at javax.ws.rs.ext.FactoryFinder.find(FactoryFinder.java:155)
at javax.ws.rs.ext.RuntimeDelegate.findDelegate(RuntimeDelegate.java:105)
at javax.ws.rs.ext.RuntimeDelegate.getInstance(RuntimeDelegate.java:91) 
at javax.ws.rs.core.UriBuilder.newInstance(UriBuilder.java:69) 
at javax.ws.rs.core.UriBuilder.fromUri(UriBuilder.java:80) 
at com.microsoft.graph.http.BaseRequest.getRequestUrl(BaseRequest.java:147) 
at com.microsoft.graph.http.DefaultHttpProvider.sendRequestInternal(DefaultHttpProvider.java:239) 
at com.microsoft.graph.http.DefaultHttpProvider.access$000(DefaultHttpProvider.java:53) 
at com.microsoft.graph.http.DefaultHttpProvider$1.run(DefaultHttpProvider.java:155) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) 
at java.lang.Thread.run(Thread.java:764) 
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.sun.ws.rs.ext.RuntimeDelegateImpl" on path: DexPathList[[zip file "/data/app/com.example.graphtutorial-Pj2fXigqtiVMK_9sn4W2Sw==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.graphtutorial-Pj2fXigqtiVMK_9sn4W2Sw==/lib/arm64, /system/lib64, /system/vendor/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:93)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at java.lang.Class.classForName(Native Method) 
at java.lang.Class.forName(Class.java:453) 
at java.lang.Class.forName(Class.java:378) 
at javax.ws.rs.ext.FactoryFinder.newInstance(FactoryFinder.java:62) 
at javax.ws.rs.ext.FactoryFinder.find(FactoryFinder.java:155) 
at javax.ws.rs.ext.RuntimeDelegate.findDelegate(RuntimeDelegate.java:105) 
at javax.ws.rs.ext.RuntimeDelegate.getInstance(RuntimeDelegate.java:91) 
at javax.ws.rs.core.UriBuilder.newInstance(UriBuilder.java:69) 
at javax.ws.rs.core.UriBuilder.fromUri(UriBuilder.java:80) 
at com.microsoft.graph.http.BaseRequest.getRequestUrl(BaseRequest.java:147) 
at com.microsoft.graph.http.DefaultHttpProvider.sendRequestInternal(DefaultHttpProvider.java:239) 
at com.microsoft.graph.http.DefaultHttpProvider.access$000(DefaultHttpProvider.java:53) 
at com.microsoft.graph.http.DefaultHttpProvider$1.run(DefaultHttpProvider.java:155) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) 
at java.lang.Thread.run(Thread.java:764) 

My proguard rules:
-keep class com.sun.** { *; }
-keep interface com.sun.** { *; }

Stacktrace with proguard rules:
E/AUTH: Service error authenticating
com.microsoft.identity.client.exception.MsalServiceException: AADSTS900144: The request body must contain the following parameter: 'grant_type'.
Trace ID: 3cd1afe5-5fa1-4ac5-a8f9-7353dc891d00
Correlation ID: 0e0db0aa-5a27-4d26-899b-c2d1ab567438
Timestamp: 2019-11-01 20:23:26Z
at com.microsoft.identity.client.internal.controllers.ExceptionAdapter.exceptionFromAcquireTokenResult(ExceptionAdapter.java:90)
at com.microsoft.identity.client.internal.controllers.MSALApiDispatcher$1.run(MSALApiDispatcher.java:108)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)

But if I turn off minifyEnabled=false then all works correctly.

Access is denied. Check credentials and try again.

While fetching emails for mClient!!.me().mailFolders().buildRequest()[callback] call i am getting following error log

com.microsoft.graph.http.GraphServiceException: Error code: ErrorAccessDenied
Error message: Access is denied. Check credentials and try again.

GET https://graph.microsoft.com/v1.0/me/mailFolders
SdkVersion : graph-java-v1.4.0
Authorization : Bearer eyJ0eXAiOiJKV1QiLCJub25jZSI6InFzTDN2NklER0I0UUZ4bVBqbkNFdFVKUENJYkxXRU9MWGJLRlRwOUQ3ZFEiLCJhbGciOiJSUzI1NiIsIng1dCI6InBpVmxsb1FEU01LeGgxbTJ5Z3FHU1ZkZ0ZwQSIsImtpZCI6InBpVmxsb1FEU01LeGgxbTJ5Z3FHU1ZkZ0ZwQSJ9.eyJhdWQiOiIwMDAwMDAwMy0wMDAwLTAwMDAtYzAwMC0wMDAwMDAwMDAwMDAiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC83MmJjNTNjNC02MjJkLTRjYmItODdhOS1hYjM3OTkxMmI0MDYvIiwiaWF0IjoxNTgwMjgxNjE5LCJuYmYiOjE1ODAyODE2MTksImV4cCI6MTU4MDI4NTUxOSwiYWNjdCI6MCwiYWNyIjoiMSIsImFpbyI6IjQyTmdZSmpMUDlYc1NkU2x3LzhjNXplYVNZVDJQSXFKc21jKzN0VHo2NEdaL1FwWEZ6NEEiLCJhbXIiOlsicHdkIl0sImFwcF9kaXNwbGF5bmFtZSI6Iktub3dsZWRlbWlsbCBNb2JpbGUgQXBwIiwiYXBwaWQiOiJmNjI1OTk0Yi00MWJmLTRhNzMtOWIzOC05MDAzZTg4OWQyOWQiLCJhcHBpZGFjciI6IjAiLCJmYW1pbHlfbmFtZSI6IlNhbXVlbCIsImdpdmVuX25hbWUiOiJTdGVwaGVuIiwiaXBhZGRyIjoiNDkuMjQ4LjE0OC4yMDIiLCJuYW1lIjoiU3RlcGhlbiBTYW11ZWwiLCJvaWQiOiIwM2M3MjhjNi01NWFiLTRjMDktOGQzYy1iOTVjYmMyNWYwY2YiLCJwbGF0ZiI6IjEiLCJwdWlkIjoiMTAwMzNGRkY5QUYzOTM1RiIsInNjcCI6IkNhbGVuZGFycy5SZWFkIG9wZW5pZCBwcm9maWxlIFVzZXIuUmVhZCBlbWFpbCIsInNpZ25pbl9zdGF0ZSI6WyJrbXNpIl0sInN1YiI6IjVFUWF5bi16X2FvMU5YWXJPWjV3N1p2emkwX2pMNGxTZlJYSDQ4bzlUZ3ciLCJ0aWQiOiI3MmJjNTNjNC02MjJkLTRjYmItODdhOS1hYjM3OTkxMmI0MDYiLCJ1bmlxdWVfbmFtZSI6InN0ZXBoZW4uc2FtdWVsQGFkcm90ZXN0c2VydmVyLmNvbSIsInVwbiI6InN0ZXBoZW4uc2FtdWVsQGFkcm90ZXN0c2VydmVyLmNvbSIsInV0aSI6Im9YbUFJVy1hbUVtMHpXRzUzdkVhQVEiLCJ2ZXIiOiIxLjAiLCJ4bXNfc3QiOnsic3ViIjoiZWEwRmNwbER3WC05Z1pmb3V6QUZhV2JiM2gyUXVSVjlkMm5KaF9HdDFSbyJ9LCJ4bXNfdGNkdCI6MTQ1OTc3OTA2OH0.bwdBq8UiU17vVxDycIqZgLQ2_RKBEMIi3r8D5EPI-xe2agjdu7EcSClOU4bGdMU4314pQvmOigJ0dVY67f4QrNv7Oc_QZSXhxLP01BVcqj3I6gDt9Xw6f0HglRR3Jw4v8pyF7LefgMvNjnW8oN-cs3iS4homyTxOisIqJwb3Dbmbazx9psA5rt-OtXCdYKb3xWx9g9TM7uFZmV_cnl9r24NPRzxzwEmap8H8HfrZgzobnlhb5gXWJTOVXlmq6ANeoVaLtsPEkSbKZZg5l_820gl_KsSE-LMKTzS1PoVy5tBpr42I00h3G15HC05EXCNxYIsZBZ6rPl-TGHidQNv1-g


403 : Forbidden
X-Android-Selected-Protocol : http/1.1
Strict-Transport-Security : max-age=31536000
Cache-Control : private
x-ms-ags-diagnostic : {"ServerInfo":{"DataCenter":"South India","Slice":"SliceC","Ring":"3","ScaleUnit":"000","RoleInstance":"AGSFE_IN_3"}}
client-request-id : 021478ab-8f0c-45cb-9d7a-b7455718a859
X-Android-Response-Source : NETWORK 403
X-Android-Sent-Millis : 1580281922991
request-id : 021478ab-8f0c-45cb-9d7a-b7455718a859
Content-Length : 253
X-Android-Received-Millis : 1580281923076
Date : Wed, 29 Jan 2020 07:12:00 GMT
Content-Type : application/json
{
  "error": {
    "code": "ErrorAccessDenied",
    "message": "Access is denied. Check credentials and try again.",
    "innerError": {
      "request-id": "021478ab-8f0c-45cb-9d7a-b7455718a859",
      "date": "2020-01-29T07:12:01"
    }
  }
}

    at com.microsoft.graph.http.DefaultHttpProvider.handleErrorResponse(DefaultHttpProvider.java:388)
    at com.microsoft.graph.http.DefaultHttpProvider.sendRequestInternal(DefaultHttpProvider.java:321)
    at com.microsoft.graph.http.DefaultHttpProvider.send(DefaultHttpProvider.java:204)
    at com.microsoft.graph.http.DefaultHttpProvider.send(DefaultHttpProvider.java:184)
    at com.microsoft.graph.http.BaseCollectionRequest.send(BaseCollectionRequest.java:87)
    at com.microsoft.graph.requests.extensions.MailFolderCollectionRequest.get(MailFolderCollectionRequest.java:52)
    at com.microsoft.graph.requests.extensions.MailFolderCollectionRequest$1.run(MailFolderCollectionRequest.java:43)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
    at java.lang.Thread.run(Thread.java:764)

java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

I followed all the instructions from https://docs.microsoft.com/en-us/graph/tutorials/android. The Authentication is passed, but when I try to get user data or calendar events, an exception occurs. I run the same codes on 2 android sdk versions, on 4.4, it failed, but on 6.0, I can get the data I want. the following is the exception messages.

com.microsoft.graph.core.ClientException: Error during http request
at com.microsoft.graph.http.CoreHttpProvider.sendRequestInternal(CoreHttpProvider.java:422)
at com.microsoft.graph.http.CoreHttpProvider.send(CoreHttpProvider.java:204)
at com.microsoft.graph.http.CoreHttpProvider.send(CoreHttpProvider.java:184)
at com.microsoft.graph.http.BaseCollectionRequest.send(BaseCollectionRequest.java:89)
at com.microsoft.graph.requests.extensions.EventCollectionRequest.get(EventCollectionRequest.java:52)
at com.microsoft.graph.requests.extensions.EventCollectionRequest$1.run(EventCollectionRequest.java:43)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:409)
at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:319)
at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:283)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:168)
at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257)
at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)
at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at com.microsoft.graph.httpcore.TelemetryHandler.intercept(TelemetryHandler.java:35)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at com.microsoft.graph.httpcore.RedirectHandler.intercept(RedirectHandler.java:123)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at com.microsoft.graph.httpcore.RetryHandler.intercept(RetryHandler.java:140)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at com.microsoft.graph.httpcore.AuthenticationHandler.intercept(AuthenticationHandler.java:31)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254)
at okhttp3.RealCall.execute(RealCall.java:92)
at com.microsoft.graph.http.CoreHttpProvider.sendRequestInternal(CoreHttpProvider.java:356)
at com.microsoft.graph.http.CoreHttpProvider.send(CoreHttpProvider.java:204) 
at com.microsoft.graph.http.CoreHttpProvider.send(CoreHttpProvider.java:184) 
at com.microsoft.graph.http.BaseCollectionRequest.send(BaseCollectionRequest.java:89) 
at com.microsoft.graph.requests.extensions.EventCollectionRequest.get(EventCollectionRequest.java:52) 
at com.microsoft.graph.requests.extensions.EventCollectionRequest$1.run(EventCollectionRequest.java:43) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
at java.lang.Thread.run(Thread.java:841) 
Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:282)
at com.android.org

What am I missing? Thanks in advance.

[Issue Transfer] Setting DayNight theme to night breaks authentication

Transferring this issue from:
AzureAD/microsoft-authentication-library-for-android#1269


Copy/Paste from @jonodav

Hi there, I've been trying to get MSAL working in an app and noticed it was crashing at night time. The cause was the daynight theme being set to night with:

AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);

Authentication is done using the following code from the MS Graph Android example app:

In MainActivity:

AuthenticationHelper.getInstance(getApplicationContext(),
                new IAuthenticationHelperCreatedListener() {
                    @Override
                    public void onCreated(AuthenticationHelper authHelper) {
                        mAuthHelper = authHelper;
                        if (!mIsSignedIn) {
                            doSilentSignIn(false);
                        } else {
                            hideProgressBar();
                        }
                    }

                    @Override
                    public void onError(MsalException exception) {
                        Log.e("AUTH", "Error creating auth helper", exception);
                    }
                });

In AuthenticationHelper:

private AuthenticationHelper(Context ctx, final IAuthenticationHelperCreatedListener listener) {
        PublicClientApplication.createSingleAccountPublicClientApplication(ctx, R.raw.msal_config,
                new IPublicClientApplication.ISingleAccountApplicationCreatedListener() {
                    @Override
                    public void onCreated(ISingleAccountPublicClientApplication application) {
                        mPCA = application;
                        listener.onCreated(INSTANCE);
                    }

                    @Override
                    public void onError(MsalException exception) {
                        Log.e("AUTHHELPER", "Error creating MSAL application", exception);
                        listener.onError(exception);
                    }
                });
    }

It appears that mPCA is never properly initialized and results in null object references when sign on is attempted:

public void acquireTokenSilently(AuthenticationCallback callback) {
        // Get the authority from MSAL config
        String authority = mPCA.getConfiguration().getDefaultAuthority().getAuthorityURL().toString();
        mPCA.acquireTokenSilentAsync(mScopes, authority, callback);
    }

Devices

  • Device: Asus Nexus 7 (2013), OnePlus 6
  • Android Version: API 23, MO30X, API 28
  • MSAL Versions 1.4.0, 2.0.4, and 2.0.5

Stacktrace

01-07 09:22:04.007 24851-24851/com.sample.app E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.sample.app, PID: 24851
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sample.app/com.sample.app.MainActivity}: java.lang.NullPointerException: Attempt to invoke interface method 'com.microsoft.identity.client.PublicClientApplicationConfiguration com.microsoft.identity.client.ISingleAccountPublicClientApplication.getConfiguration()' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4077)
        at android.app.ActivityThread.-wrap15(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1350)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5417)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
     Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'com.microsoft.identity.client.PublicClientApplicationConfiguration com.microsoft.identity.client.ISingleAccountPublicClientApplication.getConfiguration()' on a null object reference
        at com.sample.app.AuthenticationHelper.acquireTokenSilently(AuthenticationHelper.java:63)
        at com.sample.app.MainActivity.doSilentSignIn(MainActivity.java:338)
        at com.sample.app.MainActivity.access$200(MainActivity.java:53)
        at com.sample.app.MainActivity$1.onCreated(MainActivity.java:186)
        at com.sample.app.AuthenticationHelper.getInstance(AuthenticationHelper.java:42)
        at com.sample.app.MainActivity.onCreate(MainActivity.java:180)
        at android.app.Activity.performCreate(Activity.java:6251)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4077) 
        at android.app.ActivityThread.-wrap15(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1350) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:148) 
        at android.app.ActivityThread.main(ActivityThread.java:5417) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) `

To Reproduce
Steps to reproduce the behavior:
Add AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); to the onCreate, and preferably set the AppTheme to DayNight. Setting default night mode to MODE_NIGHT_NO does not result in the error.
This can be reproduced in the example app for Microsoft Graph on android here.

Expected behavior
The application should silently sign on on launch.

Actual Behavior
The application crashes on attempting to sign on.

Thank you!


@jasonjoh This looks like it might be race condition inside of the sample. As this doesn't immediately appear to be an SDK issue, sending over to this repository

The application 'Android Graph Tutorial' asked for scope 'OnlineMeetings.ReadWrite.All' that doesn't exist on the resource

From my android application, I could use the SDK and fetch the contacts using "Contacts.Read" permission scope. But I am unable to use any other permissions like OnlineMeetings.ReadWrite, Calls.JoinGroupCallsasGuest.All, Calls.JoinGroupCalls.All, Calls.Initiate.All, Calls.InitiateGroupCalls.All.

Are we not allowed to use API's which requires these permissions such as CALL (create and answer), ONlINE MEETING?

@jasonjoh Kindly guide me on this.

503 (Service Unavailable)

Thanks for this tutorial.
I'm having trouble getting your example running in my organization. I was able to register the application in azura my company and set up the application from the tutorial to download the token and basic information about my account. However, when I try to get information about my events, I get error 503 (Service Unavailable). Is there an easy way to trace the causes? Should I set something more when registering permissions, apart from User.Read, Calendars.Read, Calendars.ReadWrite?

I will be grateful for your help

Code provided gives error about format of scope param

I used the code exactly as it is and the scope param gives an error about the format of the scopes.

This is what I have

7050e98c-759a-431f-b3a1-e7075810f730
msal7050e98c-759a-431f-b3a1-e7075810f730

Calendars.Shared.Read
Calendars.Read

I have attached screenshot of error: AADSTS70011

I cannot get the screenshot to attach but I can email it if needed.

It says:

Message: AADSTS70011: The provided request must include a ‘scope’ input parameter. The provided value for the input parameter ‘scope’ is not valid. The scope opened profile offline_access Calendars.Shared.Read Calendars.Read is not valid. The scope format is invalid. Scope must be in a valid URI form https://example/scope or a valid Guid<guid/scope>.

CoreHttpProvider[sendRequestInternal] - 424Error during http request

These are the scopes i am providing in authenticationHelper class in android.

private String[] mScopes = { "User.Read", "Calendars.Read", "User.ReadWrite", "User.ReadWrite.All", "OnlineMeetings.Read", "OnlineMeetings.ReadWrite"};

This what i am getting from token.

"scp": "AccessReview.Read.All AccessReview.ReadWrite.All Application.Read.All Application.ReadWrite.All Directory.AccessAsUser.All Directory.Read.All Directory.ReadWrite.All Files.Read Files.Read.All Mail.Read Mail.ReadBasic Mail.ReadWrite OnlineMeetings.Read OnlineMeetings.ReadWrite openid Organization.Read.All Organization.ReadWrite.All OrgContact.Read.All profile Tasks.ReadWrite User.Read User.Read.All User.ReadBasic.All User.ReadWrite User.ReadWrite.All email",

In Azure AD , these are the api permissions i have added.
Screen Shot 2020-09-29 at 1 12 49 PM

I am able to update users from graph explorer.

Screen Shot 2020-09-29 at 1 19 08 PM

But While using below code in android giving error.

User user = new User();
LinkedList businessPhonesList = new LinkedList();
businessPhonesList.add("79XXXXXX94");
user.businessPhones = businessPhonesList;
user.officeLocation = "Bangalore";

    mClient.me()
            .buildRequest()
            .patch(user);

implementation 'com.microsoft.identity.client:msal:1.4.0'
implementation 'com.microsoft.graph:microsoft-graph:1.7.1'

I am getting this error while calling above method.

2020-09-29 13:14:13.361 16702-16702/com.XXX.XXXXX E/global: CoreHttpProvider[sendRequestInternal] - 424Error during http request
2020-09-29 13:14:13.361 16702-16702/com.XXX.XXXXX E/global: Throwable detail: com.microsoft.graph.core.ClientException: Error during http request
2020-09-29 13:14:13.362 16702-16702/com.XXX.XXXXX E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.XXX.XXXXX, PID: 16702
com.microsoft.graph.core.ClientException: Error during http request
at com.microsoft.graph.http.CoreHttpProvider.sendRequestInternal(CoreHttpProvider.java:422)
at com.microsoft.graph.http.CoreHttpProvider.send(CoreHttpProvider.java:204)
at com.microsoft.graph.http.CoreHttpProvider.send(CoreHttpProvider.java:184)
at com.microsoft.graph.http.BaseRequest.send(BaseRequest.java:306)
at com.microsoft.graph.requests.extensions.UserRequest.patch(UserRequest.java:91)
at com.phtl.teamsapp.GraphHelper.updateUser(GraphHelper.java:66)
at com.phtl.teamsapp.CalendarFragment$1.onSuccess(CalendarFragment.java:48)

The provided value for the input parameter 'scope' is not valid

Please help me in this.
I modified the code to include a new scope for further implmentation of a call between users.
I can run the original code perfectly, manifesting my events in my calendar.
But after only one modification to the code as this:

from

private String[] mScopes = { "User.Read", "Calendars.Read"};

to

private String[] mScopes = { "User.Read", "Calendars.Read", "Calls.Initiate.All"};

adding the scope "Calls.Initiate.All",

I got the error:

E/AUTH: Service error authenticating com.microsoft.identity.client.exception.MsalServiceException: AADSTS70011: The provided value for the input parameter 'scope' is not valid. The scope 'Calendars.Read User.Read Calls.Initiate.All openid offline_access profile' does not exist. Trace ID: be7dd311-c09f-447e-9218-d2eecf989300 Correlation ID: a794fab4-3f00-4a68-91ed-ca16afb0d767 Timestamp: 2020-03-09 03:14:18Z at com.microsoft.identity.client.internal.controllers.MsalExceptionAdapter.msalExceptionFromBaseException(MsalExceptionAdapter.java:72) at com.microsoft.identity.client.SingleAccountPublicClientApplication$4.onError(SingleAccountPublicClientApplication.java:270) at com.microsoft.identity.common.internal.controllers.ApiDispatcher$4$4.run(ApiDispatcher.java:453) at android.os.Handler.handleCallback(Handler.java:883) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:7356) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) Caused by: com.microsoft.identity.common.exception.ServiceException: AADSTS70011: The provided value for the input parameter 'scope' is not valid. The scope 'Calendars.Read User.Read Calls.Initiate.All openid offline_access profile' does not exist. Trace ID: be7dd311-c09f-447e-9218-d2eecf989300 Correlation ID: a794fab4-3f00-4a68-91ed-ca16afb0d767 Timestamp: 2020-03-09 03:14:18Z at com.microsoft.identity.common.internal.controllers.ExceptionAdapter.getExceptionFromTokenErrorResponse(ExceptionAdapter.java:179) at com.microsoft.identity.common.internal.controllers.ExceptionAdapter.exceptionFromTokenResult(ExceptionAdapter.java:127) at com.microsoft.identity.common.internal.controllers.ExceptionAdapter.exceptionFromAcquireTokenResult(ExceptionAdapter.java:108) at com.microsoft.identity.common.internal.controllers.ApiDispatcher$4.run(ApiDispatcher.java:438) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:919)

I have no idea why the Calls.Initiate.All won't work here.
Please help me with this.

Latest androidx.* and msal1.0.0 updates

Hi Jason,

First of all many thanks for this tutorial and also for the last updates. Here are some issues I found as I was updating my app:

Chapter 2: Create an Android app

Section: Add fragments, step 9
3 imports need to be updated for androidx (namely, NonNull, Nullable and Fragment)

Chapter 3: Add Azure AD authentication

Section: Implement sign-in, step 9
The note at the end of this step needs to be changed

Section: Get user details, step 7
The argument in onSuccess() method needs to be of type IAuthenticationResult not AuthenticationResult

Chapter 4: Get calendar data

Section: Get calendar events, step 3
The note at the end of this step has a ">" in the middle of the second bullet point. I don't know if this is intentional or just a typo.

After dealing with these issues the app works well.

All the best
Mohamed

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.