Skip to content

Latest commit

 

History

History
617 lines (491 loc) · 19.4 KB

File metadata and controls

617 lines (491 loc) · 19.4 KB

Android Authenticator

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">Android-Auth-Sync</string>
    <string name="desc">Desc</string>
    <string name="login_path">http://api.randomuser.me/?results=1</string>
    <string name="sync_path">http://api.randomuser.me/?results=3</string>
    <string name="account_type">me.hoen.android_auth_sync.auth</string>
    <string name="auth_token_type">@string/account_type</string>
    <string name="sync_provider">me.hoen.android_auth_sync.provider</string>
    <string name="profile">Profile</string>
    <string name="sync">Synchronize</string>
    <string name="logout">Logout</string>
</resources>
public class ServerAuthenticate {
    protected Context context;

    public ServerAuthenticate(Context context) {
        super();
        this.context = context;
    }

    public User userSignIn(String username, String password) throws Exception {

        try {
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpPost httpPost = new HttpPost(
                    context.getString(R.string.login_path));

            HttpParams postParams = new BasicHttpParams();
            postParams.setParameter("username", username);
            postParams.setParameter("password", password);
            httpPost.setParams(postParams);

            HttpResponse response = httpClient.execute(httpPost);

            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity);

            JSONObject json = new JSONObject(result);

            User u = User.fromJson(json);
        
            UserManager.getInstance().addUser(u);
            
            String authToken = u.getToken();

            Log.d(MainActivity.TAG, "Authentication auth token : " + authToken);
            return u;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
}
public class AccountGeneral {
    public static final String ACCOUNT_NAME = "AuthSync";
    public static final String AUTHTOKEN_TYPE_FULL_ACCESS = "Full access";
    public static final String AUTHTOKEN_TYPE_FULL_ACCESS_LABEL = "Full access to an AuthSync account";

    protected Context context;
    protected ServerAuthenticate serverAuthenticate;

    public AccountGeneral(Context context) {
        super();
        this.context = context;
    }

    public ServerAuthenticate getServerAuthenticate() {
        if (this.serverAuthenticate == null) {
            serverAuthenticate = new ServerAuthenticate(context);
        }

        return serverAuthenticate;
    }
}
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_NEW_ACCOUNT = "IS_ADDING_ACCOUNT";
    public static final String KEY_ERROR_MESSAGE = "ERR_MSG";
    public final static String PARAM_USER_PASS = "USER_PASS";
    private final int REQ_SIGNUP = 1;
    private AccountManager mAccountManager;
    private String mAuthTokenType;

    protected ProgressDialog progress;

    protected AuthOnTaskCompleted loginCallback = new AuthOnTaskCompleted() {

        @Override
        public void onTaskCompleted(Intent intent) {
            finishLogin(intent);

            if (progress.isShowing()) {
                progress.hide();
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        progress = new ProgressDialog(this);

        mAccountManager = AccountManager.get(getBaseContext());

        mAuthTokenType = getIntent().getStringExtra(ARG_AUTH_TYPE);
        if (mAuthTokenType == null)
            mAuthTokenType = AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS;

        Button mEmailSignInButton = (Button) findViewById(R.id.email_sign_in_button);
        mEmailSignInButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                submit();
            }
        });

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQ_SIGNUP && resultCode == RESULT_OK) {
            finishLogin(data);
        } else
            super.onActivityResult(requestCode, resultCode, data);
    }

    public void submit() {
        final String username = ((TextView) findViewById(R.id.email)).getText()
                .toString();
        final String userpass = ((TextView) findViewById(R.id.password))
                .getText().toString();
        final String accountType = getIntent().getStringExtra(ARG_ACCOUNT_TYPE);

        progress.show();
        new AuthenticationTask(getApplicationContext(), loginCallback).execute(
                username, userpass, accountType);
    }

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

        // set auto-sync
        ContentResolver.setIsSyncable(account,
                getString(R.string.sync_provider), 1);
        ContentResolver.setSyncAutomatically(account,
                getString(R.string.sync_provider), true);

        // request sync to start asap
        Utils.requestSync(account, getApplicationContext());

        if (getIntent().getBooleanExtra(ARG_IS_ADDING_NEW_ACCOUNT, false)) {
            String authtoken = intent
                    .getStringExtra(AccountManager.KEY_AUTHTOKEN);
            String authtokenType = mAuthTokenType;

            mAccountManager
                    .addAccountExplicitly(account, accountPassword, null);

            User u = UserManager.getInstance().getUser(accountName);
            if (u != null) {
                User.saveToAccount(u, account, getApplicationContext());
            }
            mAccountManager.setAuthToken(account, authtokenType, authtoken);
        } else {
            mAccountManager.setPassword(account, accountPassword);
        }
        setAccountAuthenticatorResult(intent.getExtras());
        setResult(RESULT_OK, intent);
        finish();
    }
}
public class User implements Serializable {
    String username;
    String email;
    String password;

    String title;
    String firstName;
    String lastName;
    String thumbnail;

    String token;

    public User() {

    }

    public User(String username, String token) {
        this.username = username;
        this.token = token;
    }

    @Override
    public String toString() {
        return "User [token=" + token + ", username=" + username + "]";
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getThumbnail() {
        return thumbnail;
    }

    public void setThumbnail(String thumbnail) {
        this.thumbnail = thumbnail;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    static public User fromJson(JSONObject json) {
        try {
            JSONArray results = json.getJSONArray("results");
            if (results.length() > 0) {
                JSONObject jsonUser = results.getJSONObject(0).getJSONObject(
                        "user");

                User u = new User();

                u.setUsername(jsonUser.getString("username"));
                u.setEmail(jsonUser.getString("email"));
                u.setPassword(jsonUser.getString("password"));

                u.setTitle(jsonUser.getJSONObject("name").getString("title"));
                u.setFirstName(jsonUser.getJSONObject("name")
                        .getString("first"));
                u.setLastName(jsonUser.getJSONObject("name").getString("last"));
                u.setThumbnail(jsonUser.getJSONObject("picture").getString(
                        "thumbnail"));

                u.setToken(jsonUser.getString("sha256"));

                return u;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    static public User fromAccount(Account account, Context context) {
        User u = new User();

        AccountManager am = AccountManager.get(context);

        u.setUsername(am.getUserData(account, "username"));
        u.setEmail(am.getUserData(account, "email"));
        u.setPassword(am.getUserData(account, "password"));

        u.setTitle(am.getUserData(account, "title"));
        u.setFirstName(am.getUserData(account, "firstName"));
        u.setLastName(am.getUserData(account, "lastName"));
        u.setThumbnail(am.getUserData(account, "thumbnail"));

        u.setToken(am.getUserData(account, "token"));

        return u;
    }

    static public User saveAccount(JSONObject result, Account account, Context context) {
        User u = User.fromJson(result);

        if (u != null) {
            saveToAccount(u, account, context);
        }

        return u;
    }

    static public void saveToAccount(User user, Account account, Context context) {
        AccountManager am = AccountManager.get(context);

        am.setUserData(account, "username", user.getUsername());
        am.setUserData(account, "email", user.getEmail());
        am.setUserData(account, "password", user.getPassword());

        am.setUserData(account, "title", user.getTitle());
        am.setUserData(account, "firstName", user.getFirstName());
        am.setUserData(account, "lastName", user.getLastName());
        am.setUserData(account, "thumbnail", user.getThumbnail());

        am.setUserData(account, "token", user.getToken());
    }
}
public class Authenticator extends AbstractAccountAuthenticator {

    private Context mContext;

    public Authenticator(Context context) {
        super(context);

        this.mContext = context;
    }

    @Override
    public Bundle addAccount(AccountAuthenticatorResponse response,
            String accountType, String authTokenType,
            String[] requiredFeatures, Bundle options)
            throws NetworkErrorException {
        final Intent intent = new Intent(mContext, LoginActivity.class);
        intent.putExtra(LoginActivity.ARG_ACCOUNT_TYPE, accountType);
        intent.putExtra(LoginActivity.ARG_AUTH_TYPE, authTokenType);
        intent.putExtra(LoginActivity.ARG_IS_ADDING_NEW_ACCOUNT, true);
        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
                response);
        final Bundle bundle = new Bundle();
        bundle.putParcelable(AccountManager.KEY_INTENT, intent);
        return bundle;
    }

    @Override
    public Bundle confirmCredentials(AccountAuthenticatorResponse response,
            Account account, Bundle options) throws NetworkErrorException {
        return null;
    }

    @Override
    public Bundle editProperties(AccountAuthenticatorResponse response,
            String accountType) {
        return null;
    }

    @Override
    public Bundle getAuthToken(AccountAuthenticatorResponse response,
            Account account, String authTokenType, Bundle options)
            throws NetworkErrorException {

        if (!authTokenType.equals(AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS)) {
            final Bundle result = new Bundle();
            result.putString(AccountManager.KEY_ERROR_MESSAGE,
                    "invalid authTokenType");
            return result;
        }

        final AccountManager am = AccountManager.get(mContext);

        String authToken = am.peekAuthToken(account, authTokenType);

        if (TextUtils.isEmpty(authToken)) {
            final String password = am.getPassword(account);
            if (password != null) {
                try {
                    User u = new ServerAuthenticate(mContext).userSignIn(
                            account.name, password);

                    if (u != null) {
                        User.saveToAccount(u, account, this.mContext);
                        authToken = u.getToken();
                    }
                } 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;
        }

        final Intent intent = new Intent(mContext, Authenticator.class);
        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
                response);
        intent.putExtra("ACCOUNT_TYPE", account.type);
        intent.putExtra("AUTH_TYPE", authTokenType);
        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
            return authTokenType + " (Label)";
    }

    @Override
    public Bundle hasFeatures(AccountAuthenticatorResponse response,
            Account account, String[] features) throws NetworkErrorException {
        final Bundle result = new Bundle();
        result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
        return result;
    }

    @Override
    public Bundle updateCredentials(AccountAuthenticatorResponse response,
            Account account, String authTokenType, Bundle options)
            throws NetworkErrorException {
        return null;
    }
}
public class AuthenticatorService extends Service {

    private static final Object lock = new Object();
    private Authenticator auth;

    @Override
    public void onCreate() {
        synchronized (lock) {
            if (auth == null) {
                auth = new Authenticator(this);
            }
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return auth.getIBinder();
    }

}
<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
    android:accountType="@string/account_type"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:smallIcon="@drawable/ic_launcher" />
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="me.hoen.android_auth_sync"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />

    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
    <uses-permission android:name="android.permission.USE_CREDENTIALS" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
       
        <activity
            android:name="me.hoen.android_auth_sync.auth.LoginActivity"
            android:clearTaskOnLaunch="true"
            android:label="@string/title_activity_login" >
        </activity>

        <service
            android:name="me.hoen.android_auth_sync.auth.AuthenticatorService"
            android:exported="false" >
            <intent-filter>
                <action android:name="android.accounts.AccountAuthenticator" />
            </intent-filter>

            <meta-data
                android:name="android.accounts.AccountAuthenticator"
                android:resource="@xml/authenticator" />
        </service>

    </application>

</manifest>
public class MainActivity extends ActionBarActivity {
    public static final String TAG = "me.example";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Fragment f = new ContactsFragment();
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction()
                .replace(android.R.id.content, f, "home").commit();
        fragmentManager.executePendingTransactions();

    }

    @Override
    protected void onResume() {
        super.onResume();

        AccountManager am = AccountManager.get(this);

        String accountType = getString(R.string.account_type);
        String authTokenType = getString(R.string.auth_token_type);

        am.getAuthTokenByFeatures(accountType, authTokenType, null, this, null,
                null, new AccountManagerCallback<Bundle>() {
                    @Override
                    public void run(AccountManagerFuture<Bundle> future) {
                        try {
                            Bundle bnd = future.getResult();
                            String keyAuthToken = AccountManager.KEY_AUTHTOKEN;
                            String authToken = bnd.getString(keyAuthToken);

                            Log.d(MainActivity.TAG, "AuthToken : " + authToken);
                        } catch (OperationCanceledException e) {
                            finish();
                            e.printStackTrace();
                        } catch (AuthenticatorException e) {
                            finish();
                            e.printStackTrace();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }, null);
    }

}