We've been through various Android Quick Tips. This week we'll focus on Intents.
Android Quick Tips #1 Series Overview
Internal use of startActivityForResult()
Every Android developer is aware of the startActivityForResult(Intent i)
to call external apps to do something specific and get the result back, like calling the camera app to take a photo. However, startActivityForResult(Intent i)
isn't used as much internally. The best example is if your app has a LoginActivity. That LoginActivity often is not part of a forward flow, it's rather a one-time thing, which fulfills a specific action with a result.
So, instead of building a funky combination of startActivity() and finish() in the LoginActivity, this is going to be a better, cleaner solution. The calling activity calls the login activity and signals that it would like to have a result with:
public final static int LOGIN_REQUEST_CODE = 1;
public void loginButtonClick(View view) {
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
startActivityForResult(intent, LOGIN_REQUEST_CODE);
}
This will open the LoginActivity. The LoginActivity then handles the login and should send a result back, for example a User object in case the login was successful, or an error message in case it wasn't successful.
bool loginSuccessful = true; // or false, depending on the login
String errorMessage = .. // set when there was an error
if (loginSuccessful) {
setResult(RESULT_OK); // you can call setResult() without additional data
}
else {
// you can call setResult() with additional data by passing an intent
Intent resultIntent = new Intent();
resultIntent.putExtra("error", errorMessage);
setResult(RESULT_CANCELED, resultIntent);
}
finish();
In either case, this will send data back to the calling MainActivity. The MainActivity has to receive the result and take the appropriate action:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == LOGIN_REQUEST_CODE) {
if (resultCode == RESULT_OK){
// todo login was successful, take appropriate action
}
else if (resultCode == RESULT_CANCELED) {
// login failed, get error message
String errorMessage = data.getStringExtra("error");
// todo take appropriate action matching the error message
}
}
}
This should give you a good example of how clean and easy it is to implement an Activity, which returns a result. Take a look at these two links if you want to know more:
Difference between Intent.ACTION_CALL and Intent.ACTION_DIAL
We've seen it multiple times that Android developers are not aware of the subtle difference between Intent.ACTION_CALL
and Intent.ACTION_DIAL
.
Intent.ACTION_CALL
opens the phone app, dials and calls to a number. The user has no option of reviewing the phone call before its actually made. That's why the Intent.ACTION_CALL
requires an extra permission:
<uses-permission android:name="android.permission.CALL_PHONE" />
In almost all use cases, it's sufficient and user friendlier to just pull up the phone app and dial the number, but not hit the virtual green "call" button. The user has to decide himself if he really wants to call the number, or if he just hit the wrong button. This requires no permission.
We hope you learned a little bit about Intents today. Let us know your Intent tips in the comments!