Rather than using a long-running service, use an AlarmManager to trigger alarms periodically, which can be received by a BroadcastReceiver and can call a Service (which should stop itself at some point) or an IntentService to perform your battery check. This will cause the least grief for the user, since it will use less resources to keep your application doing what it needs to do, and less grief for you, since the system will be less likely to kill your endlessly-running app.
For example, for an Alarm Receiver:
public class AlarmReceiver extends BroadcastReceiver {
private static final String TAG = "AlarmReceiver";
private static final int REQUEST_CODE = 777;
public static final long ALARM_INTERVAL = DateUtils.MINUTE_IN_MILLIS;
// Call this from your service
public static void startAlarms(final Context context) {
final AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// start alarm right away
manager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, 0, ALARM_INTERVAL,
getAlarmIntent(context));
}
/*
* Creates the PendingIntent used for alarms of this receiver.
*/
private static PendingIntent getAlarmIntent(final Context context) {
return PendingIntent.getBroadcast(context, REQUEST_CODE, new Intent(context, AlarmReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT);
}
@Override
public void onReceive(final Context context, final Intent intent) {
if (context == null) {
// Somehow you've lost your context; this really shouldn't happen
return;
}
if (intent == null){
// No intent was passed to your receiver; this also really shouldn't happen
return;
}
if (intent.getAction() == null) {
// If you called your Receiver explicitly, this is what you should expect to happen
Intent monitorIntent = new Intent(context, YourService.class);
monitorIntent.putExtra(YourService.BATTERY_UPDATE, true);
context.startService(monitorIntent);
}
}
}
For your Boot Receiver:
public class BootReceiver extends BroadcastReceiver{
private static final String TAG = "BootReceiver";
private static final String ACTION_BOOT = "android.intent.action.BOOT_COMPLETED";
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equalsIgnoreCase(ACTION_BOOT)) {
// This intent action can only be set by the Android system after a boot
Intent monitorIntent = new Intent(context, YourService.class);
monitorIntent.putExtra(YourService.HANDLE_REBOOT, true);
context.startService(monitorIntent);
}
}
}
And for your Service:
public class YourService extends Service {
private static final String TAG = "YourService";
public static final String BATTERY_UPDATE = "battery";
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null && intent.hasExtra(BootReceiver.ACTION_BOOT)){
AlarmReceiver.startAlarms(YourService.this.getApplicationContext());
}
if (intent != null && intent.hasExtra(BATTERY_UPDATE)){
new BatteryCheckAsync().execute();
}
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
private class BatteryCheckAsync extends AsyncTask<Void, Void, Void>{
@Override
protected Void doInBackground(Void... arg0) {
//Battery State check - create log entries of current battery state
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = YourService.this.registerReceiver(null, ifilter);
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
Log.i("BatteryInfo", "Battery is charging: " + isCharging);
int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
Log.i("BatteryInfo", "Battery charge level: " + (level / (float)scale));
return null;
}
protected void onPostExecute(){
YourService.this.stopSelf();
}
}
}
In your manifest, you'll need to add in:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- Services -->
<service
android:name="com.your.package.YourService"
android:enabled="true"
android:exported="false"
android:label="@string/app_name" >
</service>
<!-- Receivers -->
<receiver
android:name="com.your.package.AlarmReceiver"
android:enabled="true" />
<receiver
android:name="com.your.package.BootReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>