Support HTTP URLs in Your App

App Indexing for Android uses HTTP URLs to direct users to content in your app.

Understand your site links

Structure your website and app so they share a common set of links that both platforms can open and use. For example, consider the http://www.recipe-app.com website from the codelab on getting your Android app into Search autocomplete. It’s a simple recipe site with content that's ideal for indexing.

The recipe-app.com sample only has one page type (for recipes), but you could have multiple page types on your site, each with a distinct link type. For example, if recipe-app.com included cooking classes, you might include the following link types:

  • Recipe Pages—http://www.recipe-app.com/recipe/*
  • Registration Page—http://www.recipe-app.com/registration/
  • Schedule Page—http://www.recipe-app.com/schedule/

Add a matching view for each link type to your app. Then configure your app to recognize and handle each link type. Understand the number and types of links you'll need to support before you start building streamlines your work. The following instructions refer back this URL structure for the examples.

Connect your site with your app

You should connect your site with your app using Digital Asset Links.

Digital Asset Links take the form of a JSON file called assetlinks.json. You upload it to your web server's .well-known directory. The file defines asset links behavior; in the case of App Indexing this means you must configure the following fields:

  • Relation: Specifies the type of relationship or delegation. For App Indexing specify that all urls delegate to the related asset link using delegate_permission/common.handle_all_urls.
  • Target: Using the namespace value of android_app determines the android app that receives the URLs. Configure it using its package name and the SHA-256 fingerprint of the certificate you used to sign your app before deploying it to the Play Store. See Signing Your Applications to learn more about deployment and your signing certificate.

Here’s an example assetlinks.json for an app package named com.recipe_app. You’ll need to change the package name and sha256_cert_fingerprints content to match those for your app.

  [{
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target" : { "namespace": "android_app",
      "package_name": "com.recipe_app",
                 "sha256_cert_fingerprints": ["hash_of_app_certificate"] }
  }]

Upload this content and make sure it's visible to everyone at https://<yoursite>/.well-known/assetlinks.json.

Receive incoming links in your app

In the previous section you saw how the URL structure of your site is an essential component for how to best build your app. You saw the type of recipe URLs on recipe-app.com that the app must also support. If your site includes any other URL types, make sure your app supports them.

In the following sections you’ll see how to configure your Android app to recognize and respond to these links.

Add intent filters

The first step is to add intent filters to your android manifest file. In the AndroidManifest.xml, intent filters declare the HTTP URL patterns that your app handles from inbound links; the same URLs used for corresponding pages on your website. Refer to the Adding an Intent Filter section of Android Studio Help. Here’s an example of an Android manifest file for an app with an activity for Recipe URLs:

   <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.recipe_app" >

    ...

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/CustomActionBarTheme" >

        <activity
            android:name=".client.HomeActivity"
            android:label="@string/app_name"
            android:exported="true"
            android:theme="@android:style/Theme.Holo.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:name=".client.RecipeActivity"
            android:label="@string/app_name"
            android:theme="@android:style/Theme.Holo.NoActionBar" />

    ...

    </application>
</manifest>
  1. Select the <activity> tag in Android Studio to reveal the lightbulb icon to the left of the tag.
  2. Choose the lightbulb, then select Add URL from the drop-down list.

Now the activity expands to show the updated URL details:

 <activity
    android:name=".client.RecipeActivity"
    android:label="@string/app_name"
    android:exported="true"
    android:launchMode="singleTop"
    android:theme="@android:style/Theme.Holo.NoActionBar">
    <intent-filter android:label="@string/app_name" android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <!-- Accepts URIs that begin with "http://recipe-app.com/recipe" -->
        <data android:scheme="http"
            android:host="recipe-app.com"
            android:pathPrefix="/recipe" />
    </intent-filter>
</activity>

 

You’ll likely have to update the host field, as it defaults to the app package name. Note that the DEFAULT and BROWSABLE categories are required. You may also want to edit the pathPrefix and the scheme. Here’s an example where the manifest has been updated for the recipe-app.com site. It handles the pathPrefix property, and both HTTP and HTTPS schemes by adding a second <data> tag.

  <activity
    android:name=".client.RecipeActivity"
    android:label="@string/app_name"
    android:exported="true"
    android:launchMode="singleTop"
    android:theme="@android:style/Theme.Holo.NoActionBar">
    <intent-filter android:label="@string/app_name" android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <!-- Accepts URIs that begin with "http://recipe-app.com/recipe" -->
        <data android:scheme="http"
            android:host="recipe-app.com"
            android:pathPrefix="/recipe" />
        <!-- Accepts URIs that begin with "https://recipe-app.com/recipe" -->
        <data android:scheme="https"
            android:host="recipe-app.com"
            android:pathPrefix="/recipe" />
    </intent-filter>
</activity>

Now, when a user finds the /recipe link on your site and chooses to view the search result, your app launches and presents the recipe activity. It's important that the intent filter is consistent with your app's logic. If the intent filter claims to support a URL, your app must also include logic to correctly handle the URL, otherwise App Indexing will fail. In the next section you'll see how to parse the link in this activity to determine how your app should render it and ensure App Indexing is successful.

Handle incoming URLs

Now that you've set the Intent Filter in your Android Manifest, your app launches a specific activity based on the URL passed to it. For example, the RecipeActivity activity launches in response to a URL matching http://recipe-app.com/recipe/*, like http://recipe-app.com/recipe/wedge-salad.

In this Activity you can then call getIntent() for the details from this intent. So your onCreate code could look like this:

  @Override
  protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_recipe);
     onNewIntent(getIntent());
  }

onCreate() passes the results of getIntent() (an Intent) to onNewIntent, for processing. The URL is available as a result of getDataString(), so it’s relatively simple to parse it. For example, suppose you want your app to display a specific recipe. To parse out the last element of the URL (the recipe ID), build a URI to retrieve the recipe from the database, and display your activity, use code like this:

  protected void onNewIntent(Intent intent) {
    String action = intent.getAction();
    String data = intent.getDataString();
    if (Intent.ACTION_VIEW.equals(action) && data != null) {
        String recipeId = data.substring(data.lastIndexOf("/") + 1);
        Uri contentUri = Uri.parse("content://com.recipe_app/recipe/").buildUpon()
                .appendPath(recipeId).build();
        showRecipe(contentUri);
    }
}
  

When you finish building your app, and deploy it to the play store , your app launches in response to recognized URLs from search results.

Control indexing (optional)

You can control which app elements appear in Google Search. Specifically, you can adjust the following:

  • Exclude specific pages from Search results— For first-time App Indexing use, you can configure your manifest to include only those pages you want indexed by Google. Otherwise, create a noindex.xml file to specify the URLs you want excluded from Google Search. This is similar to how the robots noindex meta tag works for websites.
  • Exclude real-time app notifications from Search results—Use a noindex.xml file with a specific exclude tag for app notifications.

Create the noindex.xml file

Create a new XML file in your app's XML resources directory: res/xml/noindex.xml. Use statements with specific attributes to indicate the parts of your app to exclude from Google Search. These attributes are as follows:

  • uri—Excludes a specific URI from Google Search. Google doesn't index URLs that exactly match this attribute.
  • uriPrefix—Excludes all content below a URI path from Google Search. Google doesn't index those URLs starting with a string matching this attribute.
  • android:value="notification"—Excludes your app's notifications from Google Search. Google doesn't index the notifications of the app if you specify this attribute.

The following example shows a noindex.xml file that excludes a specific page, hidden directories, and limits app notifications from appearing in Google Search:

  <?xml version="1.0" encoding="utf-8"?>
  <search-engine xmlns:android="http://schemas.android.com/apk/res/android">
    <noindex android:value="notification"/>
    <noindex uri="http://recipe-app.com/profile/hidden-page"/>
    <noindex uriPrefix="http://recipe-app.com/users/hidden_prefix"/>
  </search-engine>

Reference the noindex.xml file

After you add the noindex.xml file, reference it from the application section of the app’s AndroidManifest.xml file with the following line:

  <meta-data android:name="search-engine"
    android:resource="@xml/noindex"/>

For example:

  <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.recipe_app">
    <application>
      <activity android:name=".client.HomeActivity" ...>
        ...
      </activity>
      <meta-data android:name="search-engine" android:resource="@xml/noindex"/>
    </application>
    ...
  </manifest>

Next: Add the App Indexing API

Send feedback about...

Need help? Visit our support page.