我开发了一个应用程序,有些人抱怨它需要太多电池,这是屏幕后第二大消耗过程。但是,在某些设备中,它不会消耗那么多电池。
我的应用所做的所有工作都在服务中。该服务是粘性的并且一直在运行(android系统可能在资源较少时将其杀死或在设备进入休眠状态时暂停),只要屏幕打开就有监听加速度计,它不是前台服务并没有举行唤醒锁。
有人可以告诉我为什么需要大量电池吗? 为什么这只发生在某些设备上?
以下是相关代码:
public class aListenerService extends Service implements SensorEventListener
{
private BroadcastReceiver mScreenReceiver = new BroadcastReceiver()
{
// if screen was turned on then register to accelerometer
// if screen was turned off then unregister from accelerometer
}
private BroadcastReceiver mPhoneStateReceiver = new BroadcastReceiver()
{
// do something...
}
@Override
public void onCreate()
{
super.onCreate();
// get sensor manager and accelerometer sensor
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
// register accelerometer sensor and receiver
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
IntentFilter screenFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
screenFilter.addAction(Intent.ACTION_SCREEN_ON);
registerReceiver(mScreenReceiver, screenFilter);
registerReceiver(mPhoneStateReceiver, new IntentFilter(INTENT_ACTION_PHONE_STATE));
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
super.onStartCommand(intent, flags, startId);
return Service.START_STICKY;
}
@Override
public void onDestroy()
{
super.onDestroy();
// unregister to sensor and receivers
mSensorManager.unregisterListener(this);
unregisterReceiver(mScreenReceiver);
unregisterReceiver(mPhoneStateReceiver);
}
@Override
public void onSensorChanged(SensorEvent event)
{
// do something...
}
}
答案 0 :(得分:6)
关于CPU和电池,一直运行服务可能很昂贵 - 这是服务的缺点之一。特别是如果包含导致某些CPU负载的线程。有一些选项可供选择,具体取决于您的应用程序要求:
如果您的服务结果仅在用户可以使用它时相关,您可能会想到在屏幕上开启和关闭事件停止和启动服务 - 或者至少启动和停止包含的线程/处理程序。这可以通过使用BroadcastReceiver
:
public class ScreenReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
// (1) stop service or (2) stop all threads and unregister all event
// handlers, if the service has to register the screen receiver
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
// (1) start service or (2) start all threads and register all event
// handlers as needed
}
}
}
请注意,必须以编程方式注册屏幕事件。如果您必须在同一服务内部注册屏幕开启和关闭事件,请将其作为 sticky 启动。这样就可以保留服务实例。 (示例:电池小部件,天气信息......)
如果您拥有基于事件的环境,则可以考虑使用Google Cloud Messaging(GCM)。使用GCM,您可以从任何服务器向任何已注册的设备发送消息,使其唤醒并处理传入的信息。无需一直轮询信息。
查看Google官方documentation和示例,如果此方案符合您的要求(示例:短信应用,聊天应用,...)
如果您需要定期处理/运行数据/代码,您可能会考虑使用AlarmManager
:
public void SetAlarm(Context context) {
AlarmManager manager = (AlarmManager)context.
getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
PendingIntent pendingIntent =
PendingIntent.getBroadcast(context, 0, intent, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(), 1000 *60 , pendingIntent);
}
然而,缺点是它不适合短时间间隔(比方说小于30分钟)。 (示例:电子邮件客户端,...)
所以有一些替代方案。看看你的代码我可以看到你正在用传感器做些什么。如果屏幕关闭,您是否需要传感器信息?或者什么样的事件可以触发服务的开始和结束?
如果你真的需要结果(例如GPS跟踪器),你可能别无选择,只能优化你的代码。如果电池电量不足,停止服务可能有意义(详见this)。
祝你好运!