Lesson Tuesday

Think about apps you use frequently. Chances are, these apps include options to interact with other apps: Hitting "Share" allows you to open text messages, email, Facebook, or Instagram; "Find Friends" may access your contacts, etc. Coding your app to interact with other applications is a common feature in mobile development!

In this lesson, we'll learn how to instruct our applications to interact with outside applications using something called implicit intents. We'll also integrate this functionality into our ongoing MyRestaurants project.

Explicit vs. Implicit intents

As we learned in previous lessons, an intent is an Android component that represents the intention to complete an action.

There are two types of intents: Explicit intents, and implicit intents. An explicit intent is directly passed to the activity to which it will travel, and generally stays within the app. The intents we have created thus far are all explicit intents.

For instance, when we say Intent intent = new Intent(MainActivity.this, RestaurantsActivity.class); we know the intent is explicit because we're explicitly providing it both the current activity (MainActivity.this) and the activity to which it will travel (RestaurantsActivity.class).

An implicit intent passes the responsibility of completing the intended action to a different application. It relies on Android to automatically fire up whatever tool is responsible for handling the type of action we specify. For instance, we can use an implicit intent to open the user's default internet browser when a user selects a link to a restaurant's website in our MyRestaurants application.

Required Reading

Read through the Training for Android sections on Sending the User to Another App and Getting a Result from an Activity.

MyRestaurants

Next, let's apply what we've just learned to our MyRestaurants app. We will add click listeners for the website, phone, and address TextViews in the restaurant detail fragment. When clicked, these click listeners will create implicit intents to open outside apps.

RestaurantDetailFragment.java
public class RestaurantDetailFragment extends Fragment implements View.OnClickListener {
    ...
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_restaurant_detail, container, false);
        ButterKnife.bind(this, view);

        ...
        mWebsiteLabel.setOnClickListener(this);
        mPhoneLabel.setOnClickListener(this);
        mAddressLabel.setOnClickListener(this);

        return view;
    }

    @Override
    public void onClick(View v) {
        if (v == mWebsiteLabel) {
            Intent webIntent = new Intent(Intent.ACTION_VIEW, 
                    Uri.parse(mRestaurant.getWebsite()));
            startActivity(webIntent);
        }
        if (v == mPhoneLabel) {
            Intent phoneIntent = new Intent(Intent.ACTION_DIAL, 
                    Uri.parse("tel:" + mRestaurant.getPhone()));
            startActivity(phoneIntent);
        }
        if (v == mAddressLabel) {
            Intent mapIntent = new Intent(Intent.ACTION_VIEW, 
                    Uri.parse("geo:" + mRestaurant.getLatitude() 
                            + "," + mRestaurant.getLongitude() 
                            + "?q=(" + mRestaurant.getName() + ")"));
            startActivity(mapIntent);
        }
    }
}

Here, we've instructed RestaurantDetailFragment to implement the View.OnClickListener interface. Then, we create three click listeners for mWebsiteLabel, mPhoneLabel and mAddressLabel in our onCreateView() method. We also create an onClick() method that will execute one of the following three intents, depending upon what is clicked:

  • if mWebsiteLabel is clicked, we create a new implicit intent called webIntent and provide it two arguments: The ACTION_VIEW activity, responsible for displaying data to the user, and the restaurant's website URL. We start this new activity by calling startActivity().

  • If mPhoneLabel is clicked, we create an implicit intent called phoneIntent, and provide it two arguments: The ACTION_DIAL activity, which dials the number in the user's phone app, and the restaurant's telephone number. Again, we start this activity by calling startActivity().

  • If mAddressLabel is selected, we create an implicit intent called mapIntent, and provide it two arguments: The ACTION_VIEW activity, and the restaurant's longitude and latitude, and begin the activity with startActivity().

A few things to take note of:

  • As we see above, the ACTION_VIEW activity is rather flexible. We use it in both the webIntent and mapIntent implicit intents. This is because it's programmed to perform different actions depending on the type of data passed to it. For instance, if passed a mailto: link to an email address, it will open the user's email app. If passed a web URL, it will open the browser. If passed geographical coordinates, it knows to open the map. For more information, see the Android Developers article on ACTION_VIEW.

  • ?q=(" + mRestaurant.getName() + ")" creates a marker on the map with a label of the restaurant’s name.

If we launch the application in our emulator, we can see that clicking a restaurant's phone number, address, or website will now launch another application!


Example GitHub Repo for MyRestaurants

Terminology


  • Intent: An Android component that represents the intention to complete an action. For instance, MyRestaurants contains an intent that takes us from the MainActivity to the RestaurantsActivity when the "Find Restaurants" button is clicked.

  • Explicit intent: Directly passed the activity to which it will travel, and generally stays within the app. For instance, when we say Intent intent = new Intent(MainActivity.this, RestaurantsActivity.class); we know the intent is explicit because we're explicitly providing it both the current activity (MainActivity.this) and the activity to which it will travel (RestaurantsActivity.class).

Examples


The following is an example of creating an implicit intent to dial a specified number:

 Intent phoneIntent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + mRestaurant.getPhone()));

Example GitHub Repo for MyRestaurants

Additional Resources