使用服务在后台检查电池电量

时间:2014-07-02 13:50:48

标签: android service background-process battery

我经常搜索,但我总是更加困惑。

我必须创建一个适用于后台的应用程序并检查电池电量。我该如何创建服务?服务应该在设备启动时启动,并且必须在电池达到一定百分比时与活动通信,因此消费者没有任何交互。

我要创建什么类型的服务?我有什么需要做的事情?

2 个答案:

答案 0 :(得分:6)

使用AlarmManager定期触发警报,而不是使用长时间运行的服务,可以由BroadcastReceiver接收并可以调用服务(应该在某个时刻停止)或IntentService来执行电池检查。这将为用户带来最少的悲痛,因为它将使用更少的资源来保持您的应用程序执行它需要做的事情,并减少您的悲伤,因为系统将不太可能杀死无休止运行的应用程序。

例如,对于警报接收器:

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);
        }   
     }
}

对于启动接收器:

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);
        }
    }
}

并为您的服务:

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();
        }
    }
}

在您的清单中,您需要添加:

<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>

答案 1 :(得分:1)

您不需要服务。在应用程序中包含侦听Intent.ACTION_BATTERY_CHANGED广播的广播接收器。在Application Manifest中定义该广播接收器,并且只要电池状态发生变化,它就会自动启动。

广播包括有关电池当前状态的信息,因此无需精心设计(且非常昂贵!)的解决方案来查询此信息。

This page 将提供所有详细信息。

该页面引人注目的一句话:

  

您无法轻松连续监控电池状态,但事实并非如此   需要。

     一般来说,不断监测电池的影响   电平对电池的影响大于应用的正常水平   行为,所以最好只监控重大变化   电池电量 - 特别是当设备进入或退出低电平时   电池状态。

     

下面的清单代码段是从intent filter元素中提取的   在广播接收器内。每当接收器被触发   通过收听,设备电池电量变低或退出低电量状态   ACTION_BATTERY_LOW和ACTION_BATTERY_OKAY。

<receiver android:name=".BatteryLevelReceiver">
<intent-filter>
  <action android:name="android.intent.action.ACTION_BATTERY_LOW"/>
  <action android:name="android.intent.action.ACTION_BATTERY_OKAY"/>
  </intent-filter>
</receiver>

您可能希望监控的其他操作包括:ACTION_BATTERY_CHANGEDACTION_POWER_CONNECTEDACTION_POWER_DISCONNECTED