blob: a0021470275adefad2264fcca9ad31d0ba581f13 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
|
page.title=バックグラウンド処理の最適化
page.metaDescription=暗黙的なブロードキャストに対する新しい制限。
page.keywords="android N", "implicit broadcasts", "job scheduler"
page.image=images/cards/card-nyc_2x.jpg
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>
このドキュメントの内容
</h2>
<ol>
<li>
<a href="#connectivity-action">CONNECTIVITY_ACTION に対する制限</a>
</li>
<li>
<a href="#sched-jobs">従量制ではない接続でネットワーク ジョブをスケジュールする</a>
</li>
<li>
<a href="#monitor-conn">アプリを実行しているときにネットワーク接続を監視する</a>
</li>
<li>
<a href="#media-broadcasts">NEW_PICTURE と NEW_VIDEO に対する制限</a>
</li>
<li>
<a href="#new-jobinfo">新しい JobInfo メソッド</a>
</li>
<li>
<a href="#new-jobparam">新しい JobParameter メソッド</a>
</li>
<li>
<a href="#further-optimization">アプリをさらに最適化する</a>
</li>
</ol>
</div>
</div>
<p>
バックグラウンド処理が多くのメモリとバッテリーを消費する場合があります。たとえば、多くのバックグラウンド処理が暗黙的なブロードキャストをリッスンするように登録されていますが、バックグラウンド処理が有用でない場合でも、暗黙的なブロードキャストによりこれらの処理が開始されることがあります。
バックグラウンド処理が端末のパフォーマンスとユーザー エクスペリエンスの両方に多大な影響を及ぼす可能性があります。
</p>
<p>
N Developer Preview では、この問題を軽減するために、次の制限が適用されています。
</p>
<ul>
<li>プレビューをターゲットにしたアプリは、マニフェストで {@link
android.net.ConnectivityManager#CONNECTIVITY_ACTION} ブロードキャストの受信登録をしていても、このブロードキャストを受信しません。
フォアグラウンドで実行中のアプリは、{@link
android.content.Context#registerReceiver Context.registerReceiver()} で {@link android.content.BroadcastReceiver} を登録することにより、メインスレッドで {@code CONNECTIVITY_CHANGE} を引き続きリッスンできます。
</li>
<li>アプリは、{@link
android.hardware.Camera#ACTION_NEW_PICTURE} ブロードキャストまたは {@link
android.hardware.Camera#ACTION_NEW_VIDEO} ブロードキャストを送受信できません。この最適化は、プレビューをターゲットにしたアプリだけでなく、すべてのアプリに影響を及ぼします。
</li>
</ul>
<p>
Android フレームワークは、これらの暗黙的なブロードキャストの必要性を軽減するいくつかのソリューションを提供します。
たとえば、{@link android.app.job.JobScheduler} と <a href="https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager">
{@code GcmNetworkManager}</a> は、従量制ではないネットワークへの接続など、指定条件が満たされたときに、ネットワーク操作をスケジュールするための堅牢なメカニズムを提供します。
また、コンテンツ プロバイダの変更に対応するために、{@link android.app.job.JobScheduler} を使用することもできます。{@link android.app.job.JobInfo} オブジェクトは、{@link android.app.job.JobScheduler} がジョブをスケジュールするために使用するパラメータをカプセル化します。
ジョブの条件が満たされると、システムはこのジョブをアプリの {@link android.app.job.JobService} で実行します。
</p>
<p>
このドキュメントでは、アプリをこれらの新しい制限に対応させるために、
{@link android.app.job.JobScheduler} などの代替メソッドの使用法について説明します。
</p>
<h2 id="connectivity-action">
CONNECTIVITY_ACTION に対する制限
</h2>
<p>
N Developer Preview をターゲットにしたアプリは、マニフェストで {@link
android.net.ConnectivityManager#CONNECTIVITY_ACTION} ブロードキャストの受信登録をしていても、このブロードキャストを受信しません。また、このブロードキャストに依存している処理は開始されません。
これにより、ネットワークの変更をリッスンするアプリ、または端末が従量制ではないネットワークに接続したときにネットワーク アクティビティをまとめて実行するアプリに問題が発生する可能性があります。
Android フレームワークは、この制限を回避するためのいくつかのソリューションを備えていますが、アプリで実行するタスクに応じて、適切なソリューションを選択してください。
</p>
<p class="note">
<strong>注: </strong>{@link android.content.Context#registerReceiver Context.registerReceiver()} で登録された {@link android.content.BroadcastReceiver} は、アプリがフォアグラウンドにあるときにこれらのブロードキャストを継続して受信します。
</p>
<h3 id="sched-jobs">
従量制ではない接続でネットワーク ジョブをスケジュールする
</h3>
<p>
{@link android.app.job.JobInfo} オブジェクトをビルドするために {@link android.app.job.JobInfo.Builder JobInfo.Builder} を使用するときは、{@link
android.app.job.JobInfo.Builder#setRequiredNetworkType
setRequiredNetworkType()} メソッドを適用し、{@link android.app.job.JobInfo
JobInfo.NETWORK_TYPE_UNMETERED} をジョブ パラメータとして渡します。
次のコードサンプルは、端末が従量制ではないネットワークに接続し、充電しているときに実行するサービスをスケジュールします。
</p>
<pre>
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);
}
</pre>
<p>
ジョブの条件が満たされたとき、アプリはコールバックを受け取り、指定された {@code JobService.class} で {@link android.app.job.JobService#onStartJob onStartJob()} メソッドを実行します。
{@link
android.app.job.JobScheduler} 実装の例については、<a href="{@docRoot}samples/JobScheduler/index.html">JobScheduler サンプルアプリ</a>をご覧ください。
</p>
<p>
GMSCore サービスを使用し、Android 5.0(API レベル 21)以前をターゲットにしているアプリは、<a href="https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager">
{@code GcmNetworkManager}</a> を使用して {@code Task.NETWORK_STATE_UNMETERED} を指定できます。
</p>
<h3 id="monitor-conn">
アプリを実行しているときにネットワーク接続を監視する
</h3>
<p>
フォアグラウンドで実行中のアプリは、{@link
android.content.BroadcastReceiver} を登録することにより、{@code
CONNECTIVITY_CHANGE} を引き続きリッスンできます。ただし、{@link
android.net.ConnectivityManager} API は、特定のネットワーク条件が満たされたときだけコールバックをリクエストするより堅牢なメソッドを提供します。
</p>
<p>
{@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()} メソッドを実行します。
</p>
<p>
アプリは終了するか、{@link android.net.ConnectivityManager#unregisterNetworkCallback
unregisterNetworkCallback()} を呼び出すまで、コールバックを受信し続けます。
</p>
<h2 id="media-broadcasts">
NEW_PICTURE と NEW_VIDEO に対する制限
</h2>
<p>
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} を拡張することにより、代わりのソリューションを提供しています。
</p>
<h3 id="new-jobinfo">
新しい JobInfo メソッド
</h3>
<p>
N Developer Preview では、コンテンツ URI の変更でジョブをトリガーするために、{@link android.app.job.JobInfo} API に次のメソッドが追加されています。
</p>
<dl>
<dt>
{@code JobInfo.TriggerContentUri()}
</dt>
<dd>
コンテンツ URI の変更でジョブをトリガーするために必要なパラメータをカプセル化します。
</dd>
<dt>
{@code JobInfo.Builder.addTriggerContentUri()}
</dt>
<dd>
{@code TriggerContentUri} オブジェクトを {@link
android.app.job.JobInfo} に渡します。{@link android.database.ContentObserver} は、カプセル化されたコンテンツ URI を監視します。
ジョブに関連する複数の {@code
TriggerContentUri} オブジェクトがある場合、システムは、1 つのコンテンツ URI のみの変更を通知する場合でも、コールバックを提供します。
</dd>
<dd>
指定した URI の子孫のいずれかが変更された場合、ジョブをトリガーするために、{@code TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS} フラグを追加します。
このフラグは、{@link
android.content.ContentResolver#registerContentObserver
registerContentObserver()} に渡される {@code notifyForDescendants} パラメータに相当します。
</dd>
</dl>
<p class="note">
<strong>注:</strong> {@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} をスケジュールします。
</p>
<p>
次のサンプルコードは、システムが変更をコンテンツ URI {@code MEDIA_URI} に通知するときにトリガーされるジョブをスケジュールします。
</p>
<pre>
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());
}
</pre>
<p>
システムが特定のコンテンツ URI の変更を通知すると、アプリはコールバックを受け取り、{@link android.app.job.JobParameters} オブジェクトが {@code MediaContentJob.class} の {@link android.app.job.JobService#onStartJob onStartJob()} メソッドに渡されます。
</p>
<h3 id="new-jobparam">
新しい JobParameter メソッド
</h3>
<p>
また、N Developer Preview では、{@link android.app.job.JobParameters} が拡張され、ジョブをトリガーしたコンテンツ権限や URI についての有用な情報をアプリが受け取れるようになっています。
</p>
<dl>
<dt>
{@code Uri[] getTriggeredContentUris()}
</dt>
<dd>
ジョブをトリガーした URI の配列を返します。この配列は、ジョブをトリガーした URI がない場合(たとえば、期限切れ、またはその他の理由でジョブがトリガーされた場合)、または変更された URI の数が 50 を超える場合は、{@code
null} になります。
</dd>
<dt>
{@code String[] getTriggeredContentAuthorities()}
</dt>
<dd>
ジョブをトリガーしたコンテンツ権限の文字列配列を返します。
返された配列が {@code null} ではない場合、どの URI が変更されたかについて、詳細を取得するために {@code getTriggeredContentUris()} を使用します。
</dd>
</dl>
<p>
次のサンプルコードは、{@link
android.app.job.JobService#onStartJob JobService.onStartJob()} メソッドをオーバーライドし、ジョブを起動したコンテンツ権限と URI を記録します。
</p>
<pre>
@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;
}
</pre>
<h2 id="further-optimization">
アプリをさらに最適化する
</h2>
<p>
アプリをメモリ不足の端末またはメモリ不足の状況で実行するために最適化すると、パフォーマンスとユーザー エクスペリエンスが向上します。
バックグラウンド サービスと静的に登録された暗黙的なブロードキャスト レシーバーへの依存関係を削除すると、そのような端末上のアプリの動作が向上します。
N Developer Preview では、これらの問題を削減するための措置が講じられていますが、これらのバックグラウンド処理をまったく使用せずに、アプリが実行されるように最適化することをお勧めします。
</p>
<p>
N Developer Preview には、それらのバックグラウンド処理を無効にした状態でアプリの動作をテストするために使用できるいくつかの <a href="{@docRoot}tools/help/adb.html">Android デバッグ ブリッジ(ADB)</a>コマンドが追加されています。
</p>
<ul>
<li>暗黙的なブロードキャストとバックグラウンド サービスが利用できない状態をシミュレートするには、次のコマンドを入力します。
</li>
<li style="list-style: none; display: inline">
<pre class="no-pretty-print">
{@code $ adb shell cmd appops set RUN_IN_BACKGROUND ignore}
</pre>
</li>
<li>暗黙的なブロードキャストとバックグラウンド サービスを再度有効にするには、次のコマンドを入力します。
</li>
<li style="list-style: none; display: inline">
<pre class="no-pretty-print">
{@code $ adb shell cmd appops set RUN_IN_BACKGROUND allow}
</pre>
</li>
</ul>
|