package akechi.projectl.authenticator; import akechi.projectl.AppContext; import akechi.projectl.HomeActivity; import akechi.projectl.R; import android.accounts.Account; import android.accounts.AccountAuthenticatorActivity; import android.accounts.AccountManager; import android.app.LoaderManager; import android.content.AsyncTaskLoader; import android.content.Context; import android.content.Intent; import android.content.Loader; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.util.Pair; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import com.google.api.client.extensions.android.http.AndroidHttp; import com.google.common.base.Strings; import com.google.common.base.Supplier; import java.io.EOFException; import java.io.IOException; import java.util.concurrent.TimeUnit; import akechi.projectl.async.LingrTaskLoader; import jp.michikusa.chitose.lingr.LingrClient; import jp.michikusa.chitose.lingr.LingrClientFactory; import jp.michikusa.chitose.lingr.LingrException; import jp.michikusa.chitose.lingr.Session; public class LingrAuthenticatorActivity extends AccountAuthenticatorActivity implements Button.OnClickListener, LoaderManager.LoaderCallbacks<Pair<String, Exception>> { static final String ARG_ACCOUNT_TYPE = "accountType"; static final String ARG_AUTH_TYPE = "authType"; static final String ARG_IS_ADDING_NEW_ACCOUNT = "isAddingNewAccount"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(R.layout.activity_lingr_authenticator); this.findViewById(R.id.saveButton).setOnClickListener(this); this.userIdText= (EditText)this.findViewById(R.id.userIdText); this.passwordText= (EditText)this.findViewById(R.id.passwordText); this.apiKeyText= (EditText)this.findViewById(R.id.apiKeyText); this.getLoaderManager().initLoader(LOADER_LOGIN, null, this); } @Override public void onClick(View v) { this.findViewById(R.id.saveButton).setEnabled(false); this.getLoaderManager().getLoader(LOADER_LOGIN).forceLoad(); } @Override public void onLoaderReset(Loader<Pair<String, Exception>> loader) { } @Override public Loader<Pair<String, Exception>> onCreateLoader(int id, Bundle args) { switch(id) { case LOADER_LOGIN:{ return new LoginLoader( this, new Supplier<String>(){ @Override public String get() { return LingrAuthenticatorActivity.this.userIdText.getText().toString(); } }, new Supplier<String>(){ @Override public String get() { return LingrAuthenticatorActivity.this.passwordText.getText().toString(); } }, new Supplier<String>(){ @Override public String get() { return LingrAuthenticatorActivity.this.apiKeyText.getText().toString(); } } ); } } return null; } @Override public void onLoadFinished(Loader<Pair<String, Exception>> loader, Pair<String, Exception> data) { this.findViewById(R.id.saveButton).setEnabled(true); if(!Strings.isNullOrEmpty(data.first)) { final Account account= new Account(this.userIdText.getText().toString(), "com.lingr"); final Bundle bundle= new Bundle(); bundle.putString("apiKey", this.apiKeyText.getText().toString()); final AccountManager manager= AccountManager.get(this); manager.addAccountExplicitly(account, this.passwordText.getText().toString(), bundle); manager.setAuthToken(account, "", data.first); Toast.makeText(this, "Account successfuly added", Toast.LENGTH_SHORT).show(); // ProjectL will be started { final Intent intent= new Intent(this, HomeActivity.class); this.startActivity(intent); } this.finish(); } else if(data.second != null) { Log.e("LingrAuthActivity", "Login failed", data.second); Toast.makeText(this, "Sorry, detect an error. Retry, please...", Toast.LENGTH_SHORT).show(); } } private static final class LoginLoader extends AsyncTaskLoader<Pair<String, Exception>> { public LoginLoader(Context context, Supplier<String> userIdSupplier, Supplier<String> passwordSupplier, Supplier<String> apiKeySupplier) { super(context); this.userIdSupplier= userIdSupplier; this.passworSupplier= passwordSupplier; this.apiKeySupplier= apiKeySupplier; } @Override public Pair<String, Exception> loadInBackground() { try { int nretries= 0; while(nretries < MAX_NRETRIES) { try { final AppContext appContext= (AppContext)this.getContext(); final AccountManager manager= AccountManager.get(this.getContext()); final LingrClient lingr= appContext.getLingrClient(); final String userId= this.userIdSupplier.get(); final String password= this.passworSupplier.get(); final String apiKey= this.apiKeySupplier.get(); final String authToken; if(Strings.isNullOrEmpty(apiKey)) { authToken= lingr.createSession(userId, password); } else { authToken= lingr.createSession(userId, password, apiKey); } return Pair.create(authToken, null); } catch(EOFException e) { // android's bug, ignore and retry final long waitTimeMillis= Math.min(this.getWaitTimeMillis(nretries++), MAX_WAIT_TIME_MILLIS); Thread.sleep(waitTimeMillis); } } return Pair.create(null, null); } catch(Exception e) { return Pair.create(null, e); } } private long getWaitTimeMillis(int nretries) { return (long)Math.pow(2, nretries) * 500L; } private static final int MAX_NRETRIES= 5; private static final long MAX_WAIT_TIME_MILLIS= TimeUnit.SECONDS.toMillis(10); private final Supplier<String> userIdSupplier; private final Supplier<String> passworSupplier; private final Supplier<String> apiKeySupplier; } private static final int LOADER_LOGIN= 0; private EditText userIdText; private EditText passwordText; private EditText apiKeyText; }