Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/219.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 7,8和Oxygen操作系统:应用程序关闭时广播接收器不工作_Android_Broadcastreceiver_Alarmmanager - Fatal编程技术网

Android 7,8和Oxygen操作系统:应用程序关闭时广播接收器不工作

Android 7,8和Oxygen操作系统:应用程序关闭时广播接收器不工作,android,broadcastreceiver,alarmmanager,Android,Broadcastreceiver,Alarmmanager,在Android 7之后,如果应用程序从最近的任务列表中被关闭,则我的报警接收器不会接收广播接收器。 下面是我的AlarmReceiver中的一段,它扩展了BroadCastReceiver public class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.d(Constants.T

在Android 7之后,如果应用程序从最近的任务列表中被关闭,则我的报警接收器不会接收广播接收器。
下面是我的AlarmReceiver中的一段,它扩展了BroadCastReceiver

public class AlarmReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(Constants.TAG, "event received");
        setContext(context);

        /* 
        *** My logic here *** 
        */

        Log.d(Constants.TAG, "alarm received");
    }
}
设置报警并注册报警的AlarmReceiver类的位置

public class UnityNotificationManager
{
    public static void SetNotification(int id, long delayMs, String title, String message, String ticker, int sound, int vibrate,
                                       int lights, String largeIconResource, String smallIconResource, int bgColor, String bundle, String dataString)
    {
        Context currentActivity = UnityPlayer.currentActivity;
        AlarmManager am = (AlarmManager)currentActivity.getSystemService(Context.ALARM_SERVICE);

        Intent intent = new Intent(Constants.ALARM_RECEIVER);
        intent.setClass(currentActivity, AlarmReceiver.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);

        intent.putExtra("ticker", ticker);
        intent.putExtra("title", title);
        intent.putExtra("message", message);
        intent.putExtra("id", id);
        intent.putExtra("color", bgColor);
        intent.putExtra("sound", sound == 1);
        intent.putExtra("vibrate", vibrate == 1);
        intent.putExtra("lights", lights == 1);
        intent.putExtra("l_icon", largeIconResource);
        intent.putExtra("s_icon", smallIconResource);
        intent.putExtra("bundle", bundle);
        intent.putExtra("dataString", dataString);

        PendingIntent pendingIntent = PendingIntent.getBroadcast(currentActivity,
                id, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);

        am.cancel(pendingIntent);

        long finalTime = System.currentTimeMillis() + delayMs;

        if (Build.VERSION.SDK_INT < 23) {
            am.set(AlarmManager.RTC_WAKEUP,finalTime, pendingIntent);
        } else {
            am.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,finalTime, pendingIntent);
        }
        Log.d(Constants.TAG, "event fired finalTime = "+ finalTime);
    }
}
使用显式广播的原因是android文档声明,在android Oreo之后,android应用程序将无法在后台使用隐式广播来提高性能。相同的链接:

我还尝试使用WakefulBroadCastReceiver来避免在android设备上使用Doze模式进行优化,但结果表明,android Oreo中已经不推荐使用该类。相同的链接:

除了运行在oxygen os上的One Plus设备外,上述代码几乎适用于所有其他制造商。如果应用程序以同样的方式被终止,WhatsApp等应用程序的通知将继续工作,那么有没有办法解决这个问题

其他信息:
1.我在One+5T上运行命令
adb shell dumpsys package | grep stopped
,它返回以下输出:

User 0: ceDataInode=2039857 installed=true hidden=false suspended=false stopped=false notLaunched=false enabled=0 instant=false
这反过来表明,在从“最近的任务”列表中刷取应用程序时,不会停止该应用程序。此外,应用程序信息页面上的“强制停止”按钮已启用,表明应用程序尚未强制停止

  • 如果我手动将电池优化设置从“优化”更改为“未优化”,我可以使通知工作,但由于其他应用程序的通知即使在处于优化状态时也能工作,因此我不认为这是解决我问题的方法
  • 有人能建议一些修复或解决方法来修复在氧气操作系统上运行Android 7或更高版本的设备上的通知问题吗

    是的,我还发现很难获得参考示例代码,因为从8.0开始,对始终运行的任务有限制


    不要像这样在
    Manifest.xml
    中放置任何
    意图操作

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
    <uses-permission android:name="android.permission.SEND_SMS" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.WRITE_SMS" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    
    
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
    
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    
        <receiver
            android:name=".Receiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
    
        <service
            android:name=".CatchNumbers"
            android:enabled="true"
            android:exported="true" />
        <service
            android:name=".WatchMan"
            android:enabled="true"
            android:exported="true" >
    
        </service>
    
        <activity android:name=".developer_activity" />
        <activity android:name=".WhiteListActivity" />
        <activity android:name=".Contacts" />
    </application>
    
    请注意,Watchman.java是前台服务,它注册运行时接收器,如果您不使用此方法,它将永远不会工作。我已经尝试了很多并且发明了这是唯一的方法


    在前台服务中注册接收器,如

    public class WatchMan extends Service
    {
    NotificationManager mNotifyManager;
    NotificationCompat.Builder mBuilder;
    NotificationChannel notificationChannel;
    String NOTIFICATION_CHANNEL_ID = "17";
    
    private BroadcastReceiver mCallBroadcastReceiver = new BroadcastReceiver()
    {
        @Override
        public void onReceive(Context context, Intent intent)
        {
            String PhoneNumber = "UNKNOWN";
            Log.d("RECEIVER :  ","IS UP AGAIN....");
    
            try
            {
                String action = intent.getAction();
                if(action.equalsIgnoreCase("android.intent.action.PHONE_STATE"))
                {
                    if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING))
                    {
                        PhoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
                        Log.d("RECEIVER : ","Incoming number : "+PhoneNumber);
    
                        // update in database and goto catchnumber to sms
    
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
                        {
                            context.startForegroundService(new Intent(context, CatchNumbers.class));
                        }
                        else
                        {
                            context.startService(new Intent(context, CatchNumbers.class));
                        }
                    }
                    if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_IDLE))
                    {
                        PhoneNumber = "UNKNOWN";
                    }
                    if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_OFFHOOK))
                    {
                        Log.d("RECEIVER :  ","OUTGOING CALL RECEIVED....");
    
                        // UPDATED in database and JUST GOTO catchnumber to sms
    
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
                        {
                            context.startForegroundService(new Intent(context, CatchNumbers.class));
                        }
                        else
                        {
                            context.startService(new Intent(context, CatchNumbers.class));
                        }
                    }
                }
                if(action.equalsIgnoreCase("android.intent.action.NEW_OUTGOING_CALL"))
                {
                    PhoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
                    Log.d("RECEIVER : ","Outgoing number : "+PhoneNumber);
    
                    // update in database and BUT DO NOT GOTO catchnumber to sms
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
                Log.e("RECEIVER : ", "Exception is : ", e);
            }
        }
    };
    
    public WatchMan() { }
    
    @Override
    public void onCreate()
    {
        super.onCreate();
        Log.d("WatchMan : ", "\nOnCreate...");
    
        IntentFilter CallFilter = new IntentFilter();
        CallFilter.addAction("android.intent.action.NEW_OUTGOING_CALL");
        CallFilter.addAction("android.intent.action.PHONE_STATE");
        this.registerReceiver(mCallBroadcastReceiver, CallFilter);
    
        Log.d("WatchMan : ", "\nmCallBroadcastReceiver Created....");
    
        mNotifyManager = (NotificationManager) getApplicationContext().getSystemService(NOTIFICATION_SERVICE);
        mBuilder = new NotificationCompat.Builder(this, null);
        mBuilder.setContentTitle("Insta Promo")
                .setContentText("InstaPromo Service ready")
                .setTicker("InstaPromo Service ready")
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setPriority(Notification.PRIORITY_HIGH)
                .setDefaults(Notification.DEFAULT_ALL)
                .setVisibility(Notification.VISIBILITY_PUBLIC)
                .setOngoing(true)
                .setAutoCancel(false);
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
        {
            notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_HIGH);
    
            // Configure the notification channel.
            notificationChannel.setDescription("Channel description");
            notificationChannel.enableLights(true);
            notificationChannel.setLightColor(Color.RED);
            notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
            notificationChannel.enableVibration(true);
            notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
            mNotifyManager.createNotificationChannel(notificationChannel);
    
            mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
            startForeground(17, mBuilder.build());
        }
        else
        {
            mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
            //startForeground(17, mBuilder.build());
            mNotifyManager.notify(17, mBuilder.build());
        }
    }
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        Log.d("WatchMan : ", "\nmCallBroadcastReceiver Listening....");
    
        //return super.onStartCommand(intent, flags, startId);
    
        return START_STICKY;
    }
    
    @Override
    public void onDestroy()
    {
        this.unregisterReceiver(mCallBroadcastReceiver);
        Log.d("WatchMan : ", "\nDestroyed....");
        Log.d("WatchMan : ", "\nWill be created again....");
    }
    
    @Override
    public IBinder onBind(Intent intent)
    {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
    }
    

    请注意我是如何注册和注销
    NEW\u OUTGOING\u CALL
    PHONE\u STATE
    意向操作的
    CatchNumbers
    是另一种
    服务
    ,我用它来处理传入和传出的号码


    您的意图操作可能与我不同,但如果您希望在8.0以后的版本中实现它,这是唯一的方法。经过测试,我正在使用此代码。它还支持4.2到Android P api级别29。每次重新启动时,这两个意向过滤器和接收器都可以在我的
    CatchNumbers
    中使用。希望它真的能帮助你。或者其他人


    我观察到了同样的行为。问题似乎在于Oxygen OS不允许广播接收器从悬挂式天线启动。解决方案是在BroadcastReceiver上使用服务

    public class AlarmReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(Constants.TAG, "event received");
            setContext(context);
    
            /* 
            *** My logic here *** 
            */
    
            Log.d(Constants.TAG, "alarm received");
        }
    }
    
    将代码从BroadcastReceive()的onReceive()移动到服务的onStartCommand()方法,然后在PendingEvent中设置此服务类

    ...
    intent.setClass(currentActivity, AlarmService.class);
    ...
    PendingIntent pendingIntent = PendingIntent.getService(currentActivity, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    ...
    

    希望这有帮助。

    是的,如果用户从最近的应用程序中删除应用程序活动,它也会起作用。。。在4.2到android p模拟器和实际设备上测试如果您不想在最近的活动中使用android:excludeFromRecents=“true”作为您的xml主活动。但这不是解决办法。
    public class WatchMan extends Service
    {
    NotificationManager mNotifyManager;
    NotificationCompat.Builder mBuilder;
    NotificationChannel notificationChannel;
    String NOTIFICATION_CHANNEL_ID = "17";
    
    private BroadcastReceiver mCallBroadcastReceiver = new BroadcastReceiver()
    {
        @Override
        public void onReceive(Context context, Intent intent)
        {
            String PhoneNumber = "UNKNOWN";
            Log.d("RECEIVER :  ","IS UP AGAIN....");
    
            try
            {
                String action = intent.getAction();
                if(action.equalsIgnoreCase("android.intent.action.PHONE_STATE"))
                {
                    if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING))
                    {
                        PhoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
                        Log.d("RECEIVER : ","Incoming number : "+PhoneNumber);
    
                        // update in database and goto catchnumber to sms
    
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
                        {
                            context.startForegroundService(new Intent(context, CatchNumbers.class));
                        }
                        else
                        {
                            context.startService(new Intent(context, CatchNumbers.class));
                        }
                    }
                    if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_IDLE))
                    {
                        PhoneNumber = "UNKNOWN";
                    }
                    if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_OFFHOOK))
                    {
                        Log.d("RECEIVER :  ","OUTGOING CALL RECEIVED....");
    
                        // UPDATED in database and JUST GOTO catchnumber to sms
    
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
                        {
                            context.startForegroundService(new Intent(context, CatchNumbers.class));
                        }
                        else
                        {
                            context.startService(new Intent(context, CatchNumbers.class));
                        }
                    }
                }
                if(action.equalsIgnoreCase("android.intent.action.NEW_OUTGOING_CALL"))
                {
                    PhoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
                    Log.d("RECEIVER : ","Outgoing number : "+PhoneNumber);
    
                    // update in database and BUT DO NOT GOTO catchnumber to sms
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
                Log.e("RECEIVER : ", "Exception is : ", e);
            }
        }
    };
    
    public WatchMan() { }
    
    @Override
    public void onCreate()
    {
        super.onCreate();
        Log.d("WatchMan : ", "\nOnCreate...");
    
        IntentFilter CallFilter = new IntentFilter();
        CallFilter.addAction("android.intent.action.NEW_OUTGOING_CALL");
        CallFilter.addAction("android.intent.action.PHONE_STATE");
        this.registerReceiver(mCallBroadcastReceiver, CallFilter);
    
        Log.d("WatchMan : ", "\nmCallBroadcastReceiver Created....");
    
        mNotifyManager = (NotificationManager) getApplicationContext().getSystemService(NOTIFICATION_SERVICE);
        mBuilder = new NotificationCompat.Builder(this, null);
        mBuilder.setContentTitle("Insta Promo")
                .setContentText("InstaPromo Service ready")
                .setTicker("InstaPromo Service ready")
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setPriority(Notification.PRIORITY_HIGH)
                .setDefaults(Notification.DEFAULT_ALL)
                .setVisibility(Notification.VISIBILITY_PUBLIC)
                .setOngoing(true)
                .setAutoCancel(false);
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
        {
            notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_HIGH);
    
            // Configure the notification channel.
            notificationChannel.setDescription("Channel description");
            notificationChannel.enableLights(true);
            notificationChannel.setLightColor(Color.RED);
            notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
            notificationChannel.enableVibration(true);
            notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
            mNotifyManager.createNotificationChannel(notificationChannel);
    
            mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
            startForeground(17, mBuilder.build());
        }
        else
        {
            mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
            //startForeground(17, mBuilder.build());
            mNotifyManager.notify(17, mBuilder.build());
        }
    }
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        Log.d("WatchMan : ", "\nmCallBroadcastReceiver Listening....");
    
        //return super.onStartCommand(intent, flags, startId);
    
        return START_STICKY;
    }
    
    @Override
    public void onDestroy()
    {
        this.unregisterReceiver(mCallBroadcastReceiver);
        Log.d("WatchMan : ", "\nDestroyed....");
        Log.d("WatchMan : ", "\nWill be created again....");
    }
    
    @Override
    public IBinder onBind(Intent intent)
    {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
    }
    
    ...
    intent.setClass(currentActivity, AlarmService.class);
    ...
    PendingIntent pendingIntent = PendingIntent.getService(currentActivity, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    ...