我的应用程序有一个带帐户管理器的登录工具,它在验证后用oauth令牌存储帐户。如果应用程序在备份后的每一天当时处于空闲状态,我需要在11:59:59自动注销该用户数据库数据到应用程序内部存储并需要清除原始数据库内容。如果用户当时正在处理应用程序,则在5分钟不活动后注销用户。当用户在此自动注销后出现时,用户名应为默认情况下显示在登录活动中。我怎么能这样做?下面是我的代码。
AccountAuthenticator.java:
public class AccountAuthenticator extends AbstractAccountAuthenticator {
private final Context context;
private String TAG = getClass().getSimpleName();
public AccountAuthenticator(Context context) {
super(context);
this.context = context;
}
@Override
public Bundle addAccount(AccountAuthenticatorResponse accountAuthenticatorResponse, String accountType,
String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException {
System.out.println("SaveItAuthenticator addAccount....");
final Intent intent = new Intent(context, LoginActivity.class);
intent.putExtra(LoginActivity.ARG_ACCOUNT_TYPE, accountType);
intent.putExtra(LoginActivity.ARG_AUTH_TYPE, authTokenType);
intent.putExtra(LoginActivity.ARG_IS_ADDING_ACCOUNT, true);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, accountAuthenticatorResponse);
System.out.println("SaveItAuthenticator addAccount mid");
final Bundle bundle = new Bundle();
if (options != null) {
bundle.putAll(options);
}
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
System.out.println("SaveItAuthenticator addAccount end");
return bundle;
}
/* @Override
public Bundle getAccountRemovalAllowed(AccountAuthenticatorResponse response, Account account) throws NetworkErrorException {
Bundle bundle = new Bundle();
boolean allowed = true;
bundle.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, allowed);
return bundle;
} */
@Override
public Bundle getAuthToken(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account,
String authTokenType, Bundle options) throws NetworkErrorException {
System.out.println("SaveItAuthenticator getAuthToken....");
if (!authTokenType.equals(AccountGeneral.AUTHTOKEN_TYPE_READ_ONLY) &&
!authTokenType.equals(AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS)) {
final Bundle result = new Bundle();
result.putString(AccountManager.KEY_ERROR_MESSAGE, "Invalid authTokenType");
return result;
}
final AccountManager manager = AccountManager.get(context.getApplicationContext());
String authToken = manager.peekAuthToken(account, authTokenType);
Log.d("SaveItAndroidOauth", TAG + " > peekAuthToken returned - " + authToken);
if (TextUtils.isEmpty(authToken)) {
System.out.println("*************** if TextUtils.isEmpty(authToken) ******************");
final String password = manager.getPassword(account);
System.out.println("*************** password ****************** "+password);
final String refreshToken = manager.getUserData(account, LoginActivity.KEY_REFRESH_TOKEN);
if (password != null) {
try {
System.out.println("Discounty > re-authenticating with refresh token "+refreshToken);
AccessToken accessToken = discountyService.getAccessToken(DiscountyService.ACCESS_GRANT_TYPE,
username, password).toBlocking().first();
authToken = accessToken.getValue();
RefreshToken tokenRef = accessToken.getRefreshToken();
String refreshtoken = tokenRef.getValue();
// manager.setPassword(account,"password");
manager.setUserData(account, LoginActivity.KEY_REFRESH_TOKEN, refreshtoken);
} catch (Exception e) {
e.printStackTrace();
}
}
}
if (!TextUtils.isEmpty(authToken)) {
final Bundle result = new Bundle();
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
return result;
}
// If we get here, then we couldn't access the user's password - so we
// need to re-prompt them for their credentials. We do that by creating
// an intent to display our AuthenticatorActivity.
final Intent intent = new Intent(context, LoginActivity.class);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, accountAuthenticatorResponse);
intent.putExtra(LoginActivity.ARG_ACCOUNT_TYPE, account.type);
intent.putExtra(LoginActivity.ARG_AUTH_TYPE, authTokenType);
intent.putExtra(LoginActivity.ARG_ACCOUNT_NAME, account.name);
final Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
}
@Override
public String getAuthTokenLabel(String authTokenType) {
if (AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS.equals(authTokenType)) {
return AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS_LABEL;
} else if (AccountGeneral.AUTHTOKEN_TYPE_READ_ONLY.equals(authTokenType)) {
return AccountGeneral.AUTHTOKEN_TYPE_READ_ONLY_LABEL;
} else {
return authTokenType + " (Label)";
}
}
@Override
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
return null;
}
@Override
public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {
return null;
}
@Override
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
return null;
}
@Override
public Bundle hasFeatures(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String[] features) throws NetworkErrorException {
final Bundle result = new Bundle();
result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
return result;
}
}
LoginActivity.java:
public class LoginActivity extends AccountAuthenticatorActivity {
public final static String ARG_ACCOUNT_TYPE = "ACCOUNT_TYPE";
public final static String ARG_AUTH_TYPE = "AUTH_TYPE";
public final static String ARG_ACCOUNT_NAME = "ACCOUNT_NAME";
public final static String ARG_IS_ADDING_ACCOUNT = "AS_ADDING_ACCOUNT";
public final static String KEY_ERROR_MESSAGE = "ERR_MSG";
public static final String PARAM_USER_PASS = "USER_PASS";
public static final String KEY_REFRESH_TOKEN = "REFRESH_TOKEN";
/**
* Id to identity READ_CONTACTS permission request.
*/
private static final int REQUEST_READ_CONTACTS = 0;
/**
* A dummy authentication store containing known user names and passwords.
* TODO: remove after connecting to a real authentication system.
*/
private static final String[] DUMMY_CREDENTIALS = new String[]{
"foo@example.com:hello", "bar@example.com:world",
"yakovenko.denis.a@gmail.com:password", "a@:aaaaa"
};
private final int REQ_SIGNUP = 1;
private final String TAG = this.getClass().getSimpleName();
private AccountManager accountManager;
// 60 seconds (1 minute) * 180 = 3 hours
public static final int SYNC_INTERVAL = 60;
public static final int SYNC_FLEXTIME = SYNC_INTERVAL / 3;
private String authTokenType;
private EditText edtUserName,edtPassword;
View mProgressView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
System.out.println("Login Activity starts....");
accountManager = AccountManager.get(getBaseContext());
String accountName = getIntent().getStringExtra(ARG_ACCOUNT_NAME);
authTokenType = getIntent().getStringExtra(ARG_AUTH_TYPE);
edtUserName = (EditText)findViewById(R.id.edtUserName);
edtPassword = (EditText)findViewById(R.id.edtPassword);
if (authTokenType != null) {
authTokenType = AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS;
}
if (accountName != null) {
edtUserName.setText(accountName);
}
findViewById(R.id.submit).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
submit();
}
});
findViewById(R.id.signUp).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Since there can only be one AuthenticatorActivity, we call the sign up activity, get his results,
// and return them in setAccountAuthenticatorResult(). See finishLogin().
Intent signup = new Intent(getBaseContext(), SignUpActivity.class);
signup.putExtras(getIntent().getExtras());
startActivityForResult(signup, REQ_SIGNUP);
}
});
}
public void submit() {
final String userName = edtUserName.getText().toString();
final String password = edtPassword.getText().toString();
final String accountType = getIntent().getStringExtra(ARG_ACCOUNT_TYPE);
new AsyncTask<String, Void, Intent>() {
@Override
protected void onPreExecute() {
super.onPreExecute();
// showProgress(true);
}
@Override
protected Intent doInBackground(String... params) {
Log.d("Discounty", TAG + " > Started authenticating"); // 1
String authtoken, refreshtoken;
Bundle data = new Bundle();
try {
// if (NetworkHelper.isInternetAvailable(getBaseContext())) {
AccessToken accessToken = discountyService.getAccessToken(DiscountyService.ACCESS_GRANT_TYPE,
username, password).toBlocking().first();
authtoken = accessToken.getValue();
RefreshToken tokenRef = accessToken.getRefreshToken();
refreshtoken = tokenRef.getValue();
System.out.println("refreshtoken to store is "+refreshtoken);
data.putString(AccountManager.KEY_ACCOUNT_NAME, userName);
data.putString(AccountManager.KEY_ACCOUNT_TYPE, accountType);
data.putString(AccountManager.KEY_AUTHTOKEN, authtoken);
data.putString(PARAM_USER_PASS, "password");//password
data.putString(KEY_REFRESH_TOKEN, refreshtoken);
// }
} catch (Exception e) {
data.putString(KEY_ERROR_MESSAGE, e.getMessage());
}
final Intent result = new Intent();
result.putExtras(data);
return result;
}
@Override
protected void onPostExecute(Intent intent) {
// showProgress(false);
if (intent.hasExtra(KEY_ERROR_MESSAGE)) {
Toast.makeText(getBaseContext(), intent.getStringExtra(KEY_ERROR_MESSAGE),
Toast.LENGTH_LONG).show();
} else {
System.out.println("Now finish login"); // 3
finishLogin(intent);
}
}
}.execute();
}
private void finishLogin(Intent intent) {
String accountName = intent.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
String accountPassword = intent.getStringExtra(PARAM_USER_PASS);
final Account account = new Account(accountName, intent.getStringExtra(AccountManager.KEY_ACCOUNT_TYPE));
if (getIntent().getBooleanExtra(ARG_IS_ADDING_ACCOUNT, false)) {
String authtoken = intent.getStringExtra(AccountManager.KEY_AUTHTOKEN);
String authtokenType = authTokenType;
String refreshToken = intent.getStringExtra(KEY_REFRESH_TOKEN);
Bundle userData = new Bundle();
userData.putString(KEY_REFRESH_TOKEN, refreshToken);
accountManager.addAccountExplicitly(account, accountPassword, userData);
accountManager.setAuthToken(account, authtokenType, authtoken);
accountManager.setUserData(account,KEY_REFRESH_TOKEN,refreshToken);
try {
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("condition else getIntent().getBooleanExtra(ARG_IS_ADDING_ACCOUNT, false)");
accountManager.setPassword(account, accountPassword);
}
setAccountAuthenticatorResult(intent.getExtras());
setResult(RESULT_OK, intent);
finish();
}
}
MainActivity.java:
public class MainActivity extends Activity {
private static final String STATE_DIALOG = "state_dialog";
private static final String STATE_INVALIDATE = "state_invalidate";
private String TAG = this.getClass().getSimpleName();
private AccountManager accountManager;
private AlertDialog alertDialog;
private boolean invalidate;
Account mAccount;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
accountManager = AccountManager.get(this);
if (accountManager.getAccountsByType(AccountGeneral.ACCOUNT_TYPE).length == 0) {
addNewAccount(accountManager);
} else {
Account[] accountList = accountManager.getAccountsByType(AccountGeneral.ACCOUNT_TYPE);
mAccount = accountList[0];
System.out.println("There is an account...."+mAccount);
setContentView(R.layout.activity_main);
}
}
@Override
protected void onResume() {
super.onResume();
}
private void addNewAccount(AccountManager manager) {
final AccountManagerFuture<Bundle> accountManagerFuture = manager.addAccount(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS, null, null, this,
new AccountManagerCallback<Bundle>() {
@Override
public void run(AccountManagerFuture<Bundle> accountManagerFuture) {
System.out.println("AccountManagerFuture starts running...."); // 6
try {
Bundle bnd = accountManagerFuture.getResult();
} catch (Exception e) {
e.printStackTrace();
MainActivity.this.finish();
}
}
}, null);
}
private void performLogout() {
try {
Account[] accounts = accountManager.getAccountsByType(AccountGeneral.ACCOUNT_TYPE);
if (accounts.length != 0) {
ContentResolver.cancelSync(accounts[0],"com.fortune.saveitandroidoauth");
final AccountManagerFuture<Bundle> future = accountManager.getAuthToken(accounts[0], AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS, null, this, null,null);
new Thread(new Runnable() {
@Override
public void run() {
try {
Bundle bnd = future.getResult();
final String authtoken = bnd.getString(AccountManager.KEY_AUTHTOKEN);
System.out.println("User is going to logout "+authtoken);
serverAuthenticateService.logOut(authtoken);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
Log.d("ACCOUNT", accounts[0].toString());
Log.d("ACCOUNT TOKEN TYPE", accounts[0].type);
Log.d("ACCOUNT TOKEN NAME", accounts[0].name);//accountManagerFuture
accountManager.clearPassword(accounts[0]);
// accountManager.setUserData(accounts[0],LoginActivity.KEY_REFRESH_TOKEN, null);
String accessToken = accountManager.getAuthToken(accounts[0], AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS, null, true,
new AccountManagerCallback<Bundle>() {
@Override
public void run(AccountManagerFuture<Bundle> accountManagerFuture) {
System.out.println("invalidate thread running....");
try {
System.out.println("invalidateAuthToken...."+accountManagerFuture.getResult().toString());
Log.d("invalidateAuthToken", accountManagerFuture.getResult().toString());
} catch (android.accounts.OperationCanceledException | AuthenticatorException | IOException e) {
e.printStackTrace();
}
}
}, null).toString();
accountManager.invalidateAuthToken(AccountGeneral.ACCOUNT_TYPE,accessToken);
if (Build.VERSION.SDK_INT < 22) { // use deprecated method
System.out.println("removeAccount .... SDK_INT < 22 ");
accountManager.removeAccount(accounts[0], null, null);
} else {
System.out.println("removeAccountExplicitly .... SDK_INT >= 22 ");
accountManager.removeAccountExplicitly(accounts[0]);
}
addNewAccount(accountManager);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
switch (id) {
case android.R.id.home:
return true;
case R.id.action_settings:
return true;
case R.id.action_sync:
return true;
case R.id.action_logout:
performLogout();
return true;
}
return super.onOptionsItemSelected(item);
}
}
DBHelper.java:
public class DBHelper extends OrmLiteSqliteOpenHelper {
private Context context;
private static final String DATABASE_NAME = "MyDatabase.db";
private static final int DATABASE_VERSION = 1;
private Dao<AccountingPeriod,Integer> accPerDao=null;
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.context=context;
}
@Override
public void onCreate(SQLiteDatabase sqliteDatabase, ConnectionSource connectionSource) {
try{
Log.i(DatabaseHelper.class.getName(),"onCreate");
TableUtils.createTable(connectionSource, AccountingPeriod.class);
}catch(Exception ex){
Log.e(DatabaseHelper.class.getName(), "Unable to create datbases", ex);
}
}
@Override
public void onUpgrade(SQLiteDatabase sqliteDatabase, ConnectionSource connectionSource, int oldVer, int newVer) {
try{
Log.i(DatabaseHelper.class.getName(),"onUpgrade");
TableUtils.dropTable(connectionSource, AccountingPeriod.class, true);
onCreate(sqliteDatabase, connectionSource);
}catch(Exception ex){
Log.e(DatabaseHelper.class.getName(), "Can't drop databases", ex);
throw new RuntimeException(ex);
}
}
public Dao<AccountingPeriod, Integer> getAccPerDao() throws SQLException {
if (accPerDao == null) {
accPerDao = getDao(AccountingPeriod.class);
}
return accPerDao;
}
@Override
public void close() {
super.close();
}
public void deleteAll() {
try{
TableUtils.dropTable(connectionSource, AccountingPeriod.class, true);
SQLiteDatabase sqliteDatabase = null;
onCreate(sqliteDatabase, connectionSource);
}catch(Exception ew){
}
}
}