Android - Uri, Scheme and SSP(Scheme Specific Part)

This post will cover what the Uri, Scheme and SSP(Scheme Specific PART) are.

Intent has information called data. Data is expressed as Uri(Uniform Resource Identifier), which has Scheme, Host and SSP. You might be familiar with Scheme and Host, but SSP is not.

First, I will briefly explain Intent, and then introduce Uri, Scheme, and SSP.

Intent

Intent is used when sending and receiving events in Android. In Intent, there is an item called Data. Data represents what information the Intent has.

For instance, when executing an activity, the intent is used to decide which activity to execute.

Intent can be created and data variable can be set as follows.

val intent = Intent(Intent.ACTION_VIEW)
intent.addCategory(Intent.CATEGORY_DEFAULT)
intent.addCategory(Intent.CATEGORY_BROWSABLE)

val uri: Uri = Uri.parse("http://google.com")
intent.data = uri

So, we can say that the data of Intent is Uri and it represents what data intent has.

Uri

Uri stands for Uniform Resource Identifier and is an identifier that represents a resource. Url used on the Internet is a sub-concept of Uri.

The syntax of Uri is like this:

<scheme>://<host>:<port>[<path>|<pathPrefix>|<pathPattern>]

I took the above http://google.com as an example. Here, http is the scheme and google.com is the host. There was no port and path.

You can make a string into a Uri object using Uri.parse() as follows.

val uri: Uri = Uri.parse("http://google.com")
Log.d(TAG, "scheme: ${uri.scheme}, host: ${uri.host}, " +
        "port: ${uri.port}, path: ${uri.path}")

Output:

MainActivity: scheme: http, host: google.com, port: -1, path:

Why use Uri

Uri is an identifier representing a resource.

For example, when the user clicks on a link called http://google.com, the app makes this an intent and calls startActivity().

And the system looks for an app that can process the data from the Intent. At this time, it searches for apps related to Uri's scheme and host. (Under the hood, ActivityManager asks PackageManager for the intent and then start an activity)

When you run the following code, the system will find and run an app associated with this Intent. Generally, browsers can handle these intents, so when you run the code, the browser is launched.

val intent = Intent(Intent.ACTION_VIEW)
intent.addCategory(Intent.CATEGORY_DEFAULT)
intent.addCategory(Intent.CATEGORY_BROWSABLE)

val uri: Uri = Uri.parse("http://google.com")
intent.data = uri

startActivity(intent)

One way to express what kind of intent your app can handle is AndroidManifest's IntentFilter. The system reads AndroidManifest.xml to categorize which intents this app can handle, and when sending an intent, it refers to this information to determine who to send.

Looking at the Manifest of the Chrome app, the IntentFilter of the Activity is set as follows. If you look a little closer, you can see that the action and category of the above Intent are the same. Also, the scheme is defined as http in the data item. This data means Uri, and it means that Uri with the scheme http and https can all be processed. In other words, it doesn't matter what host comes in.

<activity android:name="com.google.android.apps.chrome.IntentDispatcher">
    <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <data android:scheme="http"/>
        <data android:scheme="https"/>
    </intent-filter>
</activity>

In this way, the App declares a Uri it can process in the Manifest, so the system can compare the Uri information to determine who to deliver the Intent to.

If some activity can only handle google.com as host, you can set IntentFilter like this: If you look at the data item, the host has been set.

<intent-filter>
    <action android:name="android.intent.action.VIEW"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <category android:name="android.intent.category.BROWSABLE"/>
    <data android:scheme="http" android:host="google.com"/>
    <data android:scheme="https" android:host="google.com"/>
</intent-filter>

SSP(Scheme Specific Part)

Above, we said that the syntax of Uri is like this.

<scheme>://<host>:<port>[<path>|<pathPrefix>|<pathPattern>]

However, we can use this syntax when we define SSP.

<scheme>:<scheme-specific-part>#fragment

Compared to the first syntax, there is no //. The right part of : is called SSP (Scheme Specific Part). And the right side of # is called fragment.

Sometimes Android uses SSP format Uri.

For example, the ACTION_PACKAGE_ADDED intent is delivered when the app is installed.

Intent { act=android.intent.action.PACKAGE_ADDED dat=package:com.codechacha.myapplication flg=0x4000010 (has extras) }

The Uri of this intent is package:com.codechacha.myapplication. The scheme is package and the SSP is com.codechacha.myapplication. There is no fragment.

As another example, the Uri of the Intent sent when making a call is in the form of tel:010-1111-1111. There is a scheme called tel, and detailed information about the scheme is stored in the SSP. Both sms and mms are expressed in SSP the same way.

Define SSP in IntentFilter

When the app is deleted from the device, it broadcasts an intent of PACKAGE_FULLY_REMOVED. This intent uses SSP to represent Uri, and passes the app's package name in the SSP, like package:com.example.myapplication.

If you want to receive PACKAGE_FULLY_REMOVED from the receiver, you need to set the scheme to package as follows. With this setting, you will receive that event when an app is deleted.

<receiver android:name=".MyReceiver">
    <intent-filter>
        <action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
        <data android:scheme="package"/>
    </intent-filter>
</receiver>

But what if you want to receive intents only when the app com.example.myapplication is deleted? You can set the IntentFilter to ssp as com.example.myapplication. With this setting, it is delivered only when it matches the SSP of the intent and the SSP of the intent filter.

<receiver android:name=".MyReceiver">
    <intent-filter>
        <action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
        <data android:scheme="package" android:ssp="com.example.myapplication"/>
    </intent-filter>
</receiver>

If you register a receiver with Context.registerReceiver() instead of Manifest, you can create an IntentFilter object as follows. You can use addDataSchemeSpecificPart() when setting up the SSP.

val intentFilter = IntentFilter()
intentFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED)
intentFilter.addDataScheme("package")
intentFilter.addDataSchemeSpecificPart("com.example.myapplication",
        PatternMatcher.PATTERN_LITERAL)

val receiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        Log.d("MyReceiver", "onReceive: $intent")
    }
}
context.registerReceiver(receiver, intentFilter)

Deliver Uri with SSP

We have seen ways to define IntentFilter which can receive Intents with SSP.

Here, i will show you how to send Intents with SSP from my application.

You can create a Uri object with SSP.

val intent = Intent("com.custom.intent.action")
intent.data = Uri.fromParts("package" /* scheme */,
    "com.example.myapplication" /* ssp */,
    null /* fragment */)

When you start or broadcast an intent with SSP, it can be delivered to apps with an intent filter set up like this:

<intent-filter>
    <action android:name="com.custom.intent.action" />
    <data android:scheme="package" android:ssp="com.example.myapplication"/>
</intent-filter>

Of course, it is also delivered to apps where only the scheme is set.

<intent-filter>
    <action android:name="com.custom.intent.action" />
    <data android:scheme="package"/>
</intent-filter>

Example where Fragment is used

While developing Android, I haven't seen fragments used. Please let me know if anyone has seen it.

clean up

We have looked closely at Intent and SSP. There are 2 syntax. One is for defining data without SSP, the other is for defining with SSP. Each has a slightly different way of creating IntentFilter and Intent objects.

I hope reading this article helps you understand Intent a bit.

Related Posts

codechachaCopyright ©2019 codechacha