深度链接和多个应用程序实例

我已经在我的应用程序中实现了深度链接。我在清单文件中添加了这个意图过滤器,深度链接正在工作。

<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.VIEW" />
<data
android:host="www.mywebsite.com"
android:pathPrefix="/something"
android:scheme="http" />
</intent-filter>

问题是,通过深度链接,我的应用程序是在当前的应用程序之上启动。如果我在 Gmail 中点击一个链接,那么我的应用程序将在 Gmail 之上启动。我想以不同的方式启动我的应用程序。

如果我的应用程序已经在后台运行,我点击 Gmail 中的一个链接重定向到我的应用程序,我的应用程序会有两个实例同时运行: 一个在后台,另一个在 Gmail 上。我希望一次只运行我的应用程序的一个实例,所以它并不在当前应用程序(Gmail)之上。我该怎么做?

34305 次浏览

您需要为清单中的活动执行以下操作。

android:launchMode="singleTask"

这告诉系统,如果已经创建了 Activity 的现有实例,则始终启动该实例。

然后您可以通过覆盖该方法来处理意图

onNewIntent

有关更多信息,请参见 http://developer.android.com/guide/topics/manifest/activity-element.html

接受的答案对我不起作用,以下是起作用的:

intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();

来自官方文件:

如果设置了,并且正在启动的活动已经在当前任务中运行,那么不启动该活动的新实例,而是关闭它上面的所有其他活动,这个意图将作为一个新的意图传递给(现在在顶部)旧的活动。

我们在深度链接方面遇到了一些问题。 比如:

  1. 只点击同一个链接两次,先点击触发正确的视图
  2. 打开多个实例
  3. Whatsapp 或者 facebook 上的链接因为他们的网页浏览器而打开了 whatsapp 本身的视图。
  4. 在 android 6上只打开了一个实例,但是只处理了第一个 意图,第二和第三打开应用程序,但没有行动,因为意图数据没有改变。

因此,以下并不是对这个问题的明确回答,而是对我们所遇到的几个问题的全面解决方案。

我们的解决方案是:

A)创建一个新的片段活动

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2); //well can be anything some "loading screen"


Intent intent = getIntent();
String intentUrl = intent.getDataString();
Intent newIntent = new Intent(this, MainActivity.class);
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
newIntent.putExtra("intentUrl",intentUrl);
newIntent.setAction(Long.toString(System.currentTimeMillis()));


startActivity(newIntent);
finish();
}

B)舱单:

    <activity
android:name="YOUR.NEW.FRAGMENT.ACTIVITY"
android:label="@string/app_name"
android:launchMode="singleTop">
<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" />
<data android:scheme="scheme1" /> <!-- sheme1://-->
<data android:host="yourdomain.com" />
<data android:host="www.yourdomain.com" />
</intent-filter>
</activity>

C)通过调用以下示例函数处理 onCreate ()和 onResume ()活动中传递的新意图:

private void handleUrl(Intent i){
String intentUrl = null;
if (i != null) {
intentUrl = i.getStringExtra("intentUrl");
if (intentUrl == null){
//hmm intent is damaged somehow
} else {
//because of onResume()
if ( i.getBooleanExtra("used",false) ) {
return;
}
i.putExtra("used", true);


//DO SOMETHING WITH YOUR URL HERE
}
}

只为一个实例解决这个问题

LaunchMode = “ singleInstance”

<activity
android:name=".SplashScreen"
android:screenOrientation="portrait"
android:launchMode="singleInstance"
android:theme="@style/Theme.AppCompat.Light.NoActionBar.FullScreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />


<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />


<data android:scheme="nvd.abc" />
</intent-filter>
</activity>

我也有同样的问题,只不过我希望用户返回到主任务,并且带有完整的后退堆栈,就好像他们刚刚使用了应用程序切换器来移动到我的应用程序一样。为了做到这一点,我不得不重新安排任务。

1)允许我的应用程序重新排序任务

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.company.app">
<uses-permission android:name="android.permission.REORDER_TASKS"/>
</manifest>

2)跟踪什么是 总台任务 ID

public class MainActivity {
public static int mainTaskId;


@Override
protected void onCreate(Bundle savedInstanceState) {
super(savedInstanceState);
//set the main task ID
taskId = getTaskId();
}
}

3)当我的深度链接活动启动时,它会保存一些数据供以后使用,然后将主要任务放在前面

public class DeepLinkActivity {


@Override
protected void onCreate(Bundle savedInstanceState) {
super(savedInstanceState);


//persist deep link data
Uri uri = intent.getData();
String action = intent.getAction();
saveForLater(uri, action);


if(isTaskRoot()){
//I'm in my own task and not the main task
final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
activityManager.moveTaskToFront(MainActivity.taskId, ActivityManager.MOVE_TASK_NO_USER_ACTION);
}
}
}
}

4)当主任务后台堆栈顶部的任何活动开始时,它检查是否有任何保存的数据要处理,并处理它。

我通过添加 android:launchMode="singleTask"来解决这些问题 在 AndroidManifest.xml文件中

(在开始上课时初始化)

String itemInfo == "";

基本上比较软件包的名称。

if(!itemInfo.equals(getItem(position).activityInfo.packageName))
{
intent.setComponent(new ComponentName(getItem(position).activityInfo.packageName,
getItem(position).activityInfo.name));


itemInfo = getItem(position).activityInfo.packageName;
((AxisUpiActivtiy) context).startActivityForResult(intent, RequestCodes.START_INTENT_RESPONSE);
}

这个条件 itemInfo.equals(getItem(position).activityInfo.packageName)是重要的

考虑在离开深度链接 Activity 时使用 finish(),因此如果再次操作深度链接,活动将被重新创建。 这可以避免错误和矛盾。

在经历了多个平台上可用的不同解决方案之后。这里是我的解决方案,最好的做法处理深层链接在您的应用程序。

首先创建一个单独的 Activity 来处理您的深度链接意图,例如 DeepLinkHandlerActivity。

请确保在清单中指定此活动如下:

<activity android:name=".DeepLinkHandlerActivity"
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="www.xyz.com"
android:pathPrefix="/abc"
android:scheme="https" />
</intent-filter>

将此活动命名为“单项任务”。

下一步: 设置新的活动如下:

    class DeepLinkHandlerActivity : BaseActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.whaterever_your_layout)
handelIntent(intent)
}


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


private fun handelIntent(intent: Intent?){
intent?.setClass(this,SplashActivity::class.java)
startActivity(intent)
}
}

注意: SplashActivity 是默认活动,即启动器活动。

发射器活动代码。

    <activity
android:name=".splash.SplashActivity"
android:theme="@style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />


<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

就是这样! 您的深层链接处理问题得到解决!