Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Trait's restricted class example
fun ActionBarActivity.getAccount() : Account? {
val prefs = getPreferences(Context.MODE_PRIVATE)
val name = prefs.getString("name", null)
val type = prefs.getString("type", null)
if (name != null && type != null) {
return Account(name,type)
} else {
return null
}
}
fun ActionBarActivity.storeAccount(account: Account) {
val prefs = getPreferences(Context.MODE_PRIVATE)
prefs.edit().putString("name", account.name).putString("type", account.type).apply()
}
fun ActionBarActivity.clearAccount() {
val prefs = getPreferences(Context.MODE_PRIVATE)
prefs.edit().remove("name").remove("type").apply()
}
fun ActionBarActivity.isAccountAvailable(): Boolean {
val account = getAccount()
return account != null
}
trait GmailAuthenticator : ActionBarActivity {
companion object {
val TAG = javaClass<GmailAuthenticator>().getName()
val PLAY_SERVICES_RESOLUTION_REQUEST = 9000
val REQUEST_CODE_PICK_ACCOUNT = 1000
val REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR = 1001
val AUDIENCE = "audience:...."
}
var account: Account?
var pickingAccount: Boolean
protected fun pickUserAccount() {
Log.i(TAG, "Pick user account")
if (checkGoogleServices()) {
pickingAccount = true
val accountTypes = array("com.google")
val intent = AccountPicker.newChooseAccountIntent(null, null,
accountTypes, false, null, null, null, null);
startActivityForResult(intent, REQUEST_CODE_PICK_ACCOUNT);
}
}
private fun checkGoogleServices(): Boolean {
Log.d(TAG, "checkGoogleServices()")
val resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this)
if (resultCode != ConnectionResult.SUCCESS) {
Log.i(TAG, "Google Services not available! Result code $resultCode")
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
Log.e(TAG, "Google Services are not recoverable!")
}
return false
}
return true
}
/**
* Use this method in [ActionBarActivity.onResume]
*/
protected fun onLoginResume() {
Log.d(TAG, "onLoginCreate()")
if (!isAccountAvailable() && !pickingAccount) {
pickUserAccount()
}
pickingAccount = false
}
/**
* Use this method in [ActionBarActivity.onActivityResult]
*/
protected fun onLoginActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
Log.i(TAG, "onLoginActivityResult $requestCode | $resultCode")
if (requestCode == REQUEST_CODE_PICK_ACCOUNT) {
// Receiving a result from the AccountPicker
if (resultCode == Activity.RESULT_OK) {
val email = data!!.getStringExtra(AccountManager.KEY_ACCOUNT_NAME)
val type = data.getStringExtra(AccountManager.KEY_ACCOUNT_TYPE)
account = Account(email, type)
storeAccount(account!!)
Log.i(TAG, "Picked email $email and type $type")
// With the account name acquired, go get the auth token
fetchToken()
} else if (resultCode == Activity.RESULT_CANCELED) {
// The account picker dialog closed without selecting an account.
// Notify users that they must pick an account to proceed.
// showShortToast("Canceled")
}
} else if (requestCode == REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR && resultCode == Activity.RESULT_OK) {
fetchToken()
}
}
protected fun onLoginCreateOptionsMenu(menu: Menu) {
val item = menu.findItem(R.id.action_logout)
val loggedIn = isAccountAvailable()
item.setVisible(loggedIn)
val itemLogin = menu.findItem(R.id.action_login)
itemLogin.setVisible(!loggedIn)
}
protected fun logout() {
clearAccount()
invalidateOptionsMenu()
}
private fun fetchToken() {
Log.i(TAG, "Fetch token")
runIOFunction { GoogleAuthUtil.getToken(this, account, AUDIENCE) }.subscribe({ handleToken(it) }, { handleException(it) })
}
private fun handleToken(token: String) {
Log.i(TAG, "Received token $token")
invalidateOptionsMenu()
}
private fun handleException(ex: Throwable) {
Log.e(TAG, "Handle fetch token exception", ex)
if (ex is GooglePlayServicesAvailabilityException) {
val dialog = GooglePlayServicesUtil.getErrorDialog(ex.getConnectionStatusCode(),
this,
REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR);
dialog.show();
} else if (ex is UserRecoverableAuthException) {
Log.i(TAG, "Try recover after failed token fetch")
val intent = ex.getIntent();
startActivityForResult(intent, REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR);
} else if (ex is GoogleAuthException) {
Log.e(TAG, "Gmail authentication failed!", ex)
}
}
}
public class MainActivity : ActionBarActivity(), GmailAuthenticator {
companion object {
val TAG = javaClass<MainActivity>().getName()
}
override var account: Account? = null
override var pickingAccount: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super<ActionBarActivity>.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onResume() {
super<ActionBarActivity>.onResume()
Log.i(TAG, "onResume()")
onLoginResume()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super<ActionBarActivity>.onActivityResult(requestCode, resultCode, data)
Log.i(TAG, "onActivityResult")
onLoginActivityResult(requestCode, resultCode, data)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu)
onLoginCreateOptionsMenu(menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
// 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.
val id = item.getItemId()
when (id) {
R.id.action_settings -> return true
R.id.action_logout -> {
logout()
return true
}
R.id.action_login -> {
pickUserAccount()
return true
}
}
return super<ActionBarActivity>.onOptionsItemSelected(item)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.