Android 7,8和Oxygen操作系统:应用程序关闭时广播接收器不工作
在Android 7之后,如果应用程序从最近的任务列表中被关闭,则我的报警接收器不会接收广播接收器。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
下面是我的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
这反过来表明,在从“最近的任务”列表中刷取应用程序时,不会停止该应用程序。此外,应用程序信息页面上的“强制停止”按钮已启用,表明应用程序尚未强制停止
不要像这样在
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);
...