BroadcastReceiver 死于应用程序
BroadcastReceiver dies with app
如果我让 phone 坐了很长时间,比如 15 分钟,我就失去了我的接收器,但我认为它会像服务一样在为记忆而死后继续存在。
清单:
<receiver
android:name=".WearableReceiver"
android:enabled="false">
<intent-filter>
<action android:name="com.example.johnbravado.MESSAGE_PROCESSED"/>
</intent-filter>
</receiver>
在Activity开始接收
ComponentName component = new ComponentName(CounterActivity.this, WearableReceiver.class);
getPackageManager()
.setComponentEnabledSetting(component,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
接受者
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
//MyConstants.getInstance().showToast("Message Rcvd");
PowerManager powerManager = (PowerManager) context.getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"com.example.johnbravado");
wakeLock.acquire();
// Do Work
MyConstants.getInstance().msgReqAction(intent.getIntExtra(MyConstants.BROADCAST_DATA_REQ, 0));
wakeLock.release();
}
广播发送者
String BROADCAST_ACTION_RESP = "com.example.johnbravado.MESSAGE_PROCESSED"
@Override
public void onMessageReceived(final MessageEvent messageEvent) {
nodeId = messageEvent.getSourceNodeId();
String incomingPath = messageEvent.getPath();
int incomingReq = Integer.parseInt(new String(messageEvent.getData()));
if(incomingPath.equalsIgnoreCase(MyConstants.MSG_COUNTER_REQ_PATH)) {
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(BROADCAST_ACTION_RESP);
broadcastIntent.putExtra(MyConstants.BROADCAST_DATA_REQ, incomingReq);
sendBroadcast(broadcastIntent);
}else if(incomingPath.equalsIgnoreCase(MyConstants.MSG_DEFAULT_PATH)){
}
}
我让它长期存在的唯一方法是调用服务
wearableReceiverIntent = new Intent(this, WearableReceiverService.class);
if(!WearableReceiverService.isRunning())
startService(wearableReceiverIntent);
服务
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
IntentFilter filter = new IntentFilter(MyConstants.BROADCAST_ACTION_RESP);
filter.addCategory(Intent.CATEGORY_DEFAULT);
receiver = new WearableReceiver();
registerReceiver(receiver, filter);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_notif_bible)
.setContentText("Preaching").build();
startForeground(MyConstants.NOTIF_COUNTING_SERVICE, notification);
isRunning = true;
return START_STICKY;
}
如果我 运行 该服务会持续很长时间,但考虑到我每 10 分钟只交互一次,它会不必要地耗尽电池电量。我的印象是广播接收器除了短暂的工作之外会像服务一样工作。如果您需要执行长时间操作,请调用该服务。
A BroadcastReceiver 处理一个意图,然后再次停止。这种对意图的处理应该很快。如果你想做很多事情,你应该从 BroadcastReceiver
开始一个 Service
并从那里处理它。
A BroadcastReceiver object is only valid for the duration of the call
to onReceive(Context, Intent). Once your code returns from this
function, the system considers the object to be finished and no longer
active.
BroadcastReceiver 使用 sendBroadcast
意图启动。
所以删除 android:enabled="false"
并使用 sendBroadcast
,这将在 Android.
之前启动 Receiver
http://www.vogella.com/tutorials/AndroidBroadcastReceiver/article.html
如果您的 BroadcastReceiver
已在您的清单中设置,则无需尝试调整包的 PackageManager
组件信息。只要去掉enabled="false"
部分即可。
您的 BroadcastReceiver
的功能应该非常简短:通常更新一些内部数据或启动另一个组件,这些组件可以完成应用程序操作的繁重工作。您可以使用它来触发 Service
在后台执行此类操作。但是,请注意 "background" 在这种情况下意味着没有 user-interaction。它 并不意味着 执行的后台上下文,例如辅助线程。由您来管理 Service
中的线程。 BroadcastReceiver
和 Service
回调入口点(onReceive()
和 onStartIntent()
)运行 在 主线程 的上下文中您的应用程序。
电源管理无疑在所有这些方面发挥了作用。您的广播 Intent
实际上是以唤醒设备的方式发送和完成的吗?如果它确实唤醒了设备并发送了 Intent
,设备将只会保持清醒足够长的时间,以便 BroadcastReceiver
到 运行 它的 onReceive()
;在那之后 returns 没有任何保证。该设备将主动休眠,这就是为什么唤醒锁是一回事。但是,除非使用得当,否则使用唤醒锁会导致电池过度消耗。如果您运行正在使用 Marshmallow 或更新版本,Doze 功能也会破坏您的计划。唤醒锁在打盹模式下会被忽略,并且在用户将设备从打盹模式中唤醒之前不会被考虑。
当屏幕关闭时,Greenify 正在终止我的应用程序。我正在与一些我无望用代码来防御的事情作斗争。在我明确告诉 Greenify 不要终止我的应用程序之后,我从来没有告诉它终止我的应用程序,一切都按预期进行。
由于 Asus Mobile Manager 应用程序,我在 Asus ZenPad 上遇到了同样的问题,特别是 "Auto start manager" 阻止了对我的应用程序的意图。
停用该应用程序(无法卸载)毫无意义,解决方案是保留该应用程序的安装状态,但将我正在开发的应用程序列入白名单,以便它可以像 PACKAGE_REPLACE 一样接收广播。 (注意开关很混乱,你实际上必须触摸 "blocked" 所以它变成 "allowed" 才能启用它。
我认为另一种选择是更新或更改 ROM(选择一个没有所有过时软件的版本)。
我遇到了同样的问题,通过授予应用程序自动启动权限解决了这个问题。
前往
设置->权限->管理自动启动
并允许您的应用程序自动启动。
如果我让 phone 坐了很长时间,比如 15 分钟,我就失去了我的接收器,但我认为它会像服务一样在为记忆而死后继续存在。
清单:
<receiver
android:name=".WearableReceiver"
android:enabled="false">
<intent-filter>
<action android:name="com.example.johnbravado.MESSAGE_PROCESSED"/>
</intent-filter>
</receiver>
在Activity开始接收
ComponentName component = new ComponentName(CounterActivity.this, WearableReceiver.class);
getPackageManager()
.setComponentEnabledSetting(component,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
接受者
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
//MyConstants.getInstance().showToast("Message Rcvd");
PowerManager powerManager = (PowerManager) context.getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"com.example.johnbravado");
wakeLock.acquire();
// Do Work
MyConstants.getInstance().msgReqAction(intent.getIntExtra(MyConstants.BROADCAST_DATA_REQ, 0));
wakeLock.release();
}
广播发送者
String BROADCAST_ACTION_RESP = "com.example.johnbravado.MESSAGE_PROCESSED"
@Override
public void onMessageReceived(final MessageEvent messageEvent) {
nodeId = messageEvent.getSourceNodeId();
String incomingPath = messageEvent.getPath();
int incomingReq = Integer.parseInt(new String(messageEvent.getData()));
if(incomingPath.equalsIgnoreCase(MyConstants.MSG_COUNTER_REQ_PATH)) {
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(BROADCAST_ACTION_RESP);
broadcastIntent.putExtra(MyConstants.BROADCAST_DATA_REQ, incomingReq);
sendBroadcast(broadcastIntent);
}else if(incomingPath.equalsIgnoreCase(MyConstants.MSG_DEFAULT_PATH)){
}
}
我让它长期存在的唯一方法是调用服务
wearableReceiverIntent = new Intent(this, WearableReceiverService.class);
if(!WearableReceiverService.isRunning())
startService(wearableReceiverIntent);
服务
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
IntentFilter filter = new IntentFilter(MyConstants.BROADCAST_ACTION_RESP);
filter.addCategory(Intent.CATEGORY_DEFAULT);
receiver = new WearableReceiver();
registerReceiver(receiver, filter);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_notif_bible)
.setContentText("Preaching").build();
startForeground(MyConstants.NOTIF_COUNTING_SERVICE, notification);
isRunning = true;
return START_STICKY;
}
如果我 运行 该服务会持续很长时间,但考虑到我每 10 分钟只交互一次,它会不必要地耗尽电池电量。我的印象是广播接收器除了短暂的工作之外会像服务一样工作。如果您需要执行长时间操作,请调用该服务。
A BroadcastReceiver 处理一个意图,然后再次停止。这种对意图的处理应该很快。如果你想做很多事情,你应该从 BroadcastReceiver
开始一个 Service
并从那里处理它。
A BroadcastReceiver object is only valid for the duration of the call to onReceive(Context, Intent). Once your code returns from this function, the system considers the object to be finished and no longer active.
BroadcastReceiver 使用 sendBroadcast
意图启动。
所以删除 android:enabled="false"
并使用 sendBroadcast
,这将在 Android.
http://www.vogella.com/tutorials/AndroidBroadcastReceiver/article.html
如果您的 BroadcastReceiver
已在您的清单中设置,则无需尝试调整包的 PackageManager
组件信息。只要去掉enabled="false"
部分即可。
您的 BroadcastReceiver
的功能应该非常简短:通常更新一些内部数据或启动另一个组件,这些组件可以完成应用程序操作的繁重工作。您可以使用它来触发 Service
在后台执行此类操作。但是,请注意 "background" 在这种情况下意味着没有 user-interaction。它 并不意味着 执行的后台上下文,例如辅助线程。由您来管理 Service
中的线程。 BroadcastReceiver
和 Service
回调入口点(onReceive()
和 onStartIntent()
)运行 在 主线程 的上下文中您的应用程序。
电源管理无疑在所有这些方面发挥了作用。您的广播 Intent
实际上是以唤醒设备的方式发送和完成的吗?如果它确实唤醒了设备并发送了 Intent
,设备将只会保持清醒足够长的时间,以便 BroadcastReceiver
到 运行 它的 onReceive()
;在那之后 returns 没有任何保证。该设备将主动休眠,这就是为什么唤醒锁是一回事。但是,除非使用得当,否则使用唤醒锁会导致电池过度消耗。如果您运行正在使用 Marshmallow 或更新版本,Doze 功能也会破坏您的计划。唤醒锁在打盹模式下会被忽略,并且在用户将设备从打盹模式中唤醒之前不会被考虑。
当屏幕关闭时,Greenify 正在终止我的应用程序。我正在与一些我无望用代码来防御的事情作斗争。在我明确告诉 Greenify 不要终止我的应用程序之后,我从来没有告诉它终止我的应用程序,一切都按预期进行。
由于 Asus Mobile Manager 应用程序,我在 Asus ZenPad 上遇到了同样的问题,特别是 "Auto start manager" 阻止了对我的应用程序的意图。
停用该应用程序(无法卸载)毫无意义,解决方案是保留该应用程序的安装状态,但将我正在开发的应用程序列入白名单,以便它可以像 PACKAGE_REPLACE 一样接收广播。 (注意开关很混乱,你实际上必须触摸 "blocked" 所以它变成 "allowed" 才能启用它。
我认为另一种选择是更新或更改 ROM(选择一个没有所有过时软件的版本)。
我遇到了同样的问题,通过授予应用程序自动启动权限解决了这个问题。
前往 设置->权限->管理自动启动 并允许您的应用程序自动启动。