Hide

Set Up Your Android App for App Indexing

You'll learn how to You'll need
  • Add intent filters to your app manifest.
  • Restrict access to content you want to leave out of the index.
  • An app with minSdkVersion no higher than 17.
  • Add intent filters

    In order for your app content to appear in Google Search results, you must use intent filters to define how to reach specific content inside your app. Do this by creating one intent filter for each deep link format that should launch your app content. For example, if you support both http://example.com and example:// formats, you'll need two intent filters.

    The intent filter should have these elements:

    Tag Description
    <action> Specifies the ACTION_VIEW intent action so that the intent filter can be reached from Google Search.
    <data>

    One for each URI format that the activity accepts. At minimum, the <data> tag must include the android:scheme attribute.

    You can add additional attributes to further refine the type of URI that the activity accepts. For example, you might have multiple activities that accept similar URIs, but which differ simply based on the path name. In this case, use the android:path attribute or its variants (pathPattern or pathPrefix) to differentiate which activity the system should open for different URI paths.

    <category> Defines both BROWSABLE and DEFAULT intent activities:
    • BROWSABLE is required in order for the intent to be executable from a web browser. Without it, clicking a link in a browser cannot resolve to your app and only the current mobile web browser will respond to the URL.
    • DEFAULT required only if you want your Android app to respond to a click from any referring website. The intent used from Google search results includes the identity of your app, so the intent explicitly points to your app as the recipient. Other links to your site do not know your app identity, so the DEFAULT category declares your app can accept an implicit intent.

    Example intent filter for web URIs

    The following example demonstrates a URI pattern intended to match web page URLs so that the user can open your native app instead of the web page when tapping a link. Here, users enter the app using an intent to view information about gizmos.

     <activity android:name="com.example.android.GizmosActivity"
               android:label="@string/title_gizmos" >
         <intent-filter android:label="@string/filter_title_viewgizmos">
             <action android:name="android.intent.action.VIEW" />
             <!-- Accepts URIs that begin with "http://example.com/gizmos" -->
             <data android:scheme="http"
                   android:host="example.com"
                   android:pathPrefix="/gizmos" />
             <category android:name="android.intent.category.DEFAULT" />
             <category android:name="android.intent.category.BROWSABLE" />
         </intent-filter>
     </activity>

    The intent filter declares that the activity responds to VIEW action intents containing URIs that begin with http://example.com/gizmos. In this example, your app would respond to deep links such as http://example.com/gizmos?1234, http://example.com/gizmos/1234, and http://example.com/gizmos/toys/1234.

    Example intent filters for both web and simplified URIs

    If you want a simplified format for the Android URIs, you can create alternative data URI formats using a custom scheme, such as example://gizmos. For example, here's the same intent filter from above that includes support for both the http://example.com/gizmos and example://gizmos formats:

    <activity
         android:name="com.example.android.GizmosActivity"
         android:label="@string/title_gizmos" >
         <intent-filter android:label="@string/filter_title_viewgizmos">
             <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 "example://gizmos" -->
             <data android:scheme="example"
                   android:host="gizmos" />
         </intent-filter>
         <intent-filter android:label="@string/filter_title_viewgizmos">
             <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://example.com/gizmos" -->
             <data android:scheme="http"
                   android:host="example.com"
                   android:pathPrefix="/gizmos" />
         </intent-filter>
    </activity>

    This allows your app to respond to the same http://example.com/gizmos URLs as in the first example, as well as to deep links such as example://gizmos?1234, example://gizmos/1234, and example://gizmos/toys/1234.

    Add code to handle the intent filter

    Once intent filters are added to your AndroidManifest.xml, your app will need to read the data that is passed to your activity. Call the getData() and getAction() methods to retrieve the data and action associated with the incoming Intent. You can call these methods at any time during the lifecycle of the activity, but you should generally do so during early callbacks such as onCreate() or onStart().

    The following example passes the incoming Intent to a helper method onNewIntent() in onCreate().

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

    The example next defines the onNewIntent() method to verify the deep link and display the gizmos content:

    protected void onNewIntent(Intent intent) {
        String action = intent.getAction();
        String data = intent.getDataString();
        if (Intent.ACTION_VIEW.equals(action) && data != null) {
            String gizmosId = data.substring(data.lastIndexOf("/") + 1);
            Uri contentUri = GizmosContentProvider.CONTENT_URI.buildUpon()
                    .appendPath(gizmosId).build();
            showGizmos(contentUri);
        }
    }
    

    Restricting access

    In some cases, you might not want Google to index parts of your app. To do this, first include a noindex.xml file in your Android app to indicate which deep links should not be indexed. Then, reference the noindex.xml in the application section of the app’s AndroidManifest.xml file.

    Create the noindex.xml file

    This file indicates a list of URIs to exclude, or a list of URI prefixes. This is similar to how the robots noindex meta tag works for websites.

    Create a new XML file, res/xml/noindex.xml, and put it in your app's XML resources directory. It should look like the following:

    <?xml version="1.0" encoding="utf-8"?>
    <search-engine xmlns:android="http://schemas.android.com/apk/res/android">
      <noindex uri="http://example.com/gizmos/hidden_uri"/>
      <noindex uriPrefix="http://example.com/gizmos/hidden_prefix"/>
      <noindex uri="gizmos://hidden_path"/>
      <noindex uriPrefix="gizmos://hidden_prefix"/>
    </search-engine>

    Deep links that match the uri attribute exactly, or deep links that start with the string matching uriPrefix attribute will not be indexed.

    Reference the noindex.xmlfile

    After the noindex.xml file is added, reference it in the application section of the app’s AndroidManifest.xml file. For example:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.android.Gizmos">
      <application>
        <activity android:name="com.example.android.GizmosActivity"
            android:label="@string/title_gizmos" >
          <intent-filter android:label="@string/filter_title_viewgizmos">
          <action android:name="android.intent.action.VIEW"/>
          ...
        </activity>
        <meta-data android:name="search-engine" android:resource="@xml/noindex"/>
      </application>
      <uses-permission android:name="android.permission.INTERNET"/>
    </manifest>

    <meta-data android:name="search-engine" android:resource="@xml/noindex"/> specifies where the noindex.xml file can be found in the app. In order to make sure that your app is indexed consistently, the same noindex.xml file should be included in all versions of your app published in the Google Play Store.

    Next, configure your website to provide Google with the deep links you have set up in your app.

    Send feedback about...

    App Indexing