我尝试在我的应用程序中实现一个客户经理,以避免用户每次打开应用程序时都必须登录。

所以基本上,我已经有了我的身份验证 Activity ,用户可以在其中输入其登录名和密码,并从服务器接收 token (身份验证目前是基本的)。现在,我想添加AccountManager,但是我真的不明白哪一部分会去哪里。

我需要的是非常基本的:

  • 如果我从未在
  • 之前从未登录过,请添加一个帐户
  • 如果我的帐户存在,则自动记录
  • (如果自动身份验证不起作用)在服务器上获取新 token

  • 这是我的代码:

    AuthenticationActivity.java
    public class AuthenticationActivity extends Activity {
    
        private EditText editTextUsername;
        private EditText editTextPassword;
        private Button buttonLogin;
        private ProgressBar spinner;
        private TextView error;
        private TextView register;
    
        private boolean accountRegistred;
    
        AccountManager accountManager;
    
        public static final String AUTHENTICATION = "authentication"; //action
    
        private ConnectionSuccessReceiver connectionSuccessReceiver = new ConnectionSuccessReceiver();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.authentification);
    
            accountManager = AccountManager.get(this);
            Account[] accounts = accountManager.getAccountsByType("login");
    
            if (accounts.length > 0) {
                //If there is an account
            } else {
                accountRegistred = false;
                editTextUsername = (EditText) findViewById(R.id.editText_login);
                editTextUsername.setVisibility(View.VISIBLE);
                editTextPassword = (EditText) findViewById(R.id.editText_password);
                editTextPassword.setVisibility(View.VISIBLE);
                buttonLogin = (Button) findViewById(R.id.button_connection);
                buttonLogin.setVisibility(View.VISIBLE);
                error = (TextView) findViewById(R.id.textView_error);
                register = (TextView) findViewById(R.id.textView_register);
                register.setVisibility(View.VISIBLE);
                spinner = (ProgressBar) findViewById(R.id.progressBar);
    
                buttonLogin.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        //Here we start the service which will reach the server
                        Intent i = new Intent(getApplicationContext(), AuthenticationService.class);
                        i.putExtra("username", editTextUsername.getText().toString());
                        i.putExtra("password", editTextPassword.getText().toString());
                        getApplication().startService(i);
                        spinner.setVisibility(View.VISIBLE);
                        error.setVisibility(View.INVISIBLE);
                    }
                });
    
                register.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        startActivity(new Intent(AuthenticationActivity.this, RegisterActivity.class));
                    }
                });
            }
            registerReceiver(connectionSuccessReceiver, new IntentFilter(AUTHENTICATION));
        }
    
        private class ConnectionSuccessReceiver extends BroadcastReceiver {
            //Called when the server returns success after authentication, we get the TOKEN here
            @Override
            public void onReceive(Context context, Intent intent) {
                if (intent.getStringExtra("STATE").equals("CONNECTED")) {
                    Intent i = new Intent(AuthenticationActivity.this, MainActivity.class);
                    i.putExtra("TOKEN", intent.getStringExtra("TOKEN"));
                    startActivity(i);
                } else {
                    spinner.setVisibility(View.INVISIBLE);
                    error.setVisibility(View.VISIBLE);
                }
                finish();
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unregisterReceiver(connectionSuccessReceiver);
        }
    }
    

    AuthenticatorService.java
    public class AuthenticatorService extends Service {
    
        /**
         * The implementation of the class |AccountAuthenticatorImpl|.
         * It is implemented as a singleton
         */
        private static AccountAuthenticator accountAuthenticator = null;
    
        /**
         * The main constructor.
         */
        public AuthenticatorService() {
            super();
        }
    
        /**
         * The bind method of the service.
         * @param intent The intent used to invoke the service
         * @return The binder of the class which has implemented |AbstractAccountAuthenticator|
         */
        @Override
        public IBinder onBind(Intent intent) {
            IBinder ret = null;
            if (intent.getAction().equals(android.accounts.AccountManager.ACTION_AUTHENTICATOR_INTENT)) {
                ret = getAuthenticator().getIBinder();
            }
            return ret;
        }
    
        /**
         * The method used to obtain the authenticator. It is implemented as a singleton
         * @return The implementation of the class |AbstractAccountAuthenticator|
         */
        private AccountAuthenticator getAuthenticator() {
            if (AuthenticatorService.accountAuthenticator == null) {
                AuthenticatorService.accountAuthenticator = new AccountAuthenticator(this);
            }
    
            return AuthenticatorService.accountAuthenticator;
        }
    
        public class AccountAuthenticator extends AbstractAccountAuthenticator {
            private Context context;
    
            public AccountAuthenticator(Context context) {
                super(context);
                this.context = context;
            }
    
            @Override
            public Bundle editProperties(AccountAuthenticatorResponse accountAuthenticatorResponse, String s) {
                return null;
            }
    
            @Override
            public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException {
    
                Bundle reply = new Bundle();
    
                Intent i = new Intent(context, AuthenticationActivity.class);
                i.setAction("com.readyo.app.authentication.addnewaccount");
                i.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
                i.putExtra("AuthTokenType", authTokenType);
    
                reply.putParcelable(AccountManager.KEY_INTENT, i);
    
                return reply;
            }
    
            @Override
            public Bundle confirmCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, Bundle bundle) throws NetworkErrorException {
                return null;
            }
    
            @Override
            public Bundle getAuthToken(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String s, Bundle bundle) throws NetworkErrorException {
                return null;
            }
    
            @Override
            public String getAuthTokenLabel(String s) {
                return null;
            }
    
            @Override
            public Bundle updateCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String s, Bundle bundle) throws NetworkErrorException {
                return null;
            }
    
            @Override
            public Bundle hasFeatures(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String[] strings) throws NetworkErrorException {
                return null;
            }
        }
    }
    

    我也有代码通过HTTP到达服务器,但是我不确定在这里是否很重要。

    感谢您的时间。

    最佳答案

    这是一个较晚的响应,但也许该示例可以为您提供帮助:
    https://github.com/dawidgdanski/AccountAuthenticatorExample

    我是在一段时间前创建的,但是注册/登录的逻辑可能会有所帮助

    add an account if I never logged in before:
    
  • 如果您的应用程序流程需要用户登录才能访问数据,则只需声明您的LoginActivity作为要显示的主要对象即可。

  • 验证并验证用户凭据后,请调用AccountManager.addAccountExcplicitly()方法。
  • 另一方面,如果您公开了一些匿名用户可以看到的屏幕,则在提供登录/注册功能的应用程序部分(设置或任何其他内容)中,调用AccountManager.addAccount()。该调用将激活您的AccountAuthenticator,该AccountAuthenticator在YourAccountAuthenticator.addAccount()中处理您的请求,并可能根据您的需要显示LoginActivity/SignUpActivity。

  • 请记住,您也可以从“系统设置”中创建特定于应用程序的帐户。
        log automatically if my account exists
    

    好吧,我不确定我是否正确理解您的需求。将帐户存储在AccountManager的元数据中后,调用AccountManager.getAccountsByType(“my.account.type”)即可使用该帐户。
    如果要自动登录,则必须将凭据存储在某个地方,这显然受到敏感数据泄漏的威胁。
     if the auto authentication doesn't work get a new token on the server
    

    有一个AccountManager.invalidateAuthToken()方法,该方法删除当前存储的authToken并调用另一个。

    您可以启动示例应用程序,我认为它至少可以解决您的一些问题,因为它涵盖了以下逻辑:
  • 登录/注册
  • 身份验证 token 无效
  • 显示当前登录的帐户
  • 注销

  • 干杯

    关于android - 如何在我的应用程序中实现AccountManager,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27927252/

    10-12 02:36