page.title=Tối ưu hóa Chạy ngầm page.metaDescription=Các hạn chế mới đối với truyền phát không biểu thị. page.keywords="android N", "implicit broadcasts", "job scheduler" page.image=images/cards/card-nyc_2x.jpg @jd:body
Các tiến trình chạy ngầm có thể tiêu tốn bộ nhớ và pin. Ví dụ, một truyền phát không biểu thị có thể bắt đầu nhiều tiến trình chạy ngầm đã đăng ký để theo dõi chúng, ngay cả khi các tiến trình đó có thể không làm việc nhiều. Điều này có thể có ảnh hưởng lớn đến cả hiệu suất của thiết bị lẫn trải nghiệm của người dùng.
Để loại bỏ vấn đề này, N Developer Preview áp dụng các hạn chế sau:
Khuôn khổ Android cung cấp một số giải pháp để giảm thiểu sự cần thiết đối với các truyền phát không biểu thị. Ví dụ, {@link android.app.job.JobScheduler} và {@code GcmNetworkManager} cung cấp một cơ chế lên lịch hiệu quả cho các hoạt động mạng khi đáp ứng các điều kiện được chỉ định, ví dụ như kết nối tới mạng không đo lưu lượng. Bây giờ bạn cũng có thể sử dụng {@link android.app.job.JobScheduler} để phản ứng lại với các thay đổi đối với các trình cung cấp nội dung. Các đối tượng {@link android.app.job.JobInfo} gói gọn các tham số {@link android.app.job.JobScheduler} dùng để lên lịch tác vụ của bạn. Khi đáp ứng được các điều kiện của tác vụ, hệ thống sẽ thực thi tác vụ này trên {@link android.app.job.JobService} của ứng dụng của bạn.
Trong tài liệu này, chúng ta sẽ tìm hiểu cách sử dụng các phương thức thay thế, chẳng hạn như {@link android.app.job.JobScheduler}, để thích ứng ứng dụng của bạn với các hạn chế mới này.
Các ứng dụng nhắm đến N Developer Preview không nhận được truyền phát {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION} nếu chúng đăng ký nhận truyền phát trong bản kê khai của chúng, và các tiến trình phụ thuộc vào truyền phát này sẽ không khởi động. Điều này cũng đặt ra một vấn đề cho ứng dụng về việc theo dõi thay đổi mạng hoặc thực hiện các hoạt động mạng hàng loạt khi thiết bị kết nối với một mạng không đo lưu lượng. Một số giải pháp để tránh khỏi hạn chế này đã tồn tại trong khuôn khổ Android, nhưng chọn được một giải pháp phù hợp phụ thuộc vào những gì bạn muốn ứng dụng của bạn hoàn thành.
Lưu ý: Một{@link android.content.BroadcastReceiver} có đăng ký {@link android.content.Context#registerReceiver Context.registerReceiver()} tiếp tục nhận các truyền phát này trong khi ứng dụng đang ở tiền cảnh.
Khi sử dụng lớp{@link android.app.job.JobInfo.Builder JobInfo.Builder} để xây dựng đối tượng {@link android.app.job.JobInfo} của bạn, hãy áp dụng phương thức {@link android.app.job.JobInfo.Builder#setRequiredNetworkType setRequiredNetworkType()} và chuyển {@link android.app.job.JobInfo JobInfo.NETWORK_TYPE_UNMETERED} dưới dạng một tham số tác vụ. Đoạn mã mẫu sau lên lịch một dịch vụ để chạy khi thiết bị kết nối với một mạng không đo lưu lượng và đang sạc:
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); }
Khi các điều kiện cho tác vụ của bạn đã được đáp ứng, ứng dụng của bạn sẽ nhận được lệnh gọi lại để chạy phương thức{@link android.app.job.JobService#onStartJob onStartJob()}trong {@code JobService.class} được chỉ định. Để xem thêm các ví dụ về triển khai {@link android.app.job.JobScheduler} , hãy xem ứng dụng mẫu JobScheduler.
Các ứng dụng sử dụng dịch vụ GMSCore, và nhắm đến Android 5.0 (API mức 21) hoặc thấp hơn, có thể sử dụng {@code GcmNetworkManager} và quy định {@code Task.NETWORK_STATE_UNMETERED}.
Các ứng dụng đang chạy ở tiền cảnh vẫn có thể theo dõi {@code CONNECTIVITY_CHANGE} bằng một{@link android.content.BroadcastReceiver} đã đăng ký. Tuy nhiên, API {@link android.net.ConnectivityManager} cung cấp phương thức yêu cầu lệnh gọi lại hiệu quả hơn chỉ khi đáp ứng được các điều kiện được chỉ định.
Các đối tượng {@link android.net.NetworkRequest} định nghĩa các tham số của lệnh gọi lại mạng xét về {@link android.net.NetworkCapabilities}. Bạn tạo các đối tượng {@link android.net.NetworkRequest} bằng lớp {@link android.net.NetworkRequest.Builder NetworkRequest.Builder}. {@link android.net.ConnectivityManager#registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback) registerNetworkCallback()} rồi chuyển đối tượng{@link android.net.NetworkRequest} sang hệ thống. Khi đáp ứng được các điều kiện mạng, ứng dụng nhận lệnh gọi lại để thực thi phương thức {@link android.net.ConnectivityManager.NetworkCallback#onAvailable onAvailable()} như được định nghĩa trong lớp {@link android.net.ConnectivityManager.NetworkCallback} của nó.
Ứng dụng tiếp tục nhận lệnh gọi lại cho đến khi ứng dụng tồn tại hoặc nó gọi {@link android.net.ConnectivityManager#unregisterNetworkCallback unregisterNetworkCallback()}.
Trong N Developer Preview, ứng dụng không thể gửi hoặc nhận các truyền phát {@link android.hardware.Camera#ACTION_NEW_PICTURE} hoặc {@link android.hardware.Camera#ACTION_NEW_VIDEO}. Hạn chế này giúp loại bỏ các tác động về hiệu suất và trải nghiệm của người dùng khi một số ứng dụng phải thức dậy để xử lý một ảnh hoặc video mới. N Developer Preview mở rộng {@link android.app.job.JobInfo} và {@link android.app.job.JobParameters} để cung cấp một giải pháp thay thế.
Để kích hoạt tác vụ khi thay đổi URI nội dung, N Developer Preview sẽ mở rộng API{@link android.app.job.JobInfo} bằng các phương thức sau:
Lưu ý: {@code TriggerContentUri()} không thể được sử dụng kết hợp với {@link android.app.job.JobInfo.Builder#setPeriodic setPeriodic()} hoặc {@link android.app.job.JobInfo.Builder#setPersisted setPersisted()}. Để tiếp tục theo dõi các thay đổi nội dung, hãy lên lịch một {@link android.app.job.JobInfo} mới trước khi {@link android.app.job.JobService} của ứng dụng hoàn thành xử lý lệnh gọi lại gần đây nhất.
Đoạn mã mẫu sau lên lịch kích hoạt một tác vụ khi hệ thống báo cáo có sự thay đổi về URI nội dung, {@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()); }
Khi hệ thống báo cáo có sự thay đổi trong (các) URI nội dung được chỉ định, ứng dụng của bạn sẽ nhận được lệnh gọi lại và một đối tượng {@link android.app.job.JobParameters} được chuyển sang phương thức {@link android.app.job.JobService#onStartJob onStartJob()} trong {@code MediaContentJob.class}.
N Developer Preview cũng mở rộng {@link android.app.job.JobParameters} để cho phép ứng dụng của bạn nhận thông tin hữu ích về những gì thẩm quyền nội dung và các URI đã kích hoạt tác vụ:
Mã mẫu sau sẽ ghi đè lên phương thức {@link android.app.job.JobService#onStartJob JobService.onStartJob()} và và ghi lại các thẩm quyền nội dung và URI đã kích hoạt tác vụ.
@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; }
Tối ưu hóa ứng dụng của bạn để chạy trên các thiết bị có bộ nhớ ít, hoặc đang trong điều kiện bộ nhớ ít có thể cải thiện hiệu suất và trải nghiệm của người dùng. Loại bỏ các thành phần phụ thuộc trên các dịch vụ chạy ngầm và bộ thu truyền phát không biểu thị đã đăng ký tĩnh có thể giúp ứng dụng của bạn chạy tốt hơn trên các thiết bị như vậy. Mặc dù N Developer Preview thực hiện các bước để giảm bớt một vài trong số các vấn đề này, nhưng chúng tôi khuyến nghị bạn nên tối ưu ứng dụng của bạn để chạy hoàn toàn không cần sử dụng các tiến trình chạy ngầm này.
N Developer Preview giới thiệu một số lệnh Android Debug Bridge (ADB) bổ sung mà bạn có thể sử dụng để kiểm thử hành vi của ứng dụng bằng các tiến trình chạy ngầm đã bị vô hiệu hóa đó:
{@code $ adb shell cmd appops set RUN_IN_BACKGROUND ignore}
{@code $ adb shell cmd appops set RUN_IN_BACKGROUND allow}