2015-01-13 20 views
5

Tôi cố gắng triển khai trình quản lý tài khoản trong ứng dụng của mình để tránh người dùng phải đăng nhập mỗi lần mở ứng dụng.Cách triển khai AccountManager trong ứng dụng của tôi

Vì vậy, về cơ bản, tôi đã có Hoạt động xác thực của tôi, nơi người dùng có thể đặt đăng nhập và mật khẩu của mình và nơi chúng tôi nhận được một mã thông báo từ máy chủ (xác thực là cơ bản cho bây giờ). Bây giờ tôi muốn thêm AccountManager nhưng tôi không thực sự hiểu phần nào sẽ đi đến đâu.

Những gì tôi cần là khá cơ bản:

  • thêm một tài khoản nếu tôi chưa từng đăng nhập trước khi
  • log tự động nếu tài khoản của tôi tồn tại
  • nếu xác thực tự động không hoạt động nhận mã mới trên máy chủ

đây là mã của tôi:

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; 
     } 
    } 
} 

Tôi cũng có mã để đạt được máy chủ thông qua HTTP nhưng tôi không chắc chắn nó sẽ là quan trọng ở đây.

Cảm ơn bạn đã dành thời gian.

Trả lời

2

Đó là một phản ứng chậm trễ chút nhưng có lẽ mẫu này có thể giúp bạn: https://github.com/dawidgdanski/AccountAuthenticatorExample

tôi tạo ra nó một thời gian trước nhưng logic với đăng ký/đăng nhập có thể hữu ích

add an account if I never logged in before: 
  1. Nếu luồng ứng dụng của bạn yêu cầu người dùng đăng nhập để có quyền truy cập vào dữ liệu, thì chỉ cần khai báo LoginActivity của bạn làm dữ liệu chính sẽ được hiển thị.

Khi bạn xác thực và xác minh bằng chứng xác thực người dùng, hãy gọi phương thức AccountManager.addAccountExcplicitly().

  1. Mặt khác, nếu bạn hiển thị một số màn hình cho người dùng ẩn danh thì trong phần ứng dụng (cài đặt hoặc bất kỳ) nào bạn cung cấp chức năng đăng nhập/đăng ký, hãy gọi Trình quản lý tài khoản. thêm tài khoản(). Cuộc gọi này kích hoạt Trình xác thực tài khoản của bạn xử lý yêu cầu của bạn trong YourAccountAuthenticator.addAccount() và có thể hiển thị LoginActivity/SignUpActivity theo nhu cầu của bạn.

Xin lưu ý rằng bạn cũng có thể tạo tài khoản ứng dụng cụ thể từ Cài đặt hệ thống.

log automatically if my account exists 

Vâng, tôi không chắc liệu tôi có hiểu chính xác nhu cầu của bạn hay không. Khi bạn lưu trữ Tài khoản trong dữ liệu meta của AccountManager, nó có sẵn khi bạn gọi AccountManager.getAccountsByType ("my.account.type"). Nếu bạn muốn đăng nhập tự động sau đó bạn phải một nơi nào đó lưu trữ thông tin đăng nhập của bạn rõ ràng là dưới sự đe dọa của rò rỉ dữ liệu nhạy cảm.

if the auto authentication doesn't work get a new token on the server 

Phương thức AccountManager.invalidateAuthToken() loại bỏ authToken hiện đang lưu trữ và gọi cho một số khác.

Bạn có thể khởi chạy các ứng dụng Ví dụ, tôi nghĩ rằng nó có thể giải quyết ít nhất một số vấn đề của bạn bởi vì nó bao gồm logic sau đây:

  • đăng nhập/đăng ký
  • auth thẻ huỷ bỏ hiệu lực
  • hiển thị hiện đang đăng nhập chiếm
  • logout

Cheers

Các vấn đề liên quan