【问题标题】:Open specific page in Ionic (Capacitor) app from Android intent从 Android 意图打开 Ionic (Capacitor) 应用程序中的特定页面
【发布时间】:2019-07-21 14:05:03
【问题描述】:

我有一个使用 Ionic 4 和 Capacitor 编写的 web/android 应用程序,我一直在尝试从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) 行中/周围放置一些东西,以使 Capacitor / Ionic 将应用程序初始化为正确的状态,但我无法弄清楚应该是什么!

我翻阅了 Capacitor 文档,但到目前为止找不到解决方案,我怀疑我需要使用某种 URL 向 Activity 发送“视图”意图?

当前的行为是让它启动看似全新的应用程序实例(它重新加载启动屏幕等),即使应用程序仍然是手机上的前台任务。

更新

我最近的尝试是创建这样的意图:

Intent notificationIntent = new Intent(Intent.ACTION_VIEW,
    Uri.parse("http://localhost/event/horse"),
    this, MainActivity.class);

(假设我在 Ionic/Angular 中为 /event/horse 设置了一条有效路线,我这样做了)

虽然没有变化,但这仍然表现出与上述相同的行为(重新进入启动屏幕)。

【问题讨论】:

    标签: android ionic-framework android-intent ionic4 capacitor


    【解决方案1】:

    为了实现这种行为,需要三个不同的部分。

    首先,您的 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 应用程序未运行的情况下,这不会在 Ionic 应用程序中设置“返回”堆栈,因此回击不会自动向上导航。但这是一个不同的问题......

    【讨论】:

    • android 文件中的 notificationIntent 放在哪里?
    猜你喜欢
    • 2022-10-14
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多