从 Android intent 打开 Ionic(电容器)应用程序中的特定页面
Open specific page in Ionic (Capacitor) app from Android intent
我有一个 web/android 应用程序,使用 Ionic 4 和 Capacitor 编写,我一直在尝试重新进入 Ionic 应用程序 到特定页面 来自 Android 服务(通过电容器插件激活)发出的通知。
这是在服务中创建通知的代码:
private Notification getNotification() {
CharSequence contentTitle = "Fun App Background Mode Running";
CharSequence contentText = "Fun App";
long notificationTime = System.currentTimeMillis();
if (_NFC == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel("funapp", "FunApp", NotificationManager.IMPORTANCE_DEFAULT);
channel.enableLights(false);
channel.enableVibration(false);
channel.setSound(null,null);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
channel.setShowBadge(true);
manager.createNotificationChannel(channel);
}
Intent notificationIntent = new Intent(this, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntentWithParentStack(notificationIntent);
PendingIntent pendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
_NFC = new NotificationCompat.Builder(getApplicationContext(),"funapp")
.setSmallIcon(R.drawable.ic_sheep_notif)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher_foreground))
.setPriority(NotificationCompat.PRIORITY_LOW)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.setVisibility(NotificationCompat.VISIBILITY_SECRET)
.setContentTitle(contentTitle)
.setContentText(contentText)
.setStyle(new NotificationCompat.BigTextStyle().bigText(contentText).setBigContentTitle(contentTitle))
.setContentIntent(pendingIntent)
.setOngoing(true);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
_NFC.setPriority(NotificationCompat.PRIORITY_LOW);
}
}
_NFC.setContentTitle(contentTitle);
_NFC.setContentText(contentText);
_NFC.setStyle(new NotificationCompat.BigTextStyle().bigText(contentText).setBigContentTitle(contentTitle));
_NFC.setWhen(notificationTime);
return _NFC.build();
}
我认为我需要在 new Intent(this, MainActivity.class)
行中添加一些内容 in/around 以使 Capacitor / Ionic 将应用程序初始化为正确的状态,但我不知道应该是什么!
我已经查阅了 Capacitor 文档,但到目前为止还没有找到解决方案,我怀疑我需要通过某种方式向 activity 发送一个 "view" 意图URL?
当前的行为是它启动一个看似全新的应用程序实例(它重新加载启动画面等),即使该应用程序仍然是 [=43= 上的前台任务].
更新
我最近的尝试是创建这样的意图:
Intent notificationIntent = new Intent(Intent.ACTION_VIEW,
Uri.parse("http://localhost/event/horse"),
this, MainActivity.class);
(假设我在 Ionic/Angular 中为 /event/horse 设置了一条有效路线,我这样做了)
尽管没有变化,这仍然表现出与上述相同的行为(重新进入初始屏幕)。
为了实现这个行为,需要三个不同的部分。
首先,您的 Angular / Ionic 代码必须连接到来自 Capacitor App 插件的事件,并在使用打开 URL 调用时进行导航,例如:
import { Plugins, AppUrlOpen } from '@capacitor/core';
import { Router } from '@angular/router';
@Component({
selector: 'app-root',
templateUrl: 'app.component.html'
})
export class AppComponent {
constructor(
private platform: Platform,
private router: Router
) {
this.initializeApp();
}
initializeApp() {
this.platform.ready().then(() => {
if (this.platform.is('capacitor')) {
Plugins.SplashScreen.hide();
// THIS WILL BE USED IF THE APP IS ALREADY OPEN:
Plugins.App.addListener('appUrlOpen', (urlOpen: AppUrlOpen) => {
console.log('App URL Open', urlOpen);
this.navigate(urlOpen.url);
});
}
// THIS WILL BE USED IF THE APP HAS BEEN KILLED AND RE-OPENED:
this.getLaunchUrl();
});
}
async getLaunchUrl() {
const urlOpen = await Plugins.App.getLaunchUrl();
if(!urlOpen || !urlOpen.url) return;
console.log('Launch URL', urlOpen);
this.navigate(urlOpen.url);
}
navigate(uri: string) {
// THIS MUST EQUAL THE 'custom_url_scheme' from your Android intent:
if (!uri.startsWith('net.exampleapp.app:/')) return;
// Strip off the custom scheme:
uri = uri.substring(19);
this.router.navigateByUrl(uri);
}
}
然后,在 Android 端,这是获取 PendingIntent 以触发此行为所需的咒语:
Intent notificationIntent = getPackageManager()
.getLaunchIntentForPackage(getPackageName())
.setPackage(null)
.setAction(Intent.ACTION_VIEW)
.setData(Uri.parse(
getResources().getString(R.string.custom_url_scheme) +
"://events/" + _EventId))
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 1234,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
最后,在您应用的 AndroidManifest.xml 中,您还必须将 MainActivity 的启动模式指定为 SingleTask 或 SingleTop(两者似乎都有效):
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale"
android:label="@string/title_activity_main"
android:theme="@style/AppTheme.NoActionBarLaunch">
使用此组合,如果应用程序仍然是 运行,相关页面将被正确导航到,如果不是 运行,应用程序将被打开,然后页面将是导航到。
但是请注意,在应用程序不是 运行 的情况下,这不会在 Ionic 应用程序中合理地设置 "back" 堆栈,因此回击不会自动向上导航.但这是一个不同的问题...
我有一个 web/android 应用程序,使用 Ionic 4 和 Capacitor 编写,我一直在尝试重新进入 Ionic 应用程序 到特定页面 来自 Android 服务(通过电容器插件激活)发出的通知。
这是在服务中创建通知的代码:
private Notification getNotification() {
CharSequence contentTitle = "Fun App Background Mode Running";
CharSequence contentText = "Fun App";
long notificationTime = System.currentTimeMillis();
if (_NFC == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel("funapp", "FunApp", NotificationManager.IMPORTANCE_DEFAULT);
channel.enableLights(false);
channel.enableVibration(false);
channel.setSound(null,null);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
channel.setShowBadge(true);
manager.createNotificationChannel(channel);
}
Intent notificationIntent = new Intent(this, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntentWithParentStack(notificationIntent);
PendingIntent pendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
_NFC = new NotificationCompat.Builder(getApplicationContext(),"funapp")
.setSmallIcon(R.drawable.ic_sheep_notif)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher_foreground))
.setPriority(NotificationCompat.PRIORITY_LOW)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.setVisibility(NotificationCompat.VISIBILITY_SECRET)
.setContentTitle(contentTitle)
.setContentText(contentText)
.setStyle(new NotificationCompat.BigTextStyle().bigText(contentText).setBigContentTitle(contentTitle))
.setContentIntent(pendingIntent)
.setOngoing(true);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
_NFC.setPriority(NotificationCompat.PRIORITY_LOW);
}
}
_NFC.setContentTitle(contentTitle);
_NFC.setContentText(contentText);
_NFC.setStyle(new NotificationCompat.BigTextStyle().bigText(contentText).setBigContentTitle(contentTitle));
_NFC.setWhen(notificationTime);
return _NFC.build();
}
我认为我需要在 new Intent(this, MainActivity.class)
行中添加一些内容 in/around 以使 Capacitor / Ionic 将应用程序初始化为正确的状态,但我不知道应该是什么!
我已经查阅了 Capacitor 文档,但到目前为止还没有找到解决方案,我怀疑我需要通过某种方式向 activity 发送一个 "view" 意图URL?
当前的行为是它启动一个看似全新的应用程序实例(它重新加载启动画面等),即使该应用程序仍然是 [=43= 上的前台任务].
更新
我最近的尝试是创建这样的意图:
Intent notificationIntent = new Intent(Intent.ACTION_VIEW,
Uri.parse("http://localhost/event/horse"),
this, MainActivity.class);
(假设我在 Ionic/Angular 中为 /event/horse 设置了一条有效路线,我这样做了)
尽管没有变化,这仍然表现出与上述相同的行为(重新进入初始屏幕)。
为了实现这个行为,需要三个不同的部分。
首先,您的 Angular / Ionic 代码必须连接到来自 Capacitor App 插件的事件,并在使用打开 URL 调用时进行导航,例如:
import { Plugins, AppUrlOpen } from '@capacitor/core';
import { Router } from '@angular/router';
@Component({
selector: 'app-root',
templateUrl: 'app.component.html'
})
export class AppComponent {
constructor(
private platform: Platform,
private router: Router
) {
this.initializeApp();
}
initializeApp() {
this.platform.ready().then(() => {
if (this.platform.is('capacitor')) {
Plugins.SplashScreen.hide();
// THIS WILL BE USED IF THE APP IS ALREADY OPEN:
Plugins.App.addListener('appUrlOpen', (urlOpen: AppUrlOpen) => {
console.log('App URL Open', urlOpen);
this.navigate(urlOpen.url);
});
}
// THIS WILL BE USED IF THE APP HAS BEEN KILLED AND RE-OPENED:
this.getLaunchUrl();
});
}
async getLaunchUrl() {
const urlOpen = await Plugins.App.getLaunchUrl();
if(!urlOpen || !urlOpen.url) return;
console.log('Launch URL', urlOpen);
this.navigate(urlOpen.url);
}
navigate(uri: string) {
// THIS MUST EQUAL THE 'custom_url_scheme' from your Android intent:
if (!uri.startsWith('net.exampleapp.app:/')) return;
// Strip off the custom scheme:
uri = uri.substring(19);
this.router.navigateByUrl(uri);
}
}
然后,在 Android 端,这是获取 PendingIntent 以触发此行为所需的咒语:
Intent notificationIntent = getPackageManager()
.getLaunchIntentForPackage(getPackageName())
.setPackage(null)
.setAction(Intent.ACTION_VIEW)
.setData(Uri.parse(
getResources().getString(R.string.custom_url_scheme) +
"://events/" + _EventId))
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 1234,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
最后,在您应用的 AndroidManifest.xml 中,您还必须将 MainActivity 的启动模式指定为 SingleTask 或 SingleTop(两者似乎都有效):
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale"
android:label="@string/title_activity_main"
android:theme="@style/AppTheme.NoActionBarLaunch">
使用此组合,如果应用程序仍然是 运行,相关页面将被正确导航到,如果不是 运行,应用程序将被打开,然后页面将是导航到。
但是请注意,在应用程序不是 运行 的情况下,这不会在 Ionic 应用程序中合理地设置 "back" 堆栈,因此回击不会自动向上导航.但这是一个不同的问题...