You can use the ConnectivityManager to determine the active wireless radio and modify your prefetching routines depending on network type:
ConnectivityManager cm =
(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
TelephonyManager tm =
(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
int PrefetchCacheSize = DEFAULT_PREFETCH_CACHE;
switch (activeNetwork.getType()) {
case (ConnectivityManager.TYPE_WIFI):
PrefetchCacheSize = MAX_PREFETCH_CACHE;
break;
case (ConnectivityManager.TYPE_MOBILE): {
switch (tm.getNetworkType()) {
case (TelephonyManager.NETWORK_TYPE_LTE |
TelephonyManager.NETWORK_TYPE_HSPAP):
PrefetchCacheSize *= 4;
break;
case (TelephonyManager.NETWORK_TYPE_EDGE |
TelephonyManager.NETWORK_TYPE_GPRS):
PrefetchCacheSize /= 2;
break;
default: break;
}
break;
}
default: break;
}
The BatteryManager broadcasts all battery and charging details in a broadcast Intent that includes the charging status.
To check the current battery status, examine the broadcast intent:
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = context.registerReceiver(null, ifilter);
// Are we charging / charged?
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
// How are we charging?
int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
If you want to react to changes in the battery charging state, use a BroadcastReceiver to register for the battery status actions in your code:
public void registerBatteryChargingStateReceiver()
{
// Create Receiver Object
BroadcastReceiver receiver = new MyPowerReceiver();
//Create Intent Filter
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_POWER_CONNECTED);
intentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
// Register broadcast receiver
this.registerReceiver(receiver, intentFilter);
}
Introduced in API level 21, JobScheduler allows you to schedule a task around specific conditions, rather than a specific time as with AlarmManager.
JobScheduler has three components:
- JobInfo uses the builder pattern to set the conditions for the task.
- JobService is a wrapper around the Service class where the task is actually completed.
- JobScheduler schedules and cancels tasks.
Set the job conditions by constructing a JobInfo object using the JobInfo.Builder class.
JobScheduler scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
ComponentName serviceName = new ComponentName(getPackageName(),
NotificationJobService.class.getName());
JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, serviceName);
builder.setRequiredNetworkType(NETWORK_TYPE_UNMETERED);
JobInfo jobInfo = builder.build();
The JobInfo.Builder class has many set() methods that allow you to determine the conditions of the task. Below is a list of few available constraints with their respective set() methods and class constants:
- Minimum Latency: The minimum amount of time to wait before completing the task. Set this condition using the setMinimumLatency() method, which takes a single argument: the amount of time to wait in milliseconds.
- Override Deadline: The maximum time to wait before running the task, even if other conditions aren't met. Set this condition using the setOverrideDeadline() method, which is the maximum time to wait in milliseconds.
- Periodic: Repeats the task after a certain amount of time. Set this condition using the setPeriodic() method, passing in the repetition interval. This condition is mutually exclusive with the minimum-latency and override-deadline conditions: setting setPeriodic() with one of them results in an error.
- Required Network Type: The kind of network type your job needs. If the network isn't necessary, you don't need to call this function, because the default is NETWORK_TYPE_NONE. Set this condition using the setRequiredNetworkType() method, passing in one of the following constants: NETWORK_TYPE_NONE, NETWORK_TYPE_ANY, NETWORK_TYPE_NOT_ROAMING, NETWORK_TYPE_UNMETERED.
- Required Charging State: Whether the device needs to be plugged in to run this job. Set this condition using the setRequiresCharging() method, passing in a boolean. The default is false.
- Requires Device Idle: Whether the device needs to be in idle mode to run this job. "Idle mode" means that the device isn't in use and hasn't been for some time, as loosely defined by the system. When the device is in idle mode, it's a good time to perform resource-heavy jobs. Set this condition using the setRequiresDeviceIdle()method, passing in a boolean. The default is false.
Once the conditions for a task are met, the framework launches a subclass of JobService, which is where you implement the task itself. The JobService runs on the UI thread, so you need to offload blocking operations to a worker thread.
Declare the JobService subclass in the Android Manifest, and include the BIND_JOB_SERVICE permission:
<service android:name="MyJobService"
android:permission="android.permission.BIND_JOB_SERVICE" >
In your subclass of JobService, override two methods, onStartJob() and onStopJob().
The system calls onStartJob() and automatically passes in a JobParameters object, which the system creates with information about your job. If your task contains long-running operations, offload the work onto a separate thread. The onStartJob() method returns a boolean: true if your task has been offloaded to a separate thread (meaning it might not be completed yet) and false if there is no more work to be done.
Use the jobFinished() method from any thread to tell the system that your task is complete. This method takes two parameters: the JobParameters object that contains information about the task, and a boolean that indicates whether the task needs to be rescheduled, according to the defined backoff policy.
If the system determines that your app must stop execution of the job, even before jobFinished() is called, the system calls onStopJob(). This happens if the requirements that you specified when you scheduled the job are no longer met.
Examples:
- If your app requests Wi-Fi with setRequiredNetworkType() but the user turns off Wi-Fi while your job is executing, the system calls onStopJob().
- If your app specifies setRequiresDeviceIdle() but the user starts interacting with the device while your job is executing, the system calls onStopJob().
You're responsible for how your app behaves when it receives onStopJob(), so don't ignore it. This method returns a boolean, indicating whether you'd like to reschedule the job based on the defined backoff policy, or drop the task.
The final part of scheduling a task is to use the JobScheduler class to schedule the job. To obtain an instance of this class, call getSystemService(JOB_SCHEDULER_SERVICE). Then schedule a job using the schedule() method, passing in the JobInfo object you created with the JobInfo.Builder. For example:
mScheduler.schedule(myJobInfo);
To cancel a job, call cancel(), passing in the job ID from the JobInfo.Builder object, or call cancelAll(). For example: