代码之家  ›  专栏  ›  技术社区  ›  Eugene

Xamarin.Forms应用程序上的Android Firebase初始化失败[重复]

  •  0
  • Eugene  · 技术社区  · 6 年前

    我正在学习教程 here 在我的Xamarin.Forms应用程序中为Android设置Firebase云消息。这是一个应用程序,目前使用谷歌云消息(GCM)。我相信我遵循了教程中的所有步骤。但是,我的 OnTokenRefresh OnMessageReceived 方法从不触发。

    在我的机器人项目中,我有Xamarin.Firebase.Common、Xamarin.Firebase.Iid、Xamarin.Firebase.Messaging、Xamarin.GooglePlayServices.Base、Xamarin.GooglePlayServices.Basement、Xamarin.GooglePlayServices.Tasks包。我还有大约70个其他包(我没有创建这个应用程序)。我删除了所有与GCM相关的包,并删除了与GCM相关的代码。我的google-services.json设置为GoogleServicesJson build action。

    Console.Out.WriteLine("MainActivity InstanceID token: " + FirebaseInstanceId.Instance.Token); 到主要活动的 OnCreate 方法若要强制应用程序给我一个令牌,它将崩溃,并返回错误:

    Java.Lang.IllegalStateException
    
    Default FirebaseApp is not initialized in this process com.ebelinski.fakename. Make sure to call FirebaseApp.initializeApp(Context) first.
    

    我试过很多不同的方法,但都没有效果。以下是我的代码:

    WinterFirebaseIIDService.cs公司

    using System.Collections.Generic;
    using Android.App;
    using WindowsAzure.Messaging;
    using Firebase.Iid;
    
    namespace FakeName.Droid {
    
      [Service]
      [IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
      public class WinterFirebaseIIDService: FirebaseInstanceIdService {
    
        NotificationHub hub;
    
        public override void OnTokenRefresh() {
          var refreshedToken = FirebaseInstanceId.Instance.Token;
          AppLog.Checkpoint("WinterFirebaseIIDService FCM token: " + refreshedToken);
          SendRegistrationToServer(refreshedToken);
        }
    
        void SendRegistrationToServer(string token) {
          // Register with Notification Hubs
          hub = new NotificationHub(AppConstants.NOTIFICATION_HUB_NAME,
                                    AppConstants.NOTIFICATION_HUB_CONNECTION, this);
    
          var tags = new List<string>() { };
          var regID = hub.Register(token, tags.ToArray()).RegistrationId;
    
          AppLog.Checkpoint("WinterFirebaseIIDService Successful registration of ID " + regID);
        }
    
      }
    
    }
    

    WinterFirebaseMessagingService公司

    using System.Linq;
    using Android.App;
    using Firebase.Messaging;
    
    namespace FakeName.Droid {
    
      [Service]
      [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
      public class WinterFirebaseMessagingService: FirebaseMessagingService {
    
        public override void OnMessageReceived(RemoteMessage message) {
          AppLog.Checkpoint("WinterFirebaseMessagingService From: " + message.From);
          if (message.GetNotification() != null) {
            //These is how most messages will be received
            AppLog.Checkpoint("WinterFirebaseMessagingService Notification Message Body: " + message.GetNotification().Body);
            SendNotification(message.GetNotification().Body);
          }
          else {
            //Only used for debugging payloads sent from the Azure portal
            SendNotification(message.Data.Values.First());
    
          }
    
        }
    
        void SendNotification(string messageBody) {
        }
    
      }
    
    }
    

    AndroidManifest.xml文件

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.ebelinski.fakename" android:versionName="1.1" android:versionCode="15">
        <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="28" />
        <application android:label="Fake Name">
            <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" />
            <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
                <intent-filter>
                    <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                    <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
                    <category android:name="${applicationId}" />
                </intent-filter>
            </receiver>
        </application>
        <uses-permission android:name="android.permission.WAKE_LOCK" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    </manifest>
    

    AndroidMaifest.xml(在/Droid/obj/Debug/android/中的版本)

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.ebelinski.fakename" android:versionName="1.1" android:versionCode="15">
      <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="28" />
      <permission android:name="com.ebelinski.fakename.permission.C2D_MESSAGE" />
      <uses-permission android:name="com.ebelinski.fakename.permission.C2D_MESSAGE" />
      <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
      <uses-permission android:name="android.permission.GET_ACCOUNTS" />
      <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
      <uses-feature android:name="android.hardware.location.gps" />
      <uses-feature android:name="android.hardware.location.network" />
      <uses-permission android:name="android.permission.WAKE_LOCK" />
      <uses-permission android:name="android.permission.INTERNET" />
      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
      <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
      <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
      <application android:label="Fake Name" android:name="android.support.multidex.MultiDexApplication" android:allowBackup="true" android:icon="@drawable/icon" android:debuggable="true">
        <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" />
        <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
          <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
            <category android:name="com.ebelinski.fakename" />
          </intent-filter>
        </receiver>
        <activity android:configChanges="orientation|screenSize" android:icon="@drawable/icon" android:label="Fake Name" android:launchMode="singleTop" android:theme="@style/CustomTheme" android:name="md501b8064acb9363ced7fe7144b683c1bc.MainActivity">
          <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
        </activity>
        <activity android:configChanges="orientation|screenSize" android:label="Notification Activity" android:name="md501b8064acb9363ced7fe7144b683c1bc.NotificationActivity" />
        <service android:name="md501b8064acb9363ced7fe7144b683c1bc.BackgroundService">
          <intent-filter>
            <action android:name="FakeName.Droid.BackgroundService" />
          </intent-filter>
        </service>
        <service android:name="md501b8064acb9363ced7fe7144b683c1bc.WinterFirebaseIIDService">
          <intent-filter>
            <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
          </intent-filter>
        </service>
        <service android:name="md501b8064acb9363ced7fe7144b683c1bc.WinterFirebaseMessagingService">
          <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
          </intent-filter>
        </service>
        <receiver android:enabled="true" android:exported="false" android:name="md51558244f76c53b6aeda52c8a337f2c37.PowerSaveModeBroadcastReceiver" />
        <provider android:name="mono.MonoRuntimeProvider" android:exported="false" android:initOrder="2147483647" android:authorities="com.ebelinski.fakename.mono.MonoRuntimeProvider.__mono_init__" />
        <!--suppress ExportedReceiver-->
        <receiver android:name="mono.android.Seppuku">
          <intent-filter>
            <action android:name="mono.android.intent.action.SEPPUKU" />
            <category android:name="mono.android.intent.category.SEPPUKU.com.ebelinski.fakename" />
          </intent-filter>
        </receiver>
        <provider android:authorities="com.ebelinski.fakename.firebaseinitprovider" android:name="com.google.firebase.provider.FirebaseInitProvider" android:exported="false" android:initOrder="100" />
        <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" 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.ebelinski.fakename" />
          </intent-filter>
        </receiver>
        <!-- Internal (not exported) receiver used by the app to start its own exported services
                 without risk of being spoofed. -->
        <!-- FirebaseInstanceIdService performs security checks at runtime,
                 no need for explicit permissions despite exported="true" -->
        <service android:name="com.google.firebase.iid.FirebaseInstanceIdService" android:exported="true">
          <intent-filter android:priority="-500">
            <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
          </intent-filter>
        </service>
        <!-- FirebaseMessagingService performs security checks at runtime,
                 no need for explicit permissions despite exported="true" -->
        <service android:name="com.google.firebase.messaging.FirebaseMessagingService" android:exported="true">
          <intent-filter android:priority="-500">
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
          </intent-filter>
        </service>
        <activity android:name="com.google.android.gms.common.api.GoogleApiActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:exported="false" />
        <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
      </application>
      <permission android:name="com.ebelinski.fakename.permission.C2D_MESSAGE" android:protectionLevel="signature" />
      <uses-permission android:name="com.ebelinski.fakename.permission.C2D_MESSAGE" />
    </manifest>
    

    主活动.cs

    using Android.App;
    using Android.Content.PM;
    using Android.OS;
    using System.Globalization;
    using Xamarin;
    using FakeName.Infrastructure;
    using FakeNameDroid.Infrastructure;
    using Android.Content;
    using System;
    using FakeNameMessaging;
    using FakeNameModels;
    using Firebase.Iid;
    using Firebase.Messaging;
    using Firebase;
    
    namespace FakeName.Droid
    {
      [Activity (Label = "FakeName", LaunchMode = LaunchMode.SingleTop, Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation, Theme = "@style/CustomTheme")]
      public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
      {
    
        // This will be set to true in the OnNewIntent method to notify the app should navigate to the notifications page after launching
        private bool navigateToNotifications = false;
    
        // Google API Project Number
        public static MainActivity instance;
    
        protected override void OnCreate (Bundle bundle)
        {
          AppLog.Checkpoint("MainActivity OnCreate");
    
          instance = this;
          base.OnCreate (bundle);
    
          AppLog.Checkpoint("MainActivity Initializing Xamarin Forms");
          global::Xamarin.Forms.Forms.Init (this, bundle);
    
          // Set up the Translation service based on the current culture
          Translate.Initialize (CultureInfo.CurrentCulture.TwoLetterISOLanguageName);
    
          SettingsPageModel.ShowManageNotificationsButton = true;
    
    
          try
          {
            string notificationData = null;
            if(bundle != null) {
              notificationData = bundle.GetString("notification");
            } else {
              notificationData = Intent.GetStringExtra("notification");
            }
    
            if (!string.IsNullOrEmpty(notificationData)) {
              AppLog.Checkpoint("MainActivity Notification Data Present in bundle");
              navigateToNotifications = true;
            } else {
              AppLog.Checkpoint("MainActivity Notification Data not present in bundle");
            }
          }
          catch (Exception ex)
          {
            AppLog.Checkpoint("MainActivity Exception getting notification data OnCreate");
            AppLog.CaptureException ("MainActivity CheckForNotificationData", ex);
          }
    
          FillIoCContainer();
          CreateNotificationChannel();
    
          if (navigateToNotifications) {
            LoadApplication (new App (NavigationDetailPage.Notifications));
            // Reset flag
            navigateToNotifications = false;
          } else {
            LoadApplication (new App ());
          }
    
          // NOTE: I added this even though it didn't say so in the tutorial...it doesn't work with or without it...
          FirebaseApp app = FirebaseApp.InitializeApp(Android.App.Application.Context);
        }
    
        protected override void OnResume ()
        {
          base.OnResume();
    
          AppLog.Checkpoint("MainActivity OnResume");
    
          // NOTE: This is where the app crashes. It crashes even if I move this line to OnCreate.
          Console.Out.WriteLine("MainActivity InstanceID token: " + FirebaseInstanceId.Instance.Token);
    
          if (navigateToNotifications) {
            AppLog.Checkpoint("MainActivity Navigating to notifications");
            GalaSoft.MvvmLight.Messaging.Messenger.Default.Send (new NavigationMessageEvent (NavigationDetailPage.Notifications));
            navigateToNotifications = false; // reset the value
          }
        }
    
        /* 
         * The intent that calls MainActivity from a notification is actually a different intent than the one we built and won't 
         * have the extra data we put in it. This method 'OnNewIntent' catches our intent that was tied to that notification so
         * we can get the extra data we put in it when the user click it.
         */
        protected override void OnNewIntent(Intent intent)
        {
          base.OnNewIntent(intent);
          AppLog.Checkpoint("MainActivity OnNewIntent called");
    
          try
          {
            var notificationData = intent.GetStringExtra("notification");
            if (!string.IsNullOrEmpty(notificationData)) {
              AppLog.Checkpoint("MainActivity Notification Data Present");
              navigateToNotifications = true;
            }
          }
          catch (Exception ex)
          {
            AppLog.Checkpoint("MainActivity Exception getting notification ");
            AppLog.CaptureException ("CheckForNotificationData", ex);
          }
        }
    
        private void CreateNotificationChannel() {
          if (Build.VERSION.SdkInt >= BuildVersionCodes.O) {
            string name = "Snow emergency notifications";
            string description = "This notification channel contains snow emergency notifications.";
            NotificationImportance importance = NotificationImportance.Max;
            string channelID = AppConstants.NOTIFICATION_CHANNEL_SNOW_EMERGENCIES_ID;
    
            NotificationChannel channel = new NotificationChannel(channelID, name, importance);
            channel.Description = description;
    
            NotificationManager notificationManager = (NotificationManager) GetSystemService(NotificationService);
            notificationManager.CreateNotificationChannel(channel);
          }
        }
    
        public void FillIoCContainer ()
        {
          AppLog.Checkpoint("MainActivity Filling IoC");
          IoCContainer.Instance.AddInstance<INetworkConnectionMonitor> (new NetworkConnectionMonitor ());
        }
      }
    }
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   Eugene    6 年前

    事实证明,发生这种情况的原因是因为我的Android项目中的应用程序包名和google-services.json文件中的应用程序包名略有不同,而实际上它们应该是相同的。