Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 1569a13b authored by David Luhmer's avatar David Luhmer Committed by GitHub
Browse files

Merge pull request #62 from nextcloud/fix-account-not-found

Fix account not found - Fix #60
parents 9f07430c c6e8e20d
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -67,6 +67,13 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    AccountImporter.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}

// Complete example: https://github.com/nextcloud/news-android/blob/master/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/LoginDialogFragment.java
```

@@ -250,7 +257,7 @@ if (VersionCheckHelper.verifyMinVersion(context, MIN_NEXTCLOUD_FILES_APP_VERSION
}
``` 

## Nextcloud Conference 2018 Talk
## Nextcloud Conference 2018 Talk (5min)

[![Nextcloud Single Sign On for Android David Luhmer](https://img.youtube.com/vi/gnLOwmrJLUw/0.jpg)](https://www.youtube.com/watch?v=gnLOwmrJLUw)

+83 −3
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

package com.nextcloud.android.sso;

import android.Manifest;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.Activity;
@@ -28,10 +29,12 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import com.nextcloud.android.sso.exceptions.AndroidGetAccountsPermissionNotGranted;
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountPermissionNotGrantedException;
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotInstalledException;
@@ -44,8 +47,12 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;

import io.reactivex.annotations.NonNull;

import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_OK;
import static com.nextcloud.android.sso.Constants.NEXTCLOUD_FILES_ACCOUNT;
@@ -60,6 +67,7 @@ public class AccountImporter {

    public static final int CHOOSE_ACCOUNT_SSO = 4242;
    public static final int REQUEST_AUTH_TOKEN_SSO = 4243;
    public static final int REQUEST_GET_ACCOUNTS_PERMISSION = 4244;

    private static SharedPreferences SHARED_PREFERENCES;

@@ -67,7 +75,9 @@ public class AccountImporter {
        return findAccounts(context).size() > 0;
    }

    public static void pickNewAccount(Activity activity) throws NextcloudFilesAppNotInstalledException {
    public static void pickNewAccount(Activity activity) throws NextcloudFilesAppNotInstalledException, AndroidGetAccountsPermissionNotGranted {
        checkAndroidAccountPermissions(activity);

        if (appInstalledOrNot(activity, "com.nextcloud.client")) {
            Intent intent = AccountManager.newChooseAccountIntent(null, null, new String[]{"nextcloud"},
                    true, null, null, null, null);
@@ -77,7 +87,9 @@ public class AccountImporter {
        }
    }

    public static void pickNewAccount(Fragment fragment) throws NextcloudFilesAppNotInstalledException {
    public static void pickNewAccount(Fragment fragment) throws NextcloudFilesAppNotInstalledException, AndroidGetAccountsPermissionNotGranted {
        checkAndroidAccountPermissions(fragment.getContext());

        if (appInstalledOrNot(fragment.getContext(), "com.nextcloud.client")) {
            Intent intent = AccountManager.newChooseAccountIntent(null, null, new String[]{"nextcloud"},
                    true, null, null, null, null);
@@ -87,6 +99,25 @@ public class AccountImporter {
        }
    }

    public static void requestAndroidAccountPermissionsAndPickAccount(Activity activity) {
        ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.GET_ACCOUNTS}, REQUEST_GET_ACCOUNTS_PERMISSION);
    }

    private static void checkAndroidAccountPermissions(Context context) throws AndroidGetAccountsPermissionNotGranted {
        // https://developer.android.com/reference/android/accounts/AccountManager#getAccountsByType(java.lang.String)
        // Caller targeting API level below Build.VERSION_CODES.O that have not been granted the Manifest.permission.GET_ACCOUNTS permission,
        // will only see those accounts managed by AbstractAccountAuthenticators whose signature matches the client.
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            // Do something for lollipop and above versions
            if (ContextCompat.checkSelfPermission(context, Manifest.permission.GET_ACCOUNTS) != PackageManager.PERMISSION_GRANTED) {
                Log.e(TAG, "Permission not granted yet!");
                throw new AndroidGetAccountsPermissionNotGranted();
            } else {
                Log.d(TAG, "Permission granted!");
            }
        }
    }

    private static boolean appInstalledOrNot(Context context, String uri) {
        PackageManager pm = context.getPackageManager();
        try {
@@ -101,7 +132,7 @@ public class AccountImporter {
    // Find all currently installed nextcloud accounts on the phone
    public static List<Account> findAccounts(final Context context) {
        final AccountManager accMgr = AccountManager.get(context);
        final Account[] accounts = accMgr.getAccounts();
        final Account[] accounts = accMgr.getAccountsByType("nextcloud");

        List<Account> accountsAvailable = new ArrayList<>();
        for (final Account account : accounts) {
@@ -205,6 +236,17 @@ public class AccountImporter {
                    SingleSignOnAccount singleSignOnAccount = extractSingleSignOnAccountFromResponse(data, context);
                    callback.accountAccessGranted(singleSignOnAccount);
                    break;
                case REQUEST_GET_ACCOUNTS_PERMISSION:
                    try {
                        if(activity != null) {
                            pickNewAccount(activity);
                        } else {
                            pickNewAccount(fragment);
                        }
                    } catch (NextcloudFilesAppNotInstalledException  | AndroidGetAccountsPermissionNotGranted e) {
                        UiExceptionManager.showDialogForException(context, e);
                    }
                    break;
                default:
                    break;
            }
@@ -224,12 +266,50 @@ public class AccountImporter {
                        Log.e(TAG, e.getMessage());
                    }
                    break;
                case REQUEST_GET_ACCOUNTS_PERMISSION:
                    UiExceptionManager.showDialogForException(context, new AndroidGetAccountsPermissionNotGranted());
                    break;
                default:
                    break;
            }
        }
    }

    public static void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults, Activity activity) {
        onRequestPermissionsResult(requestCode, permissions, grantResults, activity, null);
    }

    public static void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults, Fragment fragment) {
        onRequestPermissionsResult(requestCode, permissions, grantResults, null, fragment);
    }

    private static void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults, Activity activity, Fragment fragment) {
        Context context = (activity != null) ? activity : fragment.getContext();

        switch (requestCode) {
            case REQUEST_GET_ACCOUNTS_PERMISSION:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // Permissions have been granted.. start pick account dialog
                    try {
                        if (activity != null) {
                            pickNewAccount(activity);
                        } else {
                            pickNewAccount(fragment);
                        }
                    } catch (NextcloudFilesAppNotInstalledException | AndroidGetAccountsPermissionNotGranted e) {
                        UiExceptionManager.showDialogForException(context, e);
                    }
                } else {
                    // user declined the permission request..
                    UiExceptionManager.showDialogForException(context, new AndroidGetAccountsPermissionNotGranted());
                }
                break;
            default:
                break;
        }

    }

    public static void handleFailedAuthRequest(Intent data) throws SSOException {
        String exception = data.getStringExtra(NEXTCLOUD_SSO_EXCEPTION);
        throw SSOException.parseNextcloudCustomException(new Exception(exception));
+17 −0
Original line number Diff line number Diff line
package com.nextcloud.android.sso.exceptions;

import android.content.Context;

import com.nextcloud.android.sso.R;
import com.nextcloud.android.sso.model.ExceptionMessage;

public class AndroidGetAccountsPermissionNotGranted extends SSOException {

    @Override
    public void loadExceptionMessage(Context context) {
        this.em = new ExceptionMessage(
             context.getString(R.string.android_get_accounts_permission_not_granted_exception_title),
             context.getString(R.string.android_get_accounts_permission_not_granted_exception_message)
        );
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -29,8 +29,8 @@ public class CurrentAccountNotFoundException extends SSOException {
    @Override
    public void loadExceptionMessage(Context context) {
        this.em = new ExceptionMessage(
            em.title   = context.getString(R.string.current_account_not_found_exception_title),
            em.message = context.getString(R.string.current_account_not_found_exception_message)
            context.getString(R.string.current_account_not_found_exception_title),
            context.getString(R.string.current_account_not_found_exception_message)
        );
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -3,6 +3,9 @@
    <string name="no_current_account_selected_exception_title">Warning</string>
    <string name="no_current_account_selected_exception_message">No account selected yet</string>

    <string name="android_get_accounts_permission_not_granted_exception_title">Error</string>
    <string name="android_get_accounts_permission_not_granted_exception_message">In order to use the Nextcloud Single-Sign-On on this device, you need to grant permission to access your accounts</string>

    <string name="current_account_not_found_exception_title">Warning</string>
    <string name="current_account_not_found_exception_message">Selected account was not found. Something went wrong..</string>