package io.itch.authentication; import io.itch.api.ItchApiClient; import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AccountManagerCallback; import android.accounts.AccountManagerFuture; import android.app.Activity; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; public class SessionHelper { public static final String ACCOUNT_TYPE = "io.itch.account_type.user"; public static final String AUTH_TOKEN_TYPE_FULL = "io.itch.session.token_type.full"; private static SessionHelper SHARED_INSTANCE; private static final Object LOCK = new Object(); private Boolean loggedIn; private String token; public static SessionHelper getInstance() { if (SHARED_INSTANCE == null) { synchronized (LOCK) { if (SHARED_INSTANCE == null) { SHARED_INSTANCE = new SessionHelper(); } } } return SHARED_INSTANCE; } private SessionHelper() { this.loggedIn = false; } public Boolean isLoggedIn() { synchronized (LOCK) { return loggedIn; } } private void setLoggedIn(Boolean loggedIn) { synchronized (LOCK) { this.loggedIn = loggedIn; } } public String getToken() { synchronized (LOCK) { return token; } } private void setToken(String token) { synchronized (LOCK) { this.token = token; } ItchApiClient.setToken(token); } public void login(final Activity context, final SessionCallback callback) { AccountManager am = AccountManager.get(context); am.addAccount(ACCOUNT_TYPE, AUTH_TOKEN_TYPE_FULL, null, null, context, new AccountManagerCallback<Bundle>() { @Override public void run(AccountManagerFuture<Bundle> future) { boolean success = false; try { Object t = future.getResult().get(AccountManager.KEY_ACCOUNT_NAME); if (t instanceof String) { String name = (String) t; if (!TextUtils.isEmpty(name)) { success = true; } } } catch (Exception e) { Log.e("Itch", "Login failure", e); } finally { if (success) { restoreSession(context, callback); } else if (callback != null) { callback.onFailed(); } } } }, null); } public void logout(final Activity context, final SessionCallback callback) { AccountManager am = AccountManager.get(context); Account[] accounts = am.getAccountsByType(ACCOUNT_TYPE); if (accounts != null && accounts.length > 0) { for (Account account : accounts) { am.removeAccount(account, new AccountManagerCallback<Boolean>() { @Override public void run(AccountManagerFuture<Boolean> future) { if (callback != null) { boolean success = false; try { success = future.getResult(); } catch (Exception e) { success = false; Log.e("Itch", "Failed to log out", e); } finally { if (success) { setLoggedIn(false); setToken(null); callback.onSuccess(); } else { callback.onFailed(); } } } } }, null); } } } public void restoreSession(final Activity context, final SessionCallback callback) { AccountManager am = AccountManager.get(context); Account[] accounts = am.getAccountsByType(ACCOUNT_TYPE); if (accounts != null && accounts.length > 0) { Account first = accounts[0]; am.getAuthToken(first, AUTH_TOKEN_TYPE_FULL, null, context, new AccountManagerCallback<Bundle>() { @Override public void run(AccountManagerFuture<Bundle> future) { boolean success = false; try { Object t = future.getResult().get(AccountManager.KEY_AUTHTOKEN); if (t instanceof String) { String token = (String) t; if (!TextUtils.isEmpty(token)) { setToken(token); success = true; } } } catch (Exception e) { Log.e("Itch", "Session failure", e); } finally { setLoggedIn(success); if (callback != null) { if (success) { callback.onSuccess(); } else { callback.onFailed(); } } } } }, null); } } public static abstract class SessionCallback { public void onSuccess() { } public void onFailed() { } } }