Last active
August 29, 2015 14:18
-
-
Save damianpetla/f35278857667b3b20f23 to your computer and use it in GitHub Desktop.
Trait's restricted class example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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