• 如果目标App没有启动,那么就拉起App,并跳转到App内指定页面
  • 如果目标App已经启动,那么就把App拉到前台并跳转App内指定页面

命令行adb测试deeplink
  直接使用命令行adb测试deeplink,使用命令:

1
adb shell am start -a android.intent.action.VIEW -d "rsdkdemo://rs.com/test?referer=Deeplink_Test"

方式一

将MainActivity设置为scheme接受方,并且设置launchMode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<activity
android:name="com.example.imageloader.MainActivity"
android:exported="true"
android:launchMode="singleTask">
<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:host="rs.com"
android:pathPrefix="/test"
android:scheme="rsdkdemo" />
</intent-filter>
</activity>

SplashActivity跳转MainActivity在Intent中增加一个参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class SplashActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)
Handler(Looper.getMainLooper()).postDelayed({
val mainIntent = Intent(this, MainActivity::class.java)
//读取到传递过来的intent数据再次将其传递到MainActivity
if (getIntent() != null && getIntent().data != null) {
mainIntent.data = getIntent().data
}
mainIntent.putExtra(IS_SPLASH_LANCHER, true)
startActivity(mainIntent)
finish()
}, 2000)
}

companion object {
val IS_SPLASH_LANCHER = "is_splash_lancher"
}
}

在Mainactivity中进行判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class MainActivity : AppCompatActivity() {
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
schemeIntent(intent)
}

/**
* 处理intent的值
*/
private fun schemeIntent(intent: Intent?) {
if (intent == null || intent.data == null) {
return
}
//通过getIntent()获取到MainActivity是否是从SplashActivity过来的
if (!getIntent().getBooleanExtra(SplashActivity.IS_SPLASH_LANCHER, false)) {
//不是SplashActivity过来的将要打开SplashActivity,并且将intent数据传递传递过去
val splashIntent = Intent(this, SplashActivity::class.java)
splashIntent.data = intent.data
startActivity(splashIntent)
finish()
} else {
val referer = intent.data?.getQueryParameter("referer") ?: "未找到值"
if (referer == "Deeplink_Test") {
startActivity(Intent(this, VideoActivity::class.java))
}
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
schemeIntent(intent)
}

}

方式二

在BaseApplication创建一个值来标识是否是通过SplashActivity进行初始化的

1
2
3
4
5
6
class BaseApplication : Application() {
companion object {
//app是否是通过SplashActivity进行初始化
var is_app_init = false
}
}

SplashActivity中将BaseApplication中的标识赋值,并且将intent数据进行传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class SplashActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)
Handler(Looper.getMainLooper()).postDelayed({
val mainIntent = Intent(this, MainActivity::class.java)
//读取到传递过来的intent数据再次将其传递到MainActivity
if (getIntent() != null && getIntent().data != null) {
mainIntent.data = getIntent().data
}
startActivity(mainIntent)
//修改BaseApplication中的标识
BaseApplication.is_app_init = true
finish()
}, 2000)
}
companion object {
val IS_SPLASH_LANCHER = "is_splash_lancher"
}
}

专门创建一个Activity来接受scheme

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<activity
android:name=".SchemeActivity"
android:exported="true"
android:launchMode="singleTask">
<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:host="rs.com"
android:pathPrefix="/test"
android:scheme="rsdkdemo" />
</intent-filter>
</activity>

在SchemeActivity写逻辑进行判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class SchemeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// setContentView(R.layout.activity_scheme)
schemeIntent(intent)
}

override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
schemeIntent(intent)
}

private fun schemeIntent(intent: Intent?) {
if (intent == null || intent.data == null) {
return
}
//app是否是通过SplashActivity进行初始化
if (BaseApplication.is_app_init) {
val referer = intent?.data?.getQueryParameter("referer") ?: "未找到值"
if (referer.equals("Deeplink_Test")) {
startActivity(Intent(this, VideoActivity::class.java))
}
} else {
//打开SplashActivity并将数据进行传递
val splashIntent = Intent(this, SplashActivity::class.java)
splashIntent.data = intent.data
startActivity(splashIntent)
}
finish()
}
}

在MainActivity处理SplashActivity页面传递过来的数据内容

1
2
3
4
5
6
7
8
9
10
11
12
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//获取到传递过来的值然后进行跳转
val referer = intent?.data?.getQueryParameter("referer") ?: "未找到值"
if (referer.equals("Deeplink_Test")) {
startActivity(Intent(this, VideoActivity::class.java))
}
}

}

总结

方式一:可以解决冷启动和App在后台在恢复到前台的情况,但是会有一个问题,app已经处于运行中的话会将当前的Activity挤掉,强制进入MainActivity中.
方式二:可以解决冷启动和App在后台在恢复到前台的情况,app已经处于运行中的话并不会关闭之前打开的Activity任务栈.

参考资料

Android Deeplink原理与应用
Android Deeplink(二)
Android中的DeepLink
Android外部调用自身App(scheme DeepLink、AppLink详解)