page.title=백그라운드 최적화 page.metaDescription=암시적 브로드캐스트에 대한 새로운 제한. page.keywords="android N", "implicit broadcasts", "job scheduler" page.image=images/cards/card-nyc_2x.jpg @jd:body
백그라운드 프로세스는 메모리와 배터리를 많이 소모할 수 있습니다. 예를 들어, 암시적 브로드캐스트는 이 브로드캐스트를 수신하도록 등록된 많은 백그라운드 프로세스를 시작할 수 있지만 해당 프로세스가 많은 작업을 수행하지 못할 경우가 있습니다. 이로 인해 기기 성능과 사용자 경험에 상당한 영향을 미칠 수 있습니다.
이 문제를 완화하기 위해, N Developer Preview 는 다음과 같은 제한을 적용합니다.
Android 프레임워크는 이러한 암시적 브로드캐스트의 필요성을 줄이기 위한 여러 가지 해결책을 제공합니다. 예를 들어, {@link android.app.job.JobScheduler} 및 {@code GcmNetworkManager}는 지정된 조건(예: 비 데이터 통신 네트워크에 연결)이 충족될 경우 네트워크 작업을 예약할 수 있는 강력한 메커니즘을 제공합니다. 이제 {@link android.app.job.JobScheduler}를 사용하여 콘텐츠 제공자의 변경에 대응할 수도 있습니다. {@link android.app.job.JobInfo} 객체는 {@link android.app.job.JobScheduler}가 작업 예약에 사용하는 매개변수를 캡슐화합니다. 작업 조건이 충족되면 시스템은 이 작업을 앱의 {@link android.app.job.JobService}에서 실행합니다.
이 문서에서는 대체 메서드(예: {@link android.app.job.JobScheduler})를 사용하여 이러한 새로운 제한에 맞게 앱을 적용하는 방법에 대해 배워보겠습니다.
브로드캐스트를 수신하도록 매니페스트에 등록되어 있더라도, N Developer Preview를 대상으로 하는 앱은 {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION} 브로드캐스트를 수신하지 않으며, 이 브로드캐스트에 종속되는 프로세스는 시작되지 않습니다. 이 경우 네트워크 변경을 수신하려는 앱이나, 기기가 비 데이터 통신 네트워크에 연결될 때 대량 네트워크 액티비티를 수행하려는 앱에서 문제가 발생할 수 있습니다. 이 제한을 해결하기 위한 여러 가지 해결책이 Android 프레임워크에 이미 있지만, 올바른 해결책을 선택하는 것은 앱의 용도에 따라 다릅니다.
참고: {@link android.content.Context#registerReceiver Context.registerReceiver()}로 등록된 {@link android.content.BroadcastReceiver}는 앱이 포그라운드에 있는 동안 계속해서 이 브로드캐스트를 수신합니다.
{@link android.app.job.JobInfo.Builder JobInfo.Builder} 클래스를 사용하여 {@link android.app.job.JobInfo} 객체를 빌드하는 경우, {@link android.app.job.JobInfo.Builder#setRequiredNetworkType setRequiredNetworkType()} 메서드를 적용하고 {@link android.app.job.JobInfo JobInfo.NETWORK_TYPE_UNMETERED}를 작업 매개변수로 전달합니다. 다음의 코드 샘플에서는 기기가 비 데이터 통신 네트워크에 연결되어 충전 중일 때 실행할 서비스를 예약합니다.
public static final int MY_BACKGROUND_JOB = 0;
...
public static void scheduleJob(Context context) {
JobScheduler js =
(JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
JobInfo job = new JobInfo.Builder(
MY_BACKGROUND_JOB,
new ComponentName(context, MyJobService.class))
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(true)
.build();
js.schedule(job);
}
작업의 조건이 충족되면, 앱은 {@link android.app.job.JobService#onStartJob onStartJob()} 메서드를 지정된 {@code JobService.class}에서 실행하기 위한 콜백을 수신합니다. {@link android.app.job.JobScheduler} 구현의 더 많은 예를 보려면, JobScheduler 샘플 앱을 참조하세요.
GMSCore 서비스를 사용하고 Android 5.0(API 레벨 21) 이하를 대상으로 하는 앱은 {@code GcmNetworkManager}를 사용하고 {@code Task.NETWORK_STATE_UNMETERED}를 지정할 수 있습니다.
포그라운드에서 실행되는 앱은 여전히 등록된 {@link android.content.BroadcastReceiver}로 {@code CONNECTIVITY_CHANGE}를 수신할 수 있습니다. 그러나, {@link android.net.ConnectivityManager} API는 지정된 네트워크 조건이 충족될 경우에만 콜백을 요청하는 더욱 강력한 메서드를 제공합니다.
{@link android.net.NetworkRequest} 객체는 {@link android.net.NetworkCapabilities}의 관점에서 네트워크 콜백의 매개변수를 정의합니다. {@link android.net.NetworkRequest.Builder NetworkRequest.Builder} 클래스로 {@link android.net.NetworkRequest} 객체를 생성합니다. 이어서 {@link android.net.ConnectivityManager#registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback) registerNetworkCallback()} 이 {@link android.net.NetworkRequest} 객체를 시스템에 전달합니다. 네트워크 조건이 충족되면, 앱은 {@link android.net.ConnectivityManager.NetworkCallback} 클래스에 정의된 {@link android.net.ConnectivityManager.NetworkCallback#onAvailable onAvailable()} 메서드를 실행하기 위한 콜백을 수신합니다.
앱이 종료되거나 앱이 {@link android.net.ConnectivityManager#unregisterNetworkCallback unregisterNetworkCallback()}을 호출할 때까지 계속해서 콜백을 수신합니다.
N Developer Preview에서 앱은 {@link android.hardware.Camera#ACTION_NEW_PICTURE} 또는 {@link android.hardware.Camera#ACTION_NEW_VIDEO} 브로드캐스트를 송수신할 수 없습니다. 이 제한은 새로운 이미지나 동영상을 처리하기 위해 여러 앱을 깨워야 하는 경우, 성능 및 사용자 경험에 미치는 영향을 줄여줍니다. N Developer Preview는 {@link android.app.job.JobInfo} 및 {@link android.app.job.JobParameters}를 확장하여 대체 해결책을 제공합니다.
콘텐츠 URI 변경에 대한 작업을 트리거하기 위해, N Developer Preview 는 다음과 같은 메서드로 {@link android.app.job.JobInfo} API를 확장합니다.
참고: {@code TriggerContentUri()}는 {@link android.app.job.JobInfo.Builder#setPeriodic setPeriodic()} 또는 {@link android.app.job.JobInfo.Builder#setPersisted setPersisted()}와 조합으로 사용될 수 없습니다. 콘텐츠 변경을 계속해서 모니터링하려면, 앱의 {@link android.app.job.JobService}가 가장 최근 콜백의 처리를 완료하기 전에 새로운 {@link android.app.job.JobInfo}를 예약하세요.
다음 샘플 코드에서는 콘텐츠 URI, {@code MEDIA_URI}의 변경을 시스템이 보고할 때 트리거할 작업을 예약합니다.
public static final int MY_BACKGROUND_JOB = 0;
...
public static void scheduleJob(Context context) {
JobScheduler js =
(JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
JobInfo.Builder builder = new JobInfo.Builder(
MY_BACKGROUND_JOB,
new ComponentName(context, MediaContentJob.class));
builder.addTriggerContentUri(
new JobInfo.TriggerContentUri(MEDIA_URI,
JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
js.schedule(builder.build());
}
지정된 콘텐츠 URI에서의 변경을 시스템이 보고할 때, 앱이 콜백을 수신하고 {@link android.app.job.JobParameters} 객체가 {@code MediaContentJob.class}의 {@link android.app.job.JobService#onStartJob onStartJob()}메서드에 전달됩니다.
N Developer Preview에서는 또한 어떤 콘텐츠 기관과 URI가 작업을 트리거했는지에 대한 유용한 정보를 앱이 수신할 수 있도록 {@link android.app.job.JobParameters}를 확장합니다.
다음 샘플 코드에서는 {@link android.app.job.JobService#onStartJob JobService.onStartJob()} 메서드를 재정의하고 , 작업을 트리거한 콘텐츠 기관과 URI를 기록합니다.
@Override
public boolean onStartJob(JobParameters params) {
StringBuilder sb = new StringBuilder();
sb.append("Media content has changed:\n");
if (params.getTriggeredContentAuthorities() != null) {
sb.append("Authorities: ");
boolean first = true;
for (String auth :
params.getTriggeredContentAuthorities()) {
if (first) {
first = false;
} else {
sb.append(", ");
}
sb.append(auth);
}
if (params.getTriggeredContentUris() != null) {
for (Uri uri : params.getTriggeredContentUris()) {
sb.append("\n");
sb.append(uri);
}
}
} else {
sb.append("(No content)");
}
Log.i(TAG, sb.toString());
return true;
}
저용량 메모리 기기나 저용량 메모리 조건에서 앱이 실행되도록 최적화하면 성능과 사용자 경험을 개선할 수 있습니다. 백그라운드 서비스에 대한 종속성과 정적으로 등록된 암시적 브로드캐스트 수신기에 대한 종속성을 제거하면 기기에서 앱을 더욱 빨리 실행할 수 있습니다. N Developer Preview는 이러한 문제 중 일부를 줄이기 위한 조치를 취하고 있지만, 백그라운드 프로세스를 전혀 사용하지 않고 앱이 실행되도록 최적화하는 것이 좋습니다.
N Developer Preview에서는 백그라운드 프로세스를 비활성화하고 앱 동작을 테스트하는 데 사용할 수 있는 몇 가지 추가적인 ADB(Android Debug Bridge) 명령을 소개합니다.
{@code $ adb shell cmd appops set RUN_IN_BACKGROUND ignore}
{@code $ adb shell cmd appops set RUN_IN_BACKGROUND allow}