Branch.io с формами Xamarin: InitSessionComplete не вызывается в приложении Android при подтверждении push-уведомлений - PullRequest
0 голосов
/ 04 января 2019

Я использую Branch.io в приложении Xamarin Forms, и моя цель - отправлять push-уведомления через концентраторы уведомлений Azure с ссылками на них в филиалах, чтобы открыть приложение и что-то сделать. Кажется, у меня все отлично настроено для iOS, но в Android я получаю push-уведомление и появляется правильная активность, но InitSessionComplete не вызывается для моего объекта IBranchBUOSessionInterface.

Я подозреваю, что проблема в том, как я создаю PendingIntent, но могу ошибаться. И снова InitSessionComplete вызывается при любых других обстоятельствах, кроме случаев, когда я получаю push-уведомление со ссылкой на филиал.

Весь соответствующий код приведен ниже. Спасибо!

MainApplication.cs

using System;
using Android.App;
using Android.OS;
using Android.Runtime;
using BranchXamarinSDK;
using Plugin.CurrentActivity;

namespace MyCompany.MyApp.Droid
{
    //You can specify additional application information in this attribute
    [Application]
    [MetaData("io.branch.sdk.auto_link_disable", Value = "false")]
    [MetaData("io.branch.sdk.TestMode", Value = "true")]
    [MetaData("io.branch.sdk.BranchKey", Value = "@string/branch_key")]
    public class MainApplication : Application, Application.IActivityLifecycleCallbacks
    {
        public MainApplication (IntPtr handle, JniHandleOwnership transer)
          : base (handle, transer)
        {
        }

        public override void OnCreate ()
        {
            base.OnCreate ();
            RegisterActivityLifecycleCallbacks (this);
            BranchAndroid.GetAutoInstance(ApplicationContext);
        }

        public override void OnTerminate ()
        {
            base.OnTerminate ();
            UnregisterActivityLifecycleCallbacks (this);
        }

        public void OnActivityCreated (Activity activity, Bundle savedInstanceState)
        {
            CrossCurrentActivity.Current.Activity = activity;
        }

        public void OnActivityDestroyed (Activity activity)
        {
        }

        public void OnActivityPaused (Activity activity)
        {
        }

        public void OnActivityResumed (Activity activity)
        {
            CrossCurrentActivity.Current.Activity = activity;
        }

        public void OnActivitySaveInstanceState (Activity activity, Bundle outState)
        {
        }

        public void OnActivityStarted (Activity activity)
        {
            CrossCurrentActivity.Current.Activity = activity;
        }

        public void OnActivityStopped (Activity activity)
        {
        }
    }
}

MainActivity.cs

using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using Android.Util;
using BranchXamarinSDK;
using MyCompany.Shared.Droid.Modules;
using App = MyCompany.MyApp.Core.App;

namespace MyCompany.MyApp.Droid
{
    [Activity (Theme = "@style/Custom.Holo", 
               Label = "MyApp", 
               Icon = "@drawable/icon", 
               ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation,
               ScreenOrientation = ScreenOrientation.Portrait, 
               LaunchMode = LaunchMode.SingleTask, 
               MainLauncher = true)]
    [IntentFilter(new[] { "android.intent.action.VIEW" },
        Categories = new[] { "android.intent.category.DEFAULT", "android.intent.category.BROWSABLE" },
        DataScheme = "myapp",
        DataHost = "open")]

    [IntentFilter(new[] { "android.intent.action.VIEW" },
        Categories = new[] { "android.intent.category.DEFAULT", "android.intent.category.BROWSABLE" },
        DataScheme = "https",
        DataHost = "mycompanymyapp.test-app.link")]
    public class MainActivity : Xamarin.Forms.Platform.Android.FormsApplicationActivity, IBranchBUOSessionInterface
    {
        public const string Tag = "MainActivity";
        private App _app;

        internal static readonly string ChannelId = "MyCompany";
        internal static readonly int NotificationId = 100;

        protected override void OnCreate (Bundle savedInstanceState)
        {
            base.OnCreate (savedInstanceState);

            if (Intent.Extras != null)
            {
                foreach (var key in Intent.Extras.KeySet())
                {
                    if (key == null) { continue; }

                    var value = Intent.Extras.GetString(key);
                    Log.Debug(Tag, "Key: {0} Value: {1}", key, value);
                }
            }

            // Removes icon from android navbar
            ActionBar.SetIcon(Android.Resource.Color.Transparent);

            Xamarin.Forms.Forms.Init (this, savedInstanceState);

            BranchAndroid.Debug = true;

            var androidModule = new MyCompanyAndroidServicesModule ();
            var app = new App (androidModule);

            BranchAndroid.Init(this, GetString(Resource.String.branch_key), this);
            LoadApplication(app);

            _app = app;
        }

        #region IBranchSessionInterface implementation

        public void InitSessionComplete(BranchUniversalObject buo, BranchLinkProperties blp)
        {
            _app.InitSessionComplete(buo, blp);
        }

        public void SessionRequestError(BranchError error)
        {
            _app.SessionRequestError(error);
        }

        #endregion

        protected override void OnNewIntent(Intent intent)
        {
            Intent = intent;
        }
    }
}

MyCompany.MyApp.Core.cs

#region Libraries
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using Autofac;
using BranchXamarinSDK;
using MyCompany.Core;
using MyCompany.Core.Factories;
using MyCompany.Core.Helpers;
using MyCompany.Core.Services;
using MyCompany.Core.ViewModels;
using MyCompany.MyApp.Core.ViewModels;
using Xamarin.Forms;
using Device = Xamarin.Forms.Device;

#endregion Libraries

namespace MyCompany.MyApp.Core
{
    public class App : Application, ILoginApp, IBranchBUOSessionInterface
    {
        #region Variables
        readonly IViewFactory _viewFactory;
        readonly INavigationService _navService;
        #endregion Variables

        #region Constructor
        public App (Module platformServiceModule = null)
        {
            var bootstrapper = new TimeAppBootstrapper ();

            if (platformServiceModule != null)
                bootstrapper.AddModule (platformServiceModule);

            bootstrapper.Run ();

            _viewFactory = bootstrapper.Container.Resolve<IViewFactory> ();
            _navService = bootstrapper.Container.Resolve<INavigationService> ();
            Page startView = new NavigationPage (_viewFactory.Resolve<LoginV2ViewModel> ()) {
                    BarBackgroundColor = Color.White,
                    BarTextColor = Color.FromRgb(34, 149, 236)
                };

            MainPage = startView;
        }
        #endregion Constructor

        protected override void OnStart ()
        {
            // Handle when your app starts
        }

        protected override void OnSleep ()
        {
            // Handle when your app sleeps
        }

        /// <summary>
        /// Application developers override this method to perform actions
        /// when the application resumes from a sleeping state.
        /// </summary>
        protected override void OnResume ()
        {

        }

        #region IBranchSessionInterface implementation

        public void InitSessionComplete(BranchUniversalObject buo, BranchLinkProperties blp)
        {
            if (blp.feature == "feature")
            {
                _navService.NavigateTo<FeatureViewModel>();
            }
        }

        public void SessionRequestError(BranchError error)
        {
            var e = error;
        }

        #endregion
    }
}

FirebaseMessagingService.cs

using Android.App;
using Android.Content;
using Android.Util;
using Firebase.Messaging;
using Xamarin.Essentials;

namespace Crowdkeep.Time.Droid.Services
{
    [Service]
    [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
    public class MyFirebaseMessagingService : FirebaseMessagingService
    {
        const string TAG = "MyFirebaseMessagingService";
        public override void OnMessageReceived(RemoteMessage message)
        {
            Log.Debug(TAG, "From: " + message.From);

            var notificationManager = NotificationManager.FromContext(this);

            InitializeChannels(notificationManager);

            if (IsProductionNotification(message))
            {
                SendProductionNotification(message, notificationManager, this);
            }
            else
            {
                SendTestNotification(message, notificationManager);
            }
        }

        private static bool IsProductionNotification(RemoteMessage message)
        {
            return message.GetNotification() != null;
        }

        private void SendTestNotification(RemoteMessage message, NotificationManager notificationManager)
        {
            var notification = CreateNotification(message.Data["message"], message.Data["branch"], this);
            notificationManager.Notify(0, notification);
        }

        private static void SendProductionNotification(RemoteMessage message, NotificationManager manager, Context context)
        {
            Log.Debug(TAG, "Notification Message Body: " + message.GetNotification().Body);
            var notification = CreateNotification(message.GetNotification().Body, "https://mycompanymyapp.test-app.link/feature", context);
            manager.Notify(0, notification);
        }

        private static void InitializeChannels(NotificationManager manager)
        {
            if (DeviceInfo.Version.Major < 8 || manager.GetNotificationChannel(MainActivity.ChannelId) != null)
            {
                return;
            }

            var channel = new NotificationChannel(MainActivity.ChannelId, "Crowdkeep", NotificationImportance.Default)
            {
                Description = "Default Channel"
            };

            manager.CreateNotificationChannel(channel);
        }

        private static Notification CreateNotification(string messageBody, string link, Context context)
        {
            var pendingIntent = SetupNotificationIntent(link, context);

            var notificationBuilder = new Notification.Builder(context, MainActivity.ChannelId)
                .SetContentTitle("Message")
                .SetSmallIcon(Resource.Drawable.icon)
                .SetContentText(messageBody)
                .SetAutoCancel(true)
                .SetContentIntent(pendingIntent)
                .SetVisibility(NotificationVisibility.Public);

            return notificationBuilder.Build();
        }

        private static PendingIntent SetupNotificationIntent(string link, Context context)
        {
            var intent = new Intent(context, typeof(MainActivity));
            intent.SetFlags(ActivityFlags.ClearTop);
            intent.PutExtra("branch", link);
            intent.PutExtra("branch_force_new_session", true);

            var pendingIntent = PendingIntent.GetActivity(context, MainActivity.NotificationId, intent, PendingIntentFlags.OneShot);
            return pendingIntent;
        }
    }
}

Json отправлено с помощью уведомления:

{"data":{"message":"Click this notification to go to the best feature of the app!", "branch": "https://mycompanymyapp.test-app.link/feature"}}

РЕДАКТИРОВАТЬ (1/7/2019)

Я могу воспроизвести это на испытательном стенде. Я раздвоил свою собственную копию Branch и добавил ветку с именем initsessioncomplete-push-messages-issue, , доступ к которой можно получить здесь . Я следовал этим инструкциям , чтобы настроить Firebase и Azure Notification Hubs. В этом решении единственное, что вам нужно изменить, - это две строки в классе AppConstants в проекте TestBed.Droid и добавить файл google-services.json в корень проекта Droid (файл .csproj уже настроен правильно, чтобы прочитать его).

Насколько я могу судить, я вижу успешный вызов API-интерфейса Branch, когда нажимаю push-уведомление, но InitSessionComplete никогда не вызывается.

1 Ответ

0 голосов
/ 04 января 2019

Джун из филиала здесь. Можете ли вы дважды проверить, что вы используете правильный ключ ветви в AndroidManifest? Я заметил, что вы проводите тестирование с помощью Branch Link, поэтому вам придется использовать свой тестовый ключ Branch.

...