当前位置: 首页 > 知识库问答 >
问题:

应用程序有时会崩溃“后台启动不允许:服务意图”

沈骞仕
2023-03-14

我只兼职做Android开发(考虑到API的许多细微之处和低级水平,这似乎很有挑战性),并且在我的应用程序处于后台时接收通知有问题。我的目标是Android8.1。我的应用程序碰巧使用了Azure和Xamarin,但我不知道这些细节是否是问题所固有的。

如果我的应用程序在后台,有时会显示通知,但其他时候我的应用程序会因以下错误而崩溃:

2019-03-06 09:12:24.486 9495-9702/? D/tyresense.azurelistenerservice: OnMessage() done
2019-03-06 09:12:28.278 1548-3232/? W/ActivityManager: Background start not allowed: service Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x1000010 pkg=com.rimex.tyresense cmp=com.rimex.tyresense/md5bf34da605c12d097dc5a495af95e9376.AzureListenerService (has extras) } to com.rimex.tyresense/md5bf34da605c12d097dc5a495af95e9376.AzureListenerService from pid=9495 uid=10173 pkg=com.rimex.tyresense
2019-03-06 09:12:28.341 9495-9495/? I/MonoDroid: Java.Lang.IllegalStateException: Not allowed to start service Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x1000010 pkg=com.rimex.tyresense cmp=com.rimex.tyresense/md5bf34da605c12d097dc5a495af95e9376.AzureListenerService (has extras) }: app is in background uid UidRecord{d582ba5 u0a173 RCVR bg:+1m0s848ms idle procs:1 seq(0,0,0)}
2019-03-06 09:12:28.342 9495-9495/? I/MonoDroid: java.lang.IllegalStateException: Not allowed to start service Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x1000010 pkg=com.rimex.tyresense cmp=com.rimex.tyresense/md5bf34da605c12d097dc5a495af95e9376.AzureListenerService (has extras) }: app is in background uid UidRecord{d582ba5 u0a173 RCVR bg:+1m0s848ms idle procs:1 seq(0,0,0)}
2019-03-06 09:12:28.347 9495-9495/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.rimex.tyresense, PID: 9495
    java.lang.RuntimeException: Unable to start receiver md5bf34da605c12d097dc5a495af95e9376.TyreSenseBroadcastReceiver: java.lang.IllegalStateException: Not allowed to start service Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x1000010 pkg=com.rimex.tyresense cmp=com.rimex.tyresense/md5bf34da605c12d097dc5a495af95e9376.AzureListenerService (has extras) }: app is in background uid UidRecord{d582ba5 u0a173 RCVR bg:+1m0s848ms idle procs:1 seq(0,0,0)}
        at android.app.ActivityThread.handleReceiver(ActivityThread.java:3285)
        at android.app.ActivityThread.-wrap17(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1713)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6626)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:811)
     Caused by: java.lang.IllegalStateException: Not allowed to start service Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x1000010 pkg=com.rimex.tyresense cmp=com.rimex.tyresense/md5bf34da605c12d097dc5a495af95e9376.AzureListenerService (has extras) }: app is in background uid UidRecord{d582ba5 u0a173 RCVR bg:+1m0s848ms idle procs:1 seq(0,0,0)}
        at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1536)
        at android.app.ContextImpl.startService(ContextImpl.java:1492)
        at android.content.ContextWrapper.startService(ContextWrapper.java:650)
        at android.content.ContextWrapper.startService(ContextWrapper.java:650)
        at md513d040a829b3f298fbeeee5a6e2c042a.GcmBroadcastReceiverBase_1.n_onReceive(Native Method)
        at md513d040a829b3f298fbeeee5a6e2c042a.GcmBroadcastReceiverBase_1.onReceive(GcmBroadcastReceiverBase_1.java:29)
        at android.app.ActivityThread.handleReceiver(ActivityThread.java:3278)
        at android.app.ActivityThread.-wrap17(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1713) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:164) 
        at android.app.ActivityThread.main(ActivityThread.java:6626) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:811) 
2019-03-06 09:12:28.348 2761-2761/? W/GCM: broadcast intent callback: result=CANCELLED forIntent { act=com.google.android.c2dm.intent.RECEIVE pkg=com.rimex.tyresense (has extras) }
2019-03-06 09:12:28.353 9495-9495/? E/tyresense.splashscreen: System.UnhandledExceptionEventArgs
2019-03-06 09:12:28.357 1548-7265/? W/ActivityManager:   Force finishing activity com.rimex.tyresense/md5bf34da605c12d097dc5a495af95e9376.MainActivity
2019-03-06 09:12:28.363 1548-1632/? I/ActivityManager: Showing crash dialog for package com.rimex.tyresense u0

我看到这样的文章:https://blog.xamarin.com/replacing-services-jobs-android-oreo-8-0/

但我不清楚到底是什么问题,所以我不知道这是否能解决它。

using System;
using System.Collections.Generic;
using Android.App;
using Android.Content;
using Android.Util;
using Gcm.Client;
using WindowsAzure.Messaging;
using SharedMobile; // keep it simple, the app might not be running
using MyApp.Android; // we need to reference ourselves...
using Android.Support.V4.App;
using Android.Content.PM;
using System.Threading.Tasks;

[assembly: Permission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "com.google.android.c2dm.permission.RECEIVE")]
[assembly: Xamarin.Forms.Dependency(typeof(DependencyListener))]
namespace MyApp.Android
{
    [BroadcastReceiver(Permission = Constants.PERMISSION_GCM_INTENTS)]
    [IntentFilter(new string[] { Constants.INTENT_FROM_GCM_MESSAGE }, Categories = new string[] { "@PACKAGE_NAME@" })]
    [IntentFilter(new string[] { Constants.INTENT_FROM_GCM_REGISTRATION_CALLBACK }, Categories = new string[] { "@PACKAGE_NAME@" })]
    [IntentFilter(new string[] { Constants.INTENT_FROM_GCM_LIBRARY_RETRY }, Categories = new string[] { "@PACKAGE_NAME@" })]
    public class MyAppBroadcastReceiver : GcmBroadcastReceiverBase<AzureListenerService>
    {
        // this declaration somehow enables messages
    }

    [Service]
    public class AzureListenerService : GcmServiceBase // this service might be started at system boot, when the app is otherwise not active
    {
        const string TAG = "MyApp.azurelistenerservice";
        const string HUBNAME = "myhubname";
        const string CONNECTION =
               "Endpoint=sb://MyApp.servicebus.windows.net/;SharedAccessKeyName=DefaultListenSharedAccessSignature;SharedAccessKey=secretstuff...";

        public const string GcmProjectNumber = "1234567890";
        private static NotificationHub noteHub = null;

        public AzureListenerService() : base(GcmProjectNumber)
        {
        }

        // need client and area ids before this is called. Application.Context is not available if called from system boot
        public static void InitializeAzure(Context context = null)
        {
            try
            {
                if (context == null)
                    context = Application.Context;
                var enabled = NotificationManagerCompat.From(context).AreNotificationsEnabled();
                SharedMobile.API.ApiService.Instance.NotificationsEnabled(enabled);
                if (enabled)
                {
                    GcmClient.CheckDevice(context);
                    GcmClient.CheckManifest(context);
                    GcmClient.Register(context, GcmProjectNumber);
                }
            }
            catch (Exception ex)
            {
                Log.Error(TAG, ex.Message);
                Messenger.SendException(ex.Message);
            }
        }

        // incoming GCM registration
        protected override void OnRegistered(Context context, string token)
        {
            try
            {
                noteHub = new NotificationHub(HUBNAME, CONNECTION, context);
                var customerId = Int32.Parse(PropertyHelper.ClientId);
                var tags = BuildTagList(customerId, PropertyHelper.AreaIds);
                noteHub.Register(token, tags.ToArray());
                Messenger.RegisterDevice(token);
            }
            catch (Exception ex)
            {
                Log.Error(TAG, "OnRegistered() " + ex.Message); // ignore register failure when using the Android emulator
            }
        }

        protected override void OnMessage(Context context, Intent intent)
        {
            try
            {
                var areaIds = PropertyHelper.AreaIds;
                if (string.IsNullOrWhiteSpace(areaIds)) // in case the user logged out
                    return;
                new Notifications().CreateEventNotification(intent);
            }
            catch (Exception ex)
            {
                Log.Error(TAG, "OnMessage() " + ex.Message);
            }
        }

        protected List<string> BuildTagList(int clientId, string areaIds)
        {
            var list = new List<string>();
            list.Add($"client_{clientId}");
            foreach (var id in areaIds.Split(','))
                list.Add($"area_{id}");
            return list;
        }

        protected override void OnUnRegistered(Context context, string registrationId)
        {
            Log.Error(TAG, "OnUnRegistered(): " + registrationId);
        }

        protected override bool OnRecoverableError(Context context, string errorId)
        {
            Log.Error(TAG, "OnRecoverableError(): " + errorId);
            return base.OnRecoverableError(context, errorId);
        }

        protected override void OnError(Context context, string errorId)
        {
            Log.Error(TAG, "OnError(): " + errorId);
        }
    }
}


using System;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Support.V4.App;
using Android.Support.V4.Content;
using Android.Util;
using Exception = System.Exception;

namespace My.Android
{
    internal class Notifications
    {
        const string TAG = "My.notifications";
        const string TITLE = "Application is running";
        const string DESC = "Tap to view";
        const int MainProgramNotificationId = 775566;

        // unique ID for our notification: 
        static readonly string CHANNEL_ID = "My_channel_23";
        static readonly string CHANNEL_NAME = "[My_channel]";

        internal void CreateProgramIcon_on_hold(Intent intent)
        {
            var extras = new Bundle();
            extras.PutString("scopeDescription", TITLE);
            extras.PutString("stateDescription", DESC);
            intent.PutExtras(extras);

            ShowNotification(intent.Extras, false);
        }

        internal void CreateEventNotification(Intent extra)
        {
            if (extra.Extras != null && !extra.Extras.IsEmpty)
                ShowNotification(extra.Extras, true);

            var notificationId = extra?.Extras?.GetString("notification-id", null);
            if (notificationId != null && notificationId.Length > 0)
                SharedMobile.API.ApiService.NotificationConfirmation(notificationId);
        }

        private void ShowNotification(Bundle extras, bool autoCancel)
        {
            try
            {
                string title = TITLE; 
                string description = DESC;
                if (extras != null && !extras.IsEmpty)
                {
                    title = extras.GetString("scopeDescription", null);
                    description = extras.GetString("stateDescription", "");
                }

                Intent intent = new Intent(Application.Context, typeof(SplashScreen));
                BuildNotification(intent, extras, title, description, autoCancel);

            }
            catch (Exception ex)
            {
                Log.Debug(TAG, ex.Message);
            }
        }

        private void BuildNotification(Intent intent, Bundle extras, string title, string description, bool autoCancel)
        {
            bool onGoing = !autoCancel;
            int icon = IconId(null, null); // code not shown
            intent.AddFlags(ActivityFlags.ReorderToFront);
            var pendingIntent = PendingIntent.GetActivity(Application.Context, 0, intent, PendingIntentFlags.UpdateCurrent);

            CreateNotificationChannel(autoCancel);

            var notificationManager = Application.Context.GetSystemService(Context.NotificationService) as NotificationManager;
            NotificationCompat.Builder builder = new NotificationCompat.Builder(Application.Context, CHANNEL_ID);

            builder.SetSmallIcon(icon)
                .SetContentTitle(title)
                .SetContentText(description)
                .SetSmallIcon(Resource.Drawable.notification_icon)
                .SetAutoCancel(autoCancel)
                .SetOngoing(onGoing)
                .SetContentIntent(pendingIntent);

            if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
                builder.SetColor(ContextCompat.GetColor(Application.Context, Resource.Color.exBackgroundColor));

            string utcTicks = null;
            if (extras != null)
                utcTicks = extras.GetString("utcTicks", null);
            if (utcTicks != null)
            {
                var ticks = Int64.Parse(utcTicks);
                DateTimeOffset dto = new DateTimeOffset(ticks, TimeSpan.Zero);
                builder.SetWhen(dto.ToUnixTimeMilliseconds());
            }
            else
                builder.SetShowWhen(true);

            notificationManager?.Notify(MainProgramNotificationId, builder.Build());
        }

        private void CreateNotificationChannel(bool evnt)
        {
            if (Build.VERSION.SdkInt < BuildVersionCodes.O)
            {
                // There is no need to create a notification channel on older versions of Android.
                return;
            }
            NotificationImportance ni;
            if (evnt)
                ni = NotificationImportance.Default;
            else
                ni = NotificationImportance.Low;
            var channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, ni)
            {
                Description = "My App",
                LockscreenVisibility = NotificationVisibility.Private,
            };
            var notificationManager = Application.Context.GetSystemService(Context.NotificationService) as NotificationManager;
            notificationManager.CreateNotificationChannel(channel);
        }

        string FormatTimeStamp(string utcTicks)
        {
            try
            {
                var ticks = Int64.Parse(utcTicks);
                DateTimeOffset dto = new DateTimeOffset(ticks, TimeSpan.Zero);
                return dto.ToLocalTime().ToString("MM/dd HH:mm:ss");
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

        bool IgnoreActionProcess(string actionProcessId, int ackedProcessId)
        {
            try
            {
                if (int.Parse(actionProcessId) == ackedProcessId)
                    return true;
            }
            catch (Exception ex)
            {
                Log.Debug(TAG, $"int parse: {actionProcessId} {ex.Message}");
            }
            return false;
        }

    }
}

未处理的异常:java.lang.IllegalStateException:不允许启动服务意图{act=com.google.android.c2dm.Intent.receive flg=0x1000010 pkg=com.mycompany.myapp cmp=com.mycompany.myapp/md5bf34da605c12d097dc5a495af95e9376.azureListenerservice(havs extras)}:app在后台uid UidRecord{d45626f u0a173 RCVR bg:+1m29s589ms空闲更改:未

更新我实现了JobScheduler,这没有什么不同。此外,应用程序必须在后台“一段时间”,然后问题总是会发生。我还改变了我的应用程序,当通知到达时,它什么也不做(但日志),但它仍然崩溃。

更新:https://developer.xamarin.com/samples/monodroid/firebase/fcmnotifications/通过将其“按原样”添加到我的firebase帐户,下载google-services.json,并使用http://pushtry.com/进行测试来实现。Azure门户测试发送还没有运气。希望将FCMNotifications的代码合并到我的应用程序中,如果我能让Azure工作...

共有1个答案

鄢承运
2023-03-14

Android 8.0(API level 26)及以上版本对后台服务有限制。它包括对具体方法的以下更改:

如果一个针对Android8.0的应用程序在不允许创建后台服务的情况下试图使用该方法,startService()方法将抛出一个IllegalStateException。新的context.startForegroundService()方法启动前台服务。该系统允许应用程序调用context.startForegroundService(),即使应用程序处于后台。但是,应用程序必须在服务创建后五秒钟内调用该服务的startForeground()方法。

 类似资料:
  • 据报道,像素设备的Android 11出现了以下崩溃。 致命异常:java.lang.RuntimeException无法启动活动ComponentInfo{}:java.lang.IllegalStateException:不允许启动服务意图{}:应用程序在后台uid UidRecord{} 这只发生在Android 11设备上。谷歌Android 11的服务实现有重大变化吗?

  • 问题是,当我在Google中使用授权运行此代码时,它会立即崩溃: 但是日志中的错误: 2019-06-22 17:55:42.652 29327-23222/?E/AudioSource:在已关闭的AudioSource 2019-06-22 17:55:43.240 2093-2616/?E/TouchFilter:setTouchFilter日志启用参数:0 2019-06-22 17:55:

  • 在调用(和)之后,我的应用程序怎么可能就在后台呢? 这对我来说没有任何意义。这可能是平台错误吗?受这次崩溃影响的所有3500+用户都在Android P上。

  • 问题内容: 我目前正在使用在Oreo中崩溃的startWakefulService函数。我意识到我要么必须切换到startForegroundService()并使用前台服务,要么切换到JobIntentService,但是基于下面的代码,我不确定该怎么做。(对不起,我是android新手)。正确方向的任何观点将不胜感激。 这是在Android 8.x上运行时遇到的当前错误 致命异常:java.l

  • 这是在Android8.x上运行时出现的当前错误 致命异常:java.lang.RuntimeException无法启动接收方com.heyjude.heyjudeapp.gcm.gcmbroadcastreceiver:java.lang.illegalstateException:不允许启动服务意图{act=com.google.android.c2dm.Intent.receive flg=

  • 我开发的应用程序在使用Android Studio进行测试时效果很好。但是在谷歌Play商店发布后遇到了问题。 该应用程序具有多个页面。其中一个页面使用Unity启动AR图像跟踪功能,只需单击一个按钮即可。从Android Studio将应用程序添加到我的手机时完全没有问题,一切正常。但是,当从谷歌Play商店下载时,当单击按钮启动unity时,它会立即崩溃。 我是一个新的Android开发者。任