Android Oreo +中的AlarmManager和BroadcastReceiver [英] AlarmManager and BroadcastReceiver in Android Oreo+

查看:93
本文介绍了Android Oreo +中的AlarmManager和BroadcastReceiver的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一个可在一天的特定时间通知用户的应用程序。就像闹钟一样。该代码可在Android Oreo之前的版本中正常运行。

I am making an application that notifies the user at certain times of the day. Like an alarm clock. The code works normally in versions prior to Android Oreo.

据我了解,Android Oreo及更高版本会在后台终止动作,这就是为什么我在下面出现错误。

From what I read, Android Oreo and later versions kill actions in the background and that's why I'm having the error below.

2020-07-13 20:31:06.766 1609-1737/? W/BroadcastQueue: Background execution not allowed: receiving Intent { act=android.intent.action.PACKAGE_REPLACED dat=package:studio.com.archeagemanager flg=0x4000010 (has extras) } to air.br.com.alelo.mobile.android/co.acoustic.mobile.push.sdk.wi.AlarmReceiver

就好像在以下情况下不会触发BroadcastService它应该是。但是,当我打开该应用程序时,它会立即启动。

It is as if the BroadcastService is simply not triggered when it should be. But when I open the app, it starts up instantly.

AndroidManifest.xml

<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="owner.custom.permission" />
<permission
    android:name="owner.custom.permission"
    android:protectionLevel="signatureOrSystem">
</permission>

<meta-data
    android:name="com.google.android.gms.version"
    android:value="@integer/google_play_services_version" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/app_icon_new"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity
        android:name=".SplashScreenActivity"
        android:theme="@style/AppCompat.TelaCheia">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:screenOrientation="portrait"
        android:theme="@style/AppTheme.NoActionBar">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>

    <receiver
        android:name=".AlarmReceiver"
        android:enabled="true"
        android:exported="false">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

</application>

TabFragEventA.java (这里,我只放置了启动警报的函数)

TabFragEventA.java (Here I put only the function that initiates the alarm)

public void startAlarm(int eventID) {
    String[] NOTIFICATION_TITLES = {"Ocleera Rift", "Ocleera Rift", "Mistmerrow Conflict", "Mistmerrow Conflict",
            "Mistmerrow Conflict", "Nation Construction Quests", "Diamond Shores", "Diamond Shores", "Battle of the Golden Plains",
            "Battle of the Golden Plains", "Karkasse Ridgelands", "Kraken", "The Mirage Isle Fish Fest", "Red Dragon",
            "Abyssal Attack", "Lusca Awakening", "Delphinad Ghostship", "Cattler Wrangler", "Legendary Chef", "+1"};

    String notificationTitle = getString(R.string.contentTitle);
    String notificationText = NOTIFICATION_TITLES[eventID] + getString(R.string.contentNotificationText);

    int alarmHour = localHour.get(eventID);
    int alarmMinute = localMinute.get(eventID);
    // Decrease 5 minutes
    if(alarmMinute == 0) {
        alarmHour = alarmHour - 1;
        alarmMinute = 55;
    } else {
        alarmMinute = alarmMinute - 5;
    }
    // Setting the alarm moment
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.set(Calendar.HOUR_OF_DAY, alarmHour);
    calendar.set(Calendar.MINUTE, alarmMinute);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);
    // Analyze if the alarm moment has passed
    Calendar actualTime = Calendar.getInstance();
    if(actualTime.getTimeInMillis() >= calendar.getTimeInMillis()) {
        calendar.add(Calendar.DAY_OF_MONTH, 1);
    }

    Intent intent = new Intent(getActivity().getApplicationContext(), AlarmReceiver.class);
    intent.putExtra("contentTitle", notificationTitle);
    intent.putExtra("contentText", notificationText);
    /*if(eventID == 11 || eventID == 13) {
        intent.putExtra("specificDayWeek", true);
    } else {
        intent.putExtra("specificDayWeek", false);
    }*/
    if(eventID == 12) {
        intent.putExtra("castleSupply", true);
        intent.putIntegerArrayListExtra("castleSupplyDayWeek", (ArrayList<Integer>) CastleSupply);
    }
    else if(eventID == 13) {
        intent.putExtra("castleClaim", true);
        intent.putIntegerArrayListExtra("castleClaimDayWeek", (ArrayList<Integer>) CastleClaim);
    }
    else if(eventID == 14) {
        intent.putExtra("abyssalAttack", true);
        intent.putIntegerArrayListExtra("abyssalDaysWeek", (ArrayList<Integer>) AbyssalDayWeek);
    }
    else if(eventID == 15) {
        intent.putExtra("luscaAwakening", true);
        intent.putIntegerArrayListExtra("luscaAwakeningDayWeek", (ArrayList<Integer>) LuscaAwakening);
    } else {
        intent.putExtra("abyssalAttack", false);
    }

    intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
    // PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity().getApplicationContext(), eventID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity().getApplicationContext(), eventID, intent, 0);
    AlarmManager alarmManager = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE);
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
}

AlarmReceiver.java

public class AlarmReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        String contentTitle = intent.getStringExtra("contentTitle");
        String contentText = intent.getStringExtra("contentText");

        String CHANNEL_ID = "my_channel_01";
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence name = "Channel Name";
            int importance = NotificationManager.IMPORTANCE_HIGH;
            NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, importance);
            notificationManager.createNotificationChannel(mChannel);
        }

        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, CHANNEL_ID)
                .setSmallIcon(R.drawable.icon_notification)
                .setContentTitle(contentTitle)
                .setContentText(contentText)
                .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.icon_notification))
                .setContentIntent(pendingIntent)
                .setAutoCancel(true)
                .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
                .setVibrate(new long[]{800, 500, 600, 300});

        notificationManager.notify(0, notificationBuilder.build());

        Log.d("ALARMRECEIVER", "INSIDE");

    }
}

我想知道如何使广播接收器在后台工作。或者,也可以在Android Oreo +上设置此闹钟,以便即使应用程序关闭或在后台也可以通知用户。

I would like to know what to do to make the Broadcast Receiver work in the background. Or an alternative to set this alarm clock on Android Oreo + so that it notifies the user even with the application closed or in the background.

推荐答案

Android具有打a模式,在这种模式下,一些不活动后会进入睡眠状态,即使您设法在某些手机上做到这一点,中文ROM也肯定会给您带来麻烦(在这种情况下,从最新应用中删除会强制停止应用程序运行)

Android has a doze mode in which it goes to sleep after some inactivity, Even if you manage to do this on some phones chinese ROMs will trouble you for sure ( in which removing from recent apps works as force stopping application)

对于您的问题,有一些解决方案,例如工作管理器,Foregroundservices,jobscheduler,它应该可以工作,但不能对所有ROM都说。我认为目前没有适当的解决方案来处理这种后台处理。

For your problem there are solutions Like Work manager , Foregroundservices ,jobscheduler it should work but again can't say for all the ROMs. I think right now there isn't a proper solution to this background processing.

但是您可以做的一件事就是从服务器发送具有高优先级的FCM通知。

But One thing you can do is sending a FCM notification from server with high priority.

您可以看到Facebook和whatsapp可以在后台运行,因为它们已被公司列入白名单。您可以通过从设置中启用自动启动功能来将应用程序列入白名单。但是您需要手动执行此操作,这在我们谈论fb和whatsapp时不会出现

You can see that Facebook and whatsapp can work in background because they are whitelisted by the companies. You can whitelist your application by enabling auto start from settings.But you need to do it manually which isnt a case when we talk about fb and whatsapp

查看此网站以获取更多详细信息: https://dontkillmyapp.com/

Check this website for more details : https://dontkillmyapp.com/

受此问题影响最大的是闹钟,健康跟踪器,自动化应用程序,日历或只是在不使用手机的特定时刻需要为您完成某些工作的任何事物。

With this issue Most affected are alarm clocks, health trackers, automation apps, calendars or simply anything which needs to do some job for you at a particular moment when you don’t use your phone.

使用Android 6(棉花糖),谷歌已经在基本的Android系统中引入了Doze模式,以期在各种Android手机上统一节省电池。

With Android 6 (Marshmallow), Google has introduced Doze mode to the base Android, in an attempt to unify battery saving across the various Android phones.

不幸的是,一些制造商(例如小米,华为,OnePlus甚至三星)。 )似乎没有接住球,而且他们都有自己的电池保护程序,通常写得很差,仅在表面上节省了电池的副作用。

Unfortunately, some manufacturers (e.g. Xiaomi, Huawei, OnePlus or even Samsung..) did not seem to catch that ball and they all have their own battery savers, usually very poorly written, saving battery only superficially with side effects.

这篇关于Android Oreo +中的AlarmManager和BroadcastReceiver的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆