深层链接和多个应用实例

时间:2014-09-17 07:42:18

标签: android deep-linking

我在我的应用中实现了深层链接。我在清单文件中添加了这个intent过滤器,深层链接正在运行。

<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)之上。我怎么能这样做?

9 个答案:

答案 0 :(得分:58)

你需要为你的Manifest中的Activity做一些事情。

android:launchMode="singleTask"

这告诉系统始终启动Activity的现有实例(如果已创建)。

然后你可以通过覆盖方法来处理Intent

onNewIntent 

有关详细信息,请参阅http://developer.android.com/guide/topics/manifest/activity-element.html

答案 1 :(得分:10)

接受的答案对我不起作用,这是做了什么:

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

来自官方文件:

  

如果已设置,并且正在启动的活动已在当前任务中运行,则不会启动该活动的新实例,而是将关闭其上的所有其他活动,并将此Intent传递给(现在在顶部)作为新意图的旧活动。

答案 2 :(得分:4)

我有同样的问题,除了我希望用户使用完整的后台堆栈返回主任务,好像他们刚刚使用应用程序切换器移动到我的应用程序。要做到这一点,我不得不重新安排任务。

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)当主任务顶部的任何活动开始时,它会检查是否有任何已保存的数据可供使用,并对其进行处理。

答案 3 :(得分:3)

我们在深层链接方面遇到了一些问题。 像:

  1. 仅点击两次相同的链接,首先点击触发正确的视图
  2. 打开多个实例
  3. whatsapp或facebook中的链接因为他们的网络浏览器而在whatsapp本身打开了一个视图。
  4. android 6上的
  5. 只打开了一个实例,但只处理了第一个实例 意图,第二个和第三个打开应用程序但没有动作,因为intentdata没有以某种方式改变。
  6. 因此,对于我们遇到的几个问题,以下问题不是一个明确的答案,而是一个全面的解决方案。

    我们的解决方案:

    a)创建了一个新的FragmentActivity

    @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()中传递的新intent:

    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
        }       
    }
    

答案 4 :(得分:2)

只针对一个实例解决此问题

  

机器人:launchMode =&#34; singleInstance&#34;

<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>

答案 5 :(得分:0)

我通过添加android:launchMode =“ singleTask”解决了这些问题 在清单文件中

答案 6 :(得分:0)

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

答案 7 :(得分:0)

在经历了在多个平台上可用的不同解决方案之后。这是我在应用中处理深度链接的最佳实践的解决方案。

首先创建一个单独的活动来处理您的深层链接意图,例如。 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>

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

答案 8 :(得分:-1)

(在课程开始时初始化)

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)很重要