如何通过深度链接在不丢失活动堆栈(或应用程序状态)的情况下恢复 android 应用程序?
How to resume android app without losing activities stack (or the app state) with deep linking?
我有这个 <intent-filter>
每次按下某些 link 它都会打开我的应用程序但问题是它会打开我的应用程序的 new 实例. 有没有办法触发 onResume() 并在不丢失其状态或活动堆栈的情况下恢复我的应用程序?
这是意图过滤器:
<intent-filter>
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="example.com" />
<data android:pathPattern="/.*" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
更新
感谢用户 David Wasser 在下面的回答我找到了答案:
所以我创建了在 gmail/inbox app:
之上启动的 EntryActivity
public class EntryActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.entry_activity);
Uri uriParams = getIntent().getData();
Log.e("EntryActivity", uriParams.getHost() );
Log.e("EntryActivity", uriParams.getQueryParameter("uid") + " " + uriParams.getQueryParameter("type") + " " + uriParams.getQueryParameter("token") );
Intent startCategory = new Intent(this, GotEmailActivity.class);
startCategory.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startCategory);
this.finish();
}
}
然后当我的应用程序在 GotEmailActivity 打开时,我用 link 向用户发送电子邮件以打开应用程序并且 GotEmailActivity 在 AndroidManifest 中有属性 android:launchMode="singleTop"
所以只有它的 1 个实例被打开:
<!--
Important: notice android:launchMode="singleTop"
which seeks if an instance of this activity is already opened and
resumes already opened instance, if not it opens new instance.
-->
<activity
android:name=".presenters.register.email.GotEmailActivity"
android:label="@string/title_activity_got_email"
android:launchMode="singleTop"
android:theme="@android:style/Theme.Translucent.NoTitleBar" >
现在发生的事情是 EntryActivity 在 Gmail 应用程序的顶部打开但它在中间关闭但首先启动已经打开的 GotEmailActivity 因此属性 launchMode Singletop 阻止了这样的新实例 activity.
您应该创建另一个 Activity
,在响应 <intent-filter>
时用作应用程序的入口点。像这样:
您需要的只是一个什么都不做的简单 Activity。这是一个例子:
public class EntryActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Check to see if this Activity is the root activity
if (isTaskRoot()) {
// This Activity is the only Activity, so
// the app wasn't running. So start the app from the
// beginning (redirect to MainActivity)
Intent mainIntent = getIntent(); // Copy the Intent used to launch me
// Launch the real root Activity (launch Intent)
mainIntent.setClass(this, MainActivity.class);
// I'm done now, so finish()
startActivity(mainIntent);
finish();
} else {
// App was already running, so just finish, which will drop the user
// in to the activity that was at the top of the task stack
finish();
}
}
}
将你的 <intent-filter>
放在这个 activity 上,而不是你的 "launcher" Activity。确保在清单中此 activity 的任务亲和力与应用程序中其他活动的任务亲和力相同(默认情况下,如果您没有明确设置 android:taskAffinity).
当 <intent-filter>
被触发时,如果您的应用程序是 运行,那么 EntryActivity
将在最顶层的 上启动activity 在您的应用程序的任务中,该任务将被带到前台。当 EntryActivity
完成时,它将简单地 return 用户到应用程序中的最顶层 activity (即:当它进入后台时用户离开的地方)。
如果您的应用 不是 运行,EntryActivity
会识别这一点并从头启动您的应用,将其传递给 Intent
包含触发 <intent-filter>
.
的 ACTION 和 DATA
应该可以。
我有这个 <intent-filter>
每次按下某些 link 它都会打开我的应用程序但问题是它会打开我的应用程序的 new 实例. 有没有办法触发 onResume() 并在不丢失其状态或活动堆栈的情况下恢复我的应用程序?
这是意图过滤器:
<intent-filter>
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="example.com" />
<data android:pathPattern="/.*" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
更新
感谢用户 David Wasser 在下面的回答我找到了答案:
所以我创建了在 gmail/inbox app:
之上启动的 EntryActivitypublic class EntryActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.entry_activity);
Uri uriParams = getIntent().getData();
Log.e("EntryActivity", uriParams.getHost() );
Log.e("EntryActivity", uriParams.getQueryParameter("uid") + " " + uriParams.getQueryParameter("type") + " " + uriParams.getQueryParameter("token") );
Intent startCategory = new Intent(this, GotEmailActivity.class);
startCategory.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startCategory);
this.finish();
}
}
然后当我的应用程序在 GotEmailActivity 打开时,我用 link 向用户发送电子邮件以打开应用程序并且 GotEmailActivity 在 AndroidManifest 中有属性 android:launchMode="singleTop"
所以只有它的 1 个实例被打开:
<!--
Important: notice android:launchMode="singleTop"
which seeks if an instance of this activity is already opened and
resumes already opened instance, if not it opens new instance.
-->
<activity
android:name=".presenters.register.email.GotEmailActivity"
android:label="@string/title_activity_got_email"
android:launchMode="singleTop"
android:theme="@android:style/Theme.Translucent.NoTitleBar" >
现在发生的事情是 EntryActivity 在 Gmail 应用程序的顶部打开但它在中间关闭但首先启动已经打开的 GotEmailActivity 因此属性 launchMode Singletop 阻止了这样的新实例 activity.
您应该创建另一个 Activity
,在响应 <intent-filter>
时用作应用程序的入口点。像这样:
您需要的只是一个什么都不做的简单 Activity。这是一个例子:
public class EntryActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Check to see if this Activity is the root activity
if (isTaskRoot()) {
// This Activity is the only Activity, so
// the app wasn't running. So start the app from the
// beginning (redirect to MainActivity)
Intent mainIntent = getIntent(); // Copy the Intent used to launch me
// Launch the real root Activity (launch Intent)
mainIntent.setClass(this, MainActivity.class);
// I'm done now, so finish()
startActivity(mainIntent);
finish();
} else {
// App was already running, so just finish, which will drop the user
// in to the activity that was at the top of the task stack
finish();
}
}
}
将你的 <intent-filter>
放在这个 activity 上,而不是你的 "launcher" Activity。确保在清单中此 activity 的任务亲和力与应用程序中其他活动的任务亲和力相同(默认情况下,如果您没有明确设置 android:taskAffinity).
当 <intent-filter>
被触发时,如果您的应用程序是 运行,那么 EntryActivity
将在最顶层的 上启动activity 在您的应用程序的任务中,该任务将被带到前台。当 EntryActivity
完成时,它将简单地 return 用户到应用程序中的最顶层 activity (即:当它进入后台时用户离开的地方)。
如果您的应用 不是 运行,EntryActivity
会识别这一点并从头启动您的应用,将其传递给 Intent
包含触发 <intent-filter>
.
应该可以。