This chapter will create an example application in Android Studio designed to demonstrate a practical implementation of implicit intents. The goal will be to create and send an intent requesting that the content of a particular web page be loaded and displayed to the user. Since the example application itself will not contain an activity capable of performing this task, an implicit intent will be issued so that the Android intent resolution algorithm can be engaged to identify and launch a suitable activity from another application. This will likely be an activity from the Chrome web browser bundled with the Android operating system.
Having successfully launched the built-in browser, a new project will be created with an activity capable of displaying web pages. This will be installed onto the device or emulator to demonstrate implicit intents and link verification.
Creating the Android Studio Implicit Intent Example Project
Select the New Project option from the welcome screen and, within the resulting new project dialog, choose the Empty Views Activity template before clicking on the Next button.
Enter ImplicitIntent into the Name field and specify com.ebookfrenzy.implicitintent as the package name. Since this example will use features only available in recent Android versions, change the Minimum API level setting to API 31: Android 12.0 (S) and the Language menu to Kotlin before clicking the Finish button.
Designing the User Interface
The user interface for the MainActivity class is straightforward, consisting solely of a ConstraintLayout and two Button objects. Within the Project tool window, locate the app -> res -> layout -> activity_main.xml file and double-click on it to load it into the Layout Editor tool.
Delete the default TextView and, with Autoconnect mode enabled, position Button widgets within the layout so that it appears as shown below:
Set the text on the buttons to Show Web Page and Enable Links and extract the text to string resources.
Select each Button and use the Attributes tool window to configure the onClick property to call methods named showWebPage and enableLink, respectively.
Creating the Implicit Intent
As outlined above, the implicit intent will be created and issued from within a method named showWebPage(), which, in turn, needs to be implemented in the MainActivity class, the code for which resides in the MainActivity.kt source file. Locate this file in the Project tool window and double-click on it to load it into an editing pane. Once loaded, modify the code to add the showWebPage() and enableLink() methods together with a few requisite imports:
package com.ebookfrenzy.implicitintent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.content.Intent
import android.view.View
import android.net.Uri
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_implicit_intent)
}
fun showWebPage(view: View) {
val intent = Intent(Intent.ACTION_VIEW,
Uri.parse("https://www.ebookfrenzy.com"))
startActivity(intent)
}
fun enableLink(view: View) {
}
}
Code language: Kotlin (kotlin)
The tasks performed by the showWebPage() method are very simple. First, a new intent object is created. Instead of specifying the class name of the intent, however, the code indicates the nature of the intent (to display something to the user) using the ACTION_VIEW option. The intent object also includes a URI containing the URL to be displayed. This indicates to the Android intent resolution system that the activity is requesting that a web page be displayed. The intent is then issued via a call to the startActivity() method.
Compile and run the application on either an emulator or a physical Android device, and once running, touch the Show Web Page button. When touched, a web browser view should appear and load the web page designated by the URL. A successful implicit intent has now been executed.
Adding a Second Matching Activity
The remainder of this chapter will demonstrate the effect of more than one activity installed on the device matching the requirements for an implicit intent. A second application will be created and installed on the device or emulator to achieve this. Begin by creating a new project within Android Studio with the application name set to MyWebView, using the same SDK configuration options used when creating the ImplicitIntent project earlier in this chapter and once again selecting an Empty Views Activity.
If you have a website to host a Digital Asset Links file and want to try out auto verification, use your website URL when specifying the package name. For example, if your website is hosted at www.mycompany.com, the package name needs to be set as follows:
com.mycompany.mywebview
Code language: plaintext (plaintext)
If you do not have a website or do not plan on using auto verification, use the following package name:
com.ebookfrenzy.mywebview
Code language: plaintext (plaintext)
Click Finish to create the project, then convert the project to use view bindings as outlined in section 18.8 Migrating a Project to View Binding.
Adding the Web View to the UI
The user interface for the sole activity contained within the new MyWebView project will consist of an instance of the Android WebView widget. Within the Project tool window, locate the activity_main.xml file, which contains the user interface description for the activity, and double-click on it to load it into the Layout Editor tool.
With the Layout Editor tool in Design mode, select the default TextView widget and remove it from the layout using the keyboard delete key.
Drag and drop a WebView object from the Widgets section of the palette onto the existing ConstraintLayout view, as illustrated in Figure 59-2:
Before continuing, change the ID of the WebView instance to webView1 and use the Infer constraints button to add any missing constraints.
Obtaining the Intent URL
When the implicit intent object is created to display a web browser window, the web page URL will be bundled into the intent object within a Uri object. The task of the onCreate() method within the MainActivity class is to extract this Uri from the intent object, convert it into a URL string and assign it to the WebView object. To implement this functionality, modify the MainActivity.kt file so that it reads as follows:
package com.ebookfrenzy.mywebview
.
.
import java.net.URL
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
.
.
handleIntent()
}
private fun handleIntent() {
val intent = this.intent
val data = intent.data
var url: URL? = null
try {
url = URL(data?.scheme,
data?.host,
data?.path)
} catch (e: Exception) {
e.printStackTrace()
}
binding.webView1.loadUrl(url.toString())
}
.
.
}
Code language: Kotlin (kotlin)
The new code added to the onCreate() method performs the following tasks:
- Obtains a reference to the intent which caused this activity to be launched
- Extracts the Uri data from the intent object
- Converts the Uri data to a URL object
- Loads the URL into the web view, converting the URL to a String in the process
The coding part of the MyWebView project is now complete. All that remains is to modify the manifest file.
Modifying the MyWebView Project Manifest File
A number of changes must be made to the MyWebView manifest file before it can be tested. In the first instance, the activity will need to seek permission to access the internet (since it will be required to load a web page). This is achieved by adding the appropriate permission line to the manifest file:
<uses-permission android:name="android.permission.INTERNET" />
Code language: HTML, XML (xml)
Further, a review of the contents of the intent filter section of the AndroidManifest.xml file for the MyWebView project will reveal the following settings:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
Code language: HTML, XML (xml)
In the above XML, the android.intent.action.MAIN entry indicates that this activity is the application’s entry point when launched without data input – the android.intent.category.LAUNCHER directive, on the other hand, indicates that the activity should be listed within the application launcher screen of the device.
Since the activity is not required to be launched as the entry point to an application, cannot be run without data input (in this case, a URL), and is not required to appear in the launcher, neither the MAIN nor LAUNCHER directives are required in the manifest file for this activity.
The intent filter for the MainActivity activity does, however, need to be modified to indicate that it is capable of handling ACTION_VIEW intent actions for HTTP data schemes.
Android also requires that activities that handle implicit intents that do not include MAIN and LAUNCHER entries include the so-called browsable and default categories in the intent filter. The modified intent filter section should therefore read as follows where <website url> is replaced either by your website address or www. ebookfrenzy.com, depending on the package name you used when the MyWebView project was created:
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="https" />
<data android:host="<website url>"/>
</intent-filter>
Code language: HTML, XML (xml)
Bringing these requirements together results in the following complete AndroidManifest.xml file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ebookfrenzy.mywebview">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyWebView">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="https" />
<data android:host="<website url>"/>
</intent-filter>
</activity>
</application>
</manifest>
Code language: HTML, XML (xml)
Load the AndroidManifest.xml file into the manifest editor by double-clicking on the file name in the Project tool window. Once loaded, modify the XML to match the above changes, remembering to enter the correct website URL.
Having made the appropriate modifications to the manifest file, the new activity is ready to be installed on the device.
Installing the MyWebView Package on a Device
Before the MyWebView main activity can be used as the recipient of an implicit intent, it must first be installed onto the device. This is achieved by running the application in the normal manner. Because the manifest file contains neither the android.intent.action.MAIN nor the android.intent.category.LAUNCHER settings, Android Studio must be instructed to install but not launch the app. To configure this behavior, select the app -> Edit configurations… menu from the toolbar as illustrated in Figure 59-3:
Within the Run/Debug Configurations dialog, change the Launch option located in the Launch Options section of the panel to Nothing and click on Apply followed by OK:
With this setting configured, run the app as usual. With this setting configured, run the app as usual. Note that the app is installed on the device but has yet to launch.
Testing the Application
With the MyWebView app installed, rerun ImplicitIntent and click the Show Web Page button. Note that the web page is still loaded into the Chrome browser instead of the main activity of the MyWebView app. This is because the MyWebView activity has not been verified or enabled to open the link contained in the launch intent. Some code must be added to the enableLink() method to enable the link manually.
Manually Enabling the Link
Within the enableLink() method, we need to create and launch an intent to display the Open by Default settings screen for the MyWebView app. Load the MainActivity.kt file into the code editor and modify the enableLink() method so that it reads as follows, making sure to replace <reverse domain> with either com.ebookfrenzy or your own reverse domain depending on the package name you chose when creating the MyWebView project:
.
.
import android.provider.Settings
.
.
fun enableLink(view: View) {
val intent = Intent(
Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS,
Uri.parse("package:<reverse domain>.mywebview"))
startActivity(intent)
}
.
.
Code language: Kotlin (kotlin)
Rerun the ImpicitIntent app and click on the Enable Link button to display the Open by Default settings screen for the MyWebView app:
Click on the Add Link button (marked A above), enable the checkbox next to your URL, and click the Add button:
Confirm that the link is now listed as being supported before clicking on the back arrow (marked B in Figure 59-5 above) to return to the ImplicitIntent app. Clicking the Open Web Page should now load the page into the MyWebView app instead of the Chrome browser:
Automatic Link Verification
If you chose to use your own website URL for the MyWebView package name, you can now take the additional step of using automatic link verification. Begin by uninstalling the MyWebView app from the device or emulator on which you have been testing. After placing the Digital Asset Links file on the website, we will reinstall the app to trigger the verification process.
Using the steps outlined in the chapter entitled “An Overview of Android Intents”, locate your debug.keystore file and obtain your SHA-256 certificate fingerprint using the keytool utility as follows:
keytool -list -v -keystore <path to debug.keystore file here>
Code language: plaintext (plaintext)
Next, open the following page in a web browser:
https://developers.google.com/digital-asset-links/tools/generator
Once the page has loaded, enter your website URL into the Hosting site domain field, com.<domain here>. mywebview as the App package name, and your SHA-256 fingerprint into the App package fingerprint (SHA256) field:
Click the Generate statement button to display the generated statement and place it in a file named assetlinks.json in a folder named .well-known on your web server. Return to the generator page and click on the Test statement button to verify that the file is valid and in the correct location.
Assuming a successful test, we are ready to try out the app link, reinstall the MyWebView app on your device or emulator and use the Settings app to navigate to the Open by Default page for MyWebView. The page should indicate that a link has been verified:
Run the ImplicitIntent app again, click the Open Web Page button, and verify that the page content appears in the MyWebView app instead of the Chrome browser.
Summary
Implicit intents provide a mechanism by which one activity can request the service of another by specifying an action type and, optionally, the data on which that action is to be performed. To be eligible as a target candidate for an implicit intent, however, an activity must be configured to extract the appropriate data from the inbound intent object and be included in a correctly configured manifest file, including appropriate permissions and intent filters. The app containing the target activity must also be verified using a Digital Asset Links file or manually enabled by the user.
Within this chapter, an example was created to demonstrate both the issuing of an implicit intent, the creation of an example activity capable of handling such an intent, and the link verification process.