Я пытался реализовать систему push-уведомлений PushWoosh в моем существующем проекте Xamarin Forms (PCL), и до сих пор она отлично работает с iOS. Когда дело доходит до добавления его в Android, у меня возникает сбой при запуске, несмотря на то, что я следил буква за буквой руководство по Xamarin Forms для Android.

Приложение просто вылетает при запуске из-за необработанного исключения .

Я с удовольствием комментировал строку за строкой, чтобы найти причину этой ошибки, и похоже, что это manager.RegisterForPushNotifications();, который выполняет код, ответственный за этот сбой.

После дальнейшего изучения журнала отладки выяснилось, что проблема заключается в том, что ShortcutBadger не может разрешить намерение.

Я запустил приложение на физических устройствах, оно полностью обновлено:

  • Самсунг гэлакси с4
  • (Asus) Google Nexus 7

Я использую Visual Studio 2017 Community.


Манифест Android:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.package.awesome"
          android:versionCode="1"
          android:versionName="4.0"
          android:installLocation="auto">
  <uses-sdk android:minSdkVersion="15" />
  <!-- Badges -->
    <!-- Common -->
    <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS"/>
    <uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS"/>

    <!-- Apex -->
    <uses-permission android:name="com.anddoes.launcher.permission.UPDATE_COUNT"/>

    <!-- Samsung -->
    <uses-permission android:name="com.sec.android.provider.badge.permission.READ" />
    <uses-permission android:name="com.sec.android.provider.badge.permission.WRITE" />

    <!-- Sony -->
    <uses-permission android:name="com.sonyericsson.home.permission.BROADCAST_BADGE" />

    <!-- HTC -->
    <uses-permission android:name="com.htc.launcher.permission.READ_SETTINGS" />
    <uses-permission android:name="com.htc.launcher.permission.UPDATE_SHORTCUT" />

    <!-- Solid -->
    <uses-permission android:name="com.majeur.launcher.permission.UPDATE_BADGE"/>

    <!-- Huawei -->
    <uses-permission android:name="com.huawei.android.launcher.permission.CHANGE_BADGE"/>
    <uses-permission android:name="com.huawei.android.launcher.permission.READ_SETTINGS"/>
    <uses-permission android:name="com.huawei.android.launcher.permission.WRITE_SETTINGS"/>

    <!-- ZUK -->
    <uses-permission android:name="android.permission.READ_APP_BADGE"/>

    <!-- OPPO -->
    <uses-permission android:name="com.oppo.launcher.permission.READ_SETTINGS"/>
    <uses-permission android:name="com.oppo.launcher.permission.WRITE_SETTINGS"/>

    <!-- EvMe -->
    <uses-permission android:name="me.everything.badger.permission.BADGE_COUNT_READ"/>
    <uses-permission android:name="me.everything.badger.permission.BADGE_COUNT_WRITE"/>
  <!-- /Badges -->

  <!-- Location tracking -->
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

  <!-- Boot permission for rescheduling local notifications and location tracking -->
  <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

  <!-- GCM Part -->
  <permission android:name="com.package.awesome.permission.C2D_MESSAGE"
              android:protectionLevel="signature"/>
  <uses-permission android:name="com.package.awesome.permission.C2D_MESSAGE"/>

  <application android:label="@string/app_name"
               android:icon="@mipmap/ic_launcher">
    <meta-data android:name="com.google.android.gms.version"
               android:value="8487000" />
    <meta-data android:name="PW_APPID"
               android:value="A1B2C-3D4E5" />
    <meta-data android:name="PW_PROJECT_ID"
               android:value="awesome-app" />

    <!-- GCM Part -->
    <receiver
            android:name="com.google.android.gms.gcm.GcmReceiver"
            android:exported="true"
            android:permission="com.google.android.c2dm.permission.SEND" >
      <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <category android:name="com.package.awesome" />
      </intent-filter>
    </receiver>
  </application>
</manifest>

MainActivity.cs :

using System;
using Android.App;
using Android.Content;
using Android.OS;
using Pushwoosh;
using Android.Content.PM;
using Android.Util;

namespace Project.Droid
{
    class LocalMessageBroadcastReceiver : BasePushMessageReceiver
    {
        public MainActivity activity { get; set; }

        protected override void OnMessageReceive(Intent intent)
        {
            activity.doOnMessageReceive(intent.GetStringExtra(BasePushMessageReceiver.JsonDataKey));
        }
    }

    [Activity(Label = "@string/app_name", Theme = "@style/MyTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    [IntentFilter(new string[] { "com.package.awesome.MESSAGE" }, Categories = new string[] { "android.intent.category.DEFAULT" })]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        LocalMessageBroadcastReceiver mMessageReceiver;

        protected override void OnCreate(Bundle bundle)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(bundle);

            global::Xamarin.Forms.Forms.Init(this, bundle);

            LoadApplication(new App());

            mMessageReceiver = new LocalMessageBroadcastReceiver();
            mMessageReceiver.activity = this;

            registerReceivers();

            PushManager manager = PushManager.GetInstance(this);
            manager.OnStartup(this);

            // Register for push!
            manager.RegisterForPushNotifications();

            // Reset application icon badge number
            manager.BadgeNumber = 0;

            checkMessage(Intent);
        }

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

        public void checkMessage(Intent intent)
        {
            if (null != intent)
            {
                if (intent.HasExtra(PushManager.PushReceiveEvent))
                {
                    doOnMessageReceive(intent.Extras.GetString(PushManager.PushReceiveEvent));
                }

                resetIntentValues();
            }
        }

        public void doOnMessageReceive(String message)
        {
            // hadle push open here
            Log.Debug("PushwooshSample", "Push opened: " + message);
        }

        private void resetIntentValues()
        {
            Intent mainAppIntent = Intent;

            if (mainAppIntent.HasExtra(PushManager.PushReceiveEvent))
            {
                mainAppIntent.RemoveExtra(PushManager.PushReceiveEvent);
            }
            else if (mainAppIntent.HasExtra(PushManager.RegisterEvent))
            {
                mainAppIntent.RemoveExtra(PushManager.RegisterEvent);
            }
            else if (mainAppIntent.HasExtra(PushManager.UnregisterEvent))
            {
                mainAppIntent.RemoveExtra(PushManager.UnregisterEvent);
            }
            else if (mainAppIntent.HasExtra(PushManager.RegisterErrorEvent))
            {
                mainAppIntent.RemoveExtra(PushManager.RegisterErrorEvent);
            }
            else if (mainAppIntent.HasExtra(PushManager.UnregisterErrorEvent))
            {
                mainAppIntent.RemoveExtra(PushManager.UnregisterErrorEvent);
            }

            Intent = mainAppIntent;
        }

        protected override void OnResume()
        {
            base.OnResume();

            registerReceivers();
        }

        protected override void OnPause()
        {
            base.OnPause();

            unregisterReceivers();
        }

        public void registerReceivers()
        {
            IntentFilter intentFilter = new IntentFilter(PackageName + ".action.PUSH_MESSAGE_RECEIVE");
            RegisterReceiver(mMessageReceiver, intentFilter);
        }

        public void unregisterReceivers()
        {
            UnregisterReceiver(mMessageReceiver);
        }
    }
}

Журнал сбоев:

07-31 10:12:09.182 D/Pushwoosh(29231): [RequestManager] Try To send: getInApps
07-31 10:12:09.185 V/Pushwoosh(29231): [GCMRegistrationService] Intent action = com.pushwoosh.gcm.intent.REGISTER
07-31 10:12:09.190 E/Pushwoosh(29231): [ShortcutBadger] Unable to execute badge
07-31 10:12:09.190 E/Pushwoosh(29231): com.pushwoosh.thirdparty.a.b: Unable to execute badge
07-31 10:12:09.190 E/Pushwoosh(29231):  at com.pushwoosh.thirdparty.a.c.b(Unknown Source)
07-31 10:12:09.190 E/Pushwoosh(29231):  at com.pushwoosh.thirdparty.a.c.a(Unknown Source)
07-31 10:12:09.190 E/Pushwoosh(29231):  at com.pushwoosh.internal.PushManagerImpl$2.run(Unknown Source)
07-31 10:12:09.190 E/Pushwoosh(29231):  at android.os.Handler.handleCallback(Handler.java:739)
07-31 10:12:09.190 E/Pushwoosh(29231):  at android.os.Handler.dispatchMessage(Handler.java:95)
07-31 10:12:09.190 E/Pushwoosh(29231):  at android.os.Looper.loop(Looper.java:148)
07-31 10:12:09.190 E/Pushwoosh(29231):  at android.app.ActivityThread.main(ActivityThread.java:5417)
07-31 10:12:09.190 E/Pushwoosh(29231):  at java.lang.reflect.Method.invoke(Native Method)
07-31 10:12:09.190 E/Pushwoosh(29231):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
07-31 10:12:09.190 E/Pushwoosh(29231):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
07-31 10:12:09.190 E/Pushwoosh(29231): Caused by: com.pushwoosh.thirdparty.a.b: unable to resolve intent: Intent { act=android.intent.action.BADGE_COUNT_UPDATE (has extras) }
07-31 10:12:09.190 E/Pushwoosh(29231):  at com.pushwoosh.thirdparty.a.a.d.a(Unknown Source)
07-31 10:12:09.190 E/Pushwoosh(29231):  ... 10 more

Обратите внимание, что я переименовал имя проекта, пакет, идентификатор приложения PushWoosh и идентификатор приложения FCM в целях конфиденциальности.

0
Quentin Lamotte 31 Июл 2017 в 11:58
 – 
SushiHangover
31 Июл 2017 в 12:21
Спасибо за Ваш ответ. К сожалению, я уже читал этот пост и, как говорится в конце, этот вопрос был закрыт без действительного решения.
 – 
Quentin Lamotte
31 Июл 2017 в 12:36
Его открытый исходный код, вы всегда можете изменить исходный код для работы с используемой вами программой запуска. Основная проблема заключается в том, что для используемой вами программы запуска не определено намерение android.intent.action.BADGE_COUNT_UPDATE.
 – 
SushiHangover
31 Июл 2017 в 12:54
Я понимаю и еще раз благодарю вас за столь быстрый ответ. Основная проблема, с которой я столкнулся, заключается в том, что я разрабатываю проект Xamarin, используя систему управления пакетами (NuGet), и поэтому мне пришлось бы удалить все пакеты, связанные с тем, который вызывает эту функцию, а затем перекодировать и ввести их вручную в мое решение. Сомневаюсь, что у меня есть для этого необходимые знания и время.
 – 
Quentin Lamotte
31 Июл 2017 в 14:22
1
Нет, ты не!!! Я только что потратил последние 2 дня на то, чтобы понять это, это сработает, вам просто нужно убедиться, что вы используете последние (предварительные) версии Xamarin.Android.Support.v4 и googleplayservices.gcm. В stackoverflow есть сообщение, которое я не могу найти сейчас, которое поставило меня на правильный путь. Как только я обновил пакеты, все начало работать.
 – 
Mike
3 Авг 2017 в 22:13

1 ответ

Лучший ответ

Я решил свою проблему, обновив зависимость Xamarin.GooglePlayServices.Gcm до последней версии 42.1021.1, в то время как моя была 29.x.x.

Как сказал Майк в комментариях, я должен был убедиться, что все обновлено, поскольку PushWoosh не требует высокой версии критических зависимостей, таких как службы Google Play, хотя они потенциально могут привести к сбою приложения, если оно устарело. Они должны быть более строгими в этом отношении!

0
Quentin Lamotte 4 Авг 2017 в 16:44