Java Android Oreo+中的AlarmManager和广播接收器;

Java Android Oreo+中的AlarmManager和广播接收器;,java,android,android-studio,broadcastreceiver,alarmmanager,Java,Android,Android Studio,Broadcastreceiver,Alarmmanager,我正在制作一个应用程序,在一天中的特定时间通知用户。就像闹钟一样。该代码在Android Oreo之前的版本中正常工作 据我所知,Android Oreo和更高版本会在后台杀死操作,这就是为什么我会出现下面的错误 2020-07-13 20:31:06.766 1609-1737/? W/BroadcastQueue: Background execution not allowed: receiving Intent { act=android.intent.action.PACKAGE_RE

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

据我所知,Android Oreo和更高版本会在后台杀死操作,这就是为什么我会出现下面的错误

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没有在应该触发的时候触发一样。但当我打开应用程序时,它会立即启动

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>


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

Android有一种打盹模式,在这种模式下,它会在一些不活动后进入睡眠状态,即使你在某些手机上成功做到这一点,中国的ROM肯定会给你带来麻烦(其中,从最近的应用程序中删除作为强制停止应用程序)

对于您的问题,有一些解决方案,如Work manager、Foreground Services、jobscheduler,它应该可以工作,但也不能说适用于所有ROM。我认为目前还没有一个合适的解决方案来解决此后台处理

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

你可以看到Facebook和whatsapp可以在后台工作,因为它们被公司列入了白名单。你可以通过启用自动启动设置来将你的应用程序列入白名单。但你需要手动操作,这在我们谈论fb和whatsapp时不是这样的

有关更多详细信息,请访问此网站:

在这个问题上,受影响最大的是闹钟、健康追踪器、自动化应用程序、日历,或者任何在你不使用手机的特定时刻需要为你做些工作的东西

在安卓6(棉花糖)上,谷歌在基础安卓系统中引入了打瞌睡模式,试图统一各种安卓手机的电池节约


不幸的是,一些制造商(如小米、华为、OnePlus甚至三星……)似乎没有抓住这个球,他们都有自己的电池节省器,通常写得很糟糕,只是表面上节省了电池,但有副作用。

从Android oreo开始,不再支持任何后台服务。开发人员文档中的建议是使用前台服务。要保持前台服务运行ice时,您需要将其与通知连接起来。您可以将通知配置为在UI中隐藏或不可见

在主要活动onCreate中

    if (!isMyServiceRunning(ForegroundService.class)) {

        BroadcastReceiver br = new GPSBroadcastReceiver();
        IntentFilter filter = new IntentFilter(CONNECTIVITY_ACTION);
        filter.addAction(Intent.ACTION_BOOT_COMPLETED);

        getApplicationContext().registerReceiver(br, filter);
}
正在检查服务是否正在运行

    private boolean isMyServiceRunning(Class<?> serviceClass) {
    ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (serviceClass.getName().equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}
private boolean IsMyService正在运行(类serviceClass){
ActivityManager=(ActivityManager)getSystemService(Context.ACTIVITY_服务);
对于(ActivityManager.RunningServiceInfo服务:manager.getRunningServices(Integer.MAX_值)){
if(serviceClass.getName().equals(service.service.getClassName())){
返回true;
}
}
返回false;
}
下面是我的一个项目的一个例子。前台服务是一个不错的选择

一些有用的资料来源


如果您正在编写时钟应用程序,请使用。即使系统处于低功耗空闲(也称为打瞌睡)模式,也允许触发。设置闹钟时,用户可以看到它。SystemUI可能会显示不同的图标或警报


如果你只是想在某个特定的时间被触发来做一些工作,没有好的方法可以逃脱后台限制。

即使用户关闭应用程序,这项服务还会继续运行吗?有时我会尝试想象Android自己的闹钟使用了什么。允许系统应用程序运行后台服务。但一天也不能ird party。是的,即使应用程序关闭,此程序也会运行。我可以按您的喜好共享工作示例。您看到通知面板上的最小化通知了吗?这就是原因。您说我可以隐藏服务通知。但无论我在何处搜索如何隐藏它,我都发现它不可能隐藏。您能告诉我它是如何隐藏的吗应该隐藏通知用户应用程序正在运行服务的通知吗?不完全隐藏只是最小化每个android开发者的文档。遗憾的是,一些与服务器通知相关的答案对我来说不是一个选项。我需要通知用户,即使他没有互联网。你能想象android clock用于在特定时间通知用户?您正在谈论的应用程序是一个系统应用程序,用户可以随意使用。此外,您可以看到Facebook和whatsapp可以在后台工作,因为它们被公司列入白名单。您可以通过启用“自动启动设置”将应用程序列入白名单。但您需要这样做当我们谈论fb和WhatsApp时,手动操作并非如此。有关更多详细信息,请查看本网站:
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    context = this;


    String input = intent.getStringExtra("inputExtra");
    createNotificationChannel();


    Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
            .setSmallIcon(R.mipmap.ic_launcher)

            .setContentTitle("GPS Service")

            .setContentText("GPS Service")
//                .setLargeIcon(emailObject.getSenderAvatar())
            .setStyle(new NotificationCompat.BigTextStyle()
                    .bigText("Ready\nAndroi " + android.os.Build.VERSION.SDK_INT))
            .setPriority(Notification.PRIORITY_HIGH)
            .setOngoing(true)
            .build();

    startForeground(1, notification);
    getLocation();

    //do heavy work on a background thread


    locationModel = new LocationModel("", "", "", "", "");

    LongOperation longOperation = new LongOperation();
    longOperation.execute();


    //stopSelf();

    return START_STICKY;
}
    if (!isMyServiceRunning(ForegroundService.class)) {

        BroadcastReceiver br = new GPSBroadcastReceiver();
        IntentFilter filter = new IntentFilter(CONNECTIVITY_ACTION);
        filter.addAction(Intent.ACTION_BOOT_COMPLETED);

        getApplicationContext().registerReceiver(br, filter);
}
    private boolean isMyServiceRunning(Class<?> serviceClass) {
    ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (serviceClass.getName().equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}