1page.title=Dịch vụ 2@jd:body 3 4<div id="qv-wrapper"> 5<ol id="qv"> 6<h2>Trong tài liệu này</h2> 7<ol> 8<li><a href="#Basics">Nội dung Cơ bản</a></li> 9<ol> 10 <li><a href="#Declaring">Khai báo một dịch vụ trong bản kê khai</a></li> 11</ol> 12<li><a href="#CreatingAService">Tạo một Dịch vụ được Bắt đầu</a> 13 <ol> 14 <li><a href="#ExtendingIntentService">Mở rộng lớp IntentService</a></li> 15 <li><a href="#ExtendingService">Mở rộng lớp Dịch vụ</a></li> 16 <li><a href="#StartingAService">Bắt đầu một dịch vụ</a></li> 17 <li><a href="#Stopping">Dừng một dịch vụ</a></li> 18 </ol> 19</li> 20<li><a href="#CreatingBoundService">Tạo một Dịch vụ Gắn kết</a></li> 21<li><a href="#Notifications">Gửi Thông báo tới Người dùng</a></li> 22<li><a href="#Foreground">Chạy một Dịch vụ trong Tiền cảnh</a></li> 23<li><a href="#Lifecycle">Quản lý Vòng đời của một Dịch vụ</a> 24<ol> 25 <li><a href="#LifecycleCallbacks">Triển khai gọi lại vòng đời</a></li> 26</ol> 27</li> 28</ol> 29 30<h2>Lớp khóa</h2> 31<ol> 32 <li>{@link android.app.Service}</li> 33 <li>{@link android.app.IntentService}</li> 34</ol> 35 36<h2>Mẫu</h2> 37<ol> 38 <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.html">{@code 39 ServiceStartArguments}</a></li> 40 <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code 41 LocalService}</a></li> 42</ol> 43 44<h2>Xem thêm</h2> 45<ol> 46<li><a href="{@docRoot}guide/components/bound-services.html">Dịch vụ Gắn kết</a></li> 47</ol> 48 49</div> 50 51 52<p>{@link android.app.Service} là một thành phần ứng dụng có khả năng thực hiện 53các thao tác chạy kéo dài trong nền và không cung cấp giao diện người dùng. Một 54thành phần ứng dụng khác có thể bắt đầu một dịch vụ và nó sẽ tiếp tục chạy ngầm ngay cả khi người dùng 55chuyển sang một ứng dụng khác. Ngoài ra, một thành phần có thể gắn kết với một dịch vụ để 56tương tác với nó và thậm chí thực hiện truyền thông liên tiến trình (IPC). Ví dụ, một dịch vụ có thể 57xử lý các giao dịch mạng, phát nhạc, thực hiện I/O tệp, hoặc tương tác với một trình cung cấp nội dung, tất cả 58đều xuất phát từ nền.</p> 59 60<p>Về cơ bản, một dịch vụ có thể có hai dạng:</p> 61 62<dl> 63 <dt>Được bắt đầu</dt> 64 <dd>Dịch vụ có dạng "được bắt đầu" khi một thành phần ứng dụng (chẳng hạn như một hoạt động) bắt đầu nó bằng cách 65gọi {@link android.content.Context#startService startService()}. Sau khi được bắt đầu, dịch vụ 66có thể chạy ngầm vô thời hạn, ngay cả khi thành phần bắt đầu nó bị hủy. Thông thường, 67dịch vụ được bắt đầu sẽ thực hiện một thao tác đơn lẻ và không trả về kết quả cho hàm gọi. 68Ví dụ, nó có thể tải xuống hoặc tải lên một tệp thông qua mạng. Khi thao tác được hoàn thành, dịch vụ 69tự nó sẽ dừng lại.</dd> 70 <dt>Gắn kết</dt> 71 <dd>Dịch vụ có dạng "gắn kết" khi một thành phần ứng dụng gắn kết với nó bằng cách gọi {@link 72android.content.Context#bindService bindService()}. Dịch vụ gắn kết sẽ đưa ra 73một giao diện máy khách-máy chủ cho phép các thành phần tương tác với dịch vụ, gửi yêu cầu, nhận kết quả, và thậm chí 74làm vậy thông qua truyền thông liên tiến trình (IPC). Dịch vụ gắn kết chỉ chạy trong khi 75một thành phần ứng dụng khác được gắn kết với nó. Nhiều thành phần có thể gắn kết cùng lúc với dịch vụ, 76nhưng khi tất cả bị bỏ gắn kết thì dịch vụ sẽ bị hủy.</dd> 77</dl> 78 79<p>Mặc dù tài liệu này thường đề cập tới hai loại dịch vụ riêng rẽ, dịch vụ 80của bạn có thể hoạt động theo cả hai cách—nó có thể được bắt đầu (để chạy vô thời hạn) và cũng cho phép gắn kết. 81Đó đơn giản là vấn đề bạn có triển khai một cặp phương pháp gọi lại hay không: {@link 82android.app.Service#onStartCommand onStartCommand()} để cho phép thành phần bắt đầu nó và {@link 83android.app.Service#onBind onBind()} để cho phép nó gắn kết.</p> 84 85<p>Không phụ thuộc vào việc ứng dụng của bạn được bắt đầu, gắn kết, hay cả hai, bất kỳ thành phần ứng dụng nào 86cũng có thể sử dụng dịch vụ (thậm chí từ một ứng dụng riêng biệt), giống như cách mà bất kỳ thành phần nào cũng có thể sử dụng 87một hoạt động—bằng cách bắt đầu nó bằng một {@link android.content.Intent}. Tuy nhiên, bạn có thể khai báo 88dịch vụ là riêng tư trong tệp bản kê khai, và chặn truy cập từ các ứng dụng khác. Điều này 89được trình bày kỹ hơn trong phần về <a href="#Declaring">Khai báo dịch vụ trong 90bản kê khai</a>.</p> 91 92<p class="caution"><strong>Chú ý:</strong> Một dịch vụ chạy trong 93luồng chính của tiến trình lưu trữ của nó—dịch vụ <strong>không</strong> tạo luồng của chính nó 94và <strong>không</strong> chạy trong một tiến trình riêng biệt (trừ khi bạn quy định khác). Điều này có nghĩa 95là, nếu dịch vụ của bạn định thực hiện bất kỳ công việc nặng nào đối với CPU hay chặn các thao tác (chẳng hạn như phát lại MP3 96hay kết nối mạng), bạn nên tạo một luồng mới bên trong dịch vụ để thực hiện công việc đó. Bằng cách sử dụng 97một luồng riêng biệt, bạn sẽ giảm rủi ro gặp lỗi Ứng dụng Không Hồi đáp (ANR) và luồng chính của ứng dụng có thể 98vẫn dành riêng cho tương tác giữa người dùng với các hoạt động của bạn.</p> 99 100 101<h2 id="Basics">Nội dung Cơ bản</h2> 102 103<div class="sidebox-wrapper"> 104<div class="sidebox"> 105 <h3>Bạn nên sử dụng dịch vụ hay luồng?</h3> 106 <p>Dịch vụ đơn thuần là một thành phần có thể chạy ngầm ngay cả khi người dùng không 107đang tương tác với ứng dụng của bạn. Vì thế, bạn chỉ nên tạo một dịch vụ nếu đó là điều bạn 108cần.</p> 109 <p>Nếu bạn cần thực hiện công việc bên ngoài luồng chính của mình, nhưng chỉ trong khi người dùng đang tương tác với 110ứng dụng của bạn, thì thay vào đó, bạn nên tạo một luồng mới chứ không phải một dịch vụ. Ví 111dụ, nếu bạn muốn phát một bản nhạc, nhưng chỉ trong khi hoạt động của bạn đang chạy, bạn có thể tạo 112một luồng trong {@link android.app.Activity#onCreate onCreate()}, bắt đầu chạy nó trong {@link 113android.app.Activity#onStart onStart()}, rồi dừng nó trong {@link android.app.Activity#onStop 114onStop()}. Cũng xem xét việc sử dụng {@link android.os.AsyncTask} hoặc {@link android.os.HandlerThread}, 115thay vì sử dụng lớp {@link java.lang.Thread} truyền thống. Xem tài liệu <a href="{@docRoot}guide/components/processes-and-threads.html#Threads">Tiến trình và 116Luồng</a> để biết thêm thông tin về luồng.</p> 117 <p>Hãy nhớ rằng nếu bạn sử dụng một dịch vụ, nó vẫn chạy trong luồng chính của ứng dụng của bạn theo 118mặc định, vì thế bạn vẫn nên tạo một luồng mới trong dịch vụ nếu nó thực hiện các thao tác tăng cường hoặc 119chặn.</p> 120</div> 121</div> 122 123<p>Để tạo một dịch vụ, bạn phải tạo một lớp con của {@link android.app.Service} (hoặc một 124trong các lớp con hiện tại của nó). Trong triển khai của mình, bạn cần khống chế một số phương pháp gọi lại có chức năng 125xử lý những khía cạnh chính trong vòng đời của dịch vụ và cung cấp một cơ chế để các thành phần gắn kết với 126dịch vụ đó, nếu phù hợp. Những phương pháp gọi lại quan trọng nhất mà bạn nên khống chế là:</p> 127 128<dl> 129 <dt>{@link android.app.Service#onStartCommand onStartCommand()}</dt> 130 <dd>Hệ thống sẽ gọi phương pháp này khi một thành phần khác, chẳng hạn như một hoạt động, 131yêu cầu dịch vụ phải được bắt đầu, bằng cách gọi {@link android.content.Context#startService 132startService()}. Sau khi phương pháp này thực thi, dịch vụ sẽ được bắt đầu và có thể chạy vô thời hạn trong 133nền. Nếu bạn triển khai điều này, bạn có trách nhiệm dừng dịch vụ khi 134công việc của nó được hoàn thành, bằng cách gọi {@link android.app.Service#stopSelf stopSelf()} hoặc {@link 135android.content.Context#stopService stopService()}. (Nếu chỉ muốn cung cấp khả năng gắn kết, bạn không 136cần triển khai phương pháp này.)</dd> 137 <dt>{@link android.app.Service#onBind onBind()}</dt> 138 <dd>Hệ thống sẽ gọi phương pháp này khi một thành phần khác muốn gắn kết với 139dịch vụ (chẳng hạn như để thực hiện RPC), bằng cách gọi {@link android.content.Context#bindService 140bindService()}. Trong triển khai phương pháp này của mình, bạn phải cung cấp một giao diện mà các máy khách 141sử dụng để giao tiếp với dịch vụ, bằng cách trả về {@link android.os.IBinder}. Bạn phải luôn 142triển khai phương pháp này, nhưng nếu bạn không muốn cho phép gắn kết thì bạn nên trả về rỗng.</dd> 143 <dt>{@link android.app.Service#onCreate()}</dt> 144 <dd>Hệ thống sẽ gọi phương pháp này khi dịch vụ được tạo lập lần đầu, để thực hiện quy trình thiết lập một lần 145(trước khi nó có thể gọi hoặc {@link android.app.Service#onStartCommand onStartCommand()} hoặc 146{@link android.app.Service#onBind onBind()}). Nếu dịch vụ đã đang chạy, phương pháp này sẽ không được 147gọi.</dd> 148 <dt>{@link android.app.Service#onDestroy()}</dt> 149 <dd>Hệ thống sẽ gọi phương pháp này khi dịch vụ không còn được sử dụng và đang bị hủy. 150Dịch vụ của bạn sẽ triển khai phương pháp này để dọn dẹp mọi tài nguyên như luồng, đối tượng theo dõi 151được đăng ký, hàm nhận, v.v... Đây là lệnh gọi cuối cùng mà dịch vụ nhận được.</dd> 152</dl> 153 154<p>Nếu một thành phần bắt đầu dịch vụ bằng cách gọi {@link 155android.content.Context#startService startService()} (kết quả là một lệnh gọi tới {@link 156android.app.Service#onStartCommand onStartCommand()}), khi đó dịch vụ 157sẽ vẫn chạy tới khi tự nó dừng bằng {@link android.app.Service#stopSelf()} hoặc một 158thành phần khác dừng nó bằng cách gọi {@link android.content.Context#stopService stopService()}.</p> 159 160<p>Nếu một thành phần gọi 161{@link android.content.Context#bindService bindService()} để tạo dịch vụ (và {@link 162android.app.Service#onStartCommand onStartCommand()} <em>không</em> được gọi), khi đó dịch vụ sẽ chỉ chạy 163khi nào mà thành phần đó còn gắn kết với nó. Sau khi dịch vụ được bỏ gắn kết khỏi tất cả máy khách, hệ thống 164sẽ hủy nó.</p> 165 166<p>Hệ thống Android sẽ buộc dừng một dịch vụ chỉ khi bộ nhớ thấp và nó phải khôi phục tài nguyên 167của hệ thống cho hoạt động có tiêu điểm của người dùng. Nếu dịch vụ gắn kết với một hoạt động mà có tiêu điểm 168của người dùng, khi đó sẽ có ít khả năng nó sẽ bị tắt bỏ hơn, và nếu dịch vụ được khai báo là <a href="#Foreground">chạy trong tiền cảnh</a> (đề cập sau), khi đó nó sẽ hầu như không bao giờ bị tắt bỏ. 169Mặt khác, nếu dịch vụ được bắt đầu và chạy trong thời gian dài, hệ thống sẽ hạ thấp vị trí của nó 170trong danh sách tác vụ chạy ngầm qua thời gian và dịch vụ sẽ rất có thể bị 171tắt bỏ—nếu dịch vụ của bạn được bắt đầu, khi đó bạn phải thiết kế nó để 172xử lý việc khởi động lại do hệ thống một cách uyển chuyển. Nếu hệ thống tắt bỏ dịch vụ của bạn, nó sẽ khởi động lại dịch vụ ngay khi tài nguyên 173có sẵn trở lại (mặc dù điều này cũng phụ thuộc vào giá trị mà bạn trả về từ {@link 174android.app.Service#onStartCommand onStartCommand()}, vấn đề này sẽ được bàn sau). Để biết thêm thông tin 175về thời điểm mà hệ thống có thể hủy một dịch vụ, hãy xem tài liệu <a href="{@docRoot}guide/components/processes-and-threads.html">Tiến trình và Luồng</a> 176.</p> 177 178<p>Trong những phần sau, bạn sẽ thấy cách bạn có thể tạo từng loại dịch vụ và cách sử dụng 179nó từ các thành phần ứng dụng khác.</p> 180 181 182 183<h3 id="Declaring">Khai báo một dịch vụ trong bản kê khai</h3> 184 185<p>Giống như hoạt động (và các thành phần khác), bạn phải khai báo tất cả dịch vụ trong tệp bản kê khai 186của ứng dụng của mình.</p> 187 188<p>Để khai báo dịch vụ của bạn, hãy thêm một phần tử <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> làm 189con của phần tử <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a> 190. Ví dụ:</p> 191 192<pre> 193<manifest ... > 194 ... 195 <application ... > 196 <service android:name=".ExampleService" /> 197 ... 198 </application> 199</manifest> 200</pre> 201 202<p>Xem tham chiếu phần tử <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> 203để biết thêm thông tin về việc khai báo dịch vụ của bạn trong bản kê khai.</p> 204 205<p>Có các thuộc tính khác mà bạn có thể bao gồm trong phần tử <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> để 206định nghĩa các tính chất chẳng hạn như những quyền cần để bắt đầu dịch vụ và tiến trình mà 207dịch vụ sẽ chạy trong đó. Thuộc tính <a href="{@docRoot}guide/topics/manifest/service-element.html#nm">{@code android:name}</a> 208là thuộc tính bắt buộc duy nhất—nó quy định tên lớp của dịch vụ. Một khi 209bạn phát hành ứng dụng của mình, bạn không nên thay đổi tên này, vì nếu bạn làm vậy, bạn sẽ gặp rủi ro làm gãy 210mã do sự phụ thuộc vào các ý định biểu thị để bắt đầu hoặc gắn kết dịch vụ (đọc bài đăng blog, <a href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Những Điều 211Không Thay Đổi Được</a>). 212 213<p>Để đảm bảo ứng dụng của bạn được bảo mật, <strong>luôn sử dụng một ý định biểu thị khi bắt đầu hoặc gắn kết 214{@link android.app.Service}</strong> của bạn và không được khai báo bộ lọc ý định cho dịch vụ. Nếu 215điều trọng yếu là bạn phải cho phép một chút không rõ ràng về dịch vụ nào sẽ bắt đầu, bạn có thể 216cung cấp bộ lọc ý định cho dịch vụ của mình và loại bỏ tên thành phần khỏi {@link 217android.content.Intent}, nhưng sau đó bạn có thể đặt gói cho ý định bằng {@link 218android.content.Intent#setPackage setPackage()}, điều này cung cấp sự không rõ ràng vừa đủ cho 219dịch vụ mục tiêu đó.</p> 220 221<p>Ngoài ra, bạn có thể đảm bảo rằng dịch vụ của mình chỉ sẵn có cho ứng dụng của bạn bằng cách 222đưa vào thuộc tính <a href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code android:exported}</a> 223và đặt nó thành {@code "false"}. Điều này sẽ dừng việc các ứng dụng khác bắt đầu 224dịch vụ của bạn, ngay cả khi sử dụng một ý định biểu thị.</p> 225 226 227 228 229<h2 id="CreatingStartedService">Tạo một Dịch vụ được Bắt đầu</h2> 230 231<p>Dịch vụ được bắt đầu là dịch vụ mà một thành phần khác bắt đầu bằng cách gọi {@link 232android.content.Context#startService startService()}, kết quả là một lệnh gọi tới phương pháp 233{@link android.app.Service#onStartCommand onStartCommand()} của dịch vụ.</p> 234 235<p>Khi một dịch vụ được bắt đầu, nó có một vòng đời độc lập với 236thành phần đã bắt đầu nó và dịch vụ có thể chạy ngầm vô thời hạn, ngay cả khi 237thành phần bắt đầu nó bị hủy. Như vậy, dịch vụ sẽ tự dừng khi làm xong công việc của nó 238bằng cách gọi {@link android.app.Service#stopSelf stopSelf()}, hoặc một thành phần khác có thể dừng nó 239bằng cách gọi {@link android.content.Context#stopService stopService()}.</p> 240 241<p>Một thành phần ứng dụng chẳng hạn như một hoạt động có thể bắt đầu dịch vụ bằng cách gọi {@link 242android.content.Context#startService startService()} và chuyển một {@link android.content.Intent} 243trong đó quy định dịch vụ và bao gồm bất kỳ dữ liệu nào để cho dịch vụ sử dụng. Dịch vụ sẽ nhận 244{@link android.content.Intent} này trong phương pháp {@link android.app.Service#onStartCommand 245onStartCommand()}.</p> 246 247<p>Ví dụ, giả sử một hoạt động cần lưu một số dữ liệu vào cơ sở dữ liệu trực tuyến. Hoạt động có thể 248bắt đầu một dịch vụ đồng hành và truyền cho nó dữ liệu để lưu bằng cách chuyển một ý định tới {@link 249android.content.Context#startService startService()}. Dịch vụ sẽ nhận ý định trong {@link 250android.app.Service#onStartCommand onStartCommand()}, kết nối với Internet và thực hiện 251giao tác cơ sở dữ liệu. Khi giao tác được thực hiện, dịch vụ sẽ tự dừng lại và nó bị 252hủy.</p> 253 254<p class="caution"><strong>Chú ý:</strong> Một dịch vụ sẽ chạy trong cùng tiến trình như ứng dụng 255mà nó được khai báo trong đó và trong luồng chính của ứng dụng đó theo mặc định. Vì vậy, nếu dịch vụ của bạn 256thực hiện các thao tác tăng cường hoặc chặn trong khi người dùng tương tác với một hoạt động từ cùng 257ứng dụng, dịch vụ sẽ làm chậm hiệu năng của hoạt động. Để tránh tác động tới hiệu năng của 258ứng dụng, bạn nên bắt đầu một luồng mới bên trong dịch vụ.</p> 259 260<p>Thông thường, có hai lớp mà bạn có thể mở rộng để tạo một dịch vụ được bắt đầu:</p> 261<dl> 262 <dt>{@link android.app.Service}</dt> 263 <dd>Đây là lớp cơ bản cho tất cả dịch vụ. Khi bạn mở rộng lớp này, điều quan trọng là 264bạn tạo một luồng mới để thực hiện tất cả công việc của dịch vụ trong đó, do dịch vụ sử dụng luồng chính 265của ứng dụng của bạn, theo mặc định, điều này có thể làm chậm hiệu năng của bất kỳ hoạt động nào mà ứng dụng 266của bạn đang chạy.</dd> 267 <dt>{@link android.app.IntentService}</dt> 268 <dd>Đây là một lớp con của {@link android.app.Service} có chức năng sử dụng một luồng trình thực hiện để xử lý tất cả 269yêu cầu bắt đầu một cách lần lượt. Đây là lựa chọn tốt nhất nếu bạn không yêu cầu dịch vụ của mình 270xử lý đồng thời nhiều yêu cầu. Tất cả những gì bạn cần làm đó là triển khai {@link 271android.app.IntentService#onHandleIntent onHandleIntent()}, nó sẽ nhận ý định cho mỗi 272yêu cầu bắt đầu để bạn có thể thực hiện công việc chạy ngầm.</dd> 273</dl> 274 275<p>Các phần sau mô tả cách bạn có thể triển khai dịch vụ của mình bằng cách sử dụng một trong các cách cho những lớp 276này.</p> 277 278 279<h3 id="ExtendingIntentService">Mở rộng lớp IntentService</h3> 280 281<p>Vì phần lớn các dịch vụ được bắt đầu không cần xử lý nhiều yêu cầu một cách đồng thời 282(điều này thực sự có thể là một kịch bản tạo đa luồng nguy hiểm), có lẽ tốt nhất là nếu bạn 283triển khai dịch vụ của mình bằng cách sử dụng lớp {@link android.app.IntentService}.</p> 284 285<p>{@link android.app.IntentService} làm điều sau đây:</p> 286 287<ul> 288 <li>Tạo một luồng trình thực hiện mặc định để thực thi tất cả ý định được chuyển tới {@link 289android.app.Service#onStartCommand onStartCommand()} tách riêng với luồng 290chính của ứng dụng của bạn.</li> 291 <li>Tạo một hàng đợi công việc để chuyển lần lượt từng ý định tới triển khai {@link 292android.app.IntentService#onHandleIntent onHandleIntent()} của bạn, vì thế bạn không bao giờ phải 293lo lắng về vấn đề tạo đa luồng.</li> 294 <li>Dừng dịch vụ sau khi tất cả yêu cầu bắt đầu đều đã được xử lý, vì thế bạn không bao giờ phải gọi 295{@link android.app.Service#stopSelf}.</li> 296 <li>Cung cấp triển khai mặc định của {@link android.app.IntentService#onBind onBind()} mà 297trả về rỗng.</li> 298 <li>Cung cấp triển khai mặc định của {@link android.app.IntentService#onStartCommand 299onStartCommand()} mà gửi ý định tới hàng đợi công việc rồi tới triển khai {@link 300android.app.IntentService#onHandleIntent onHandleIntent()} của bạn.</li> 301</ul> 302 303<p>Tất cả đều nói lên một thực tế rằng tất cả những việc bạn cần làm đó là triển khai {@link 304android.app.IntentService#onHandleIntent onHandleIntent()} để thực hiện công việc mà 305máy khách cung cấp. (Mặc dù bạn cũng cần cung cấp một hàm dựng nhỏ cho dịch vụ.)</p> 306 307<p>Sau đây là ví dụ về triển khai {@link android.app.IntentService}:</p> 308 309<pre> 310public class HelloIntentService extends IntentService { 311 312 /** 313 * A constructor is required, and must call the super {@link android.app.IntentService#IntentService} 314 * constructor with a name for the worker thread. 315 */ 316 public HelloIntentService() { 317 super("HelloIntentService"); 318 } 319 320 /** 321 * The IntentService calls this method from the default worker thread with 322 * the intent that started the service. When this method returns, IntentService 323 * stops the service, as appropriate. 324 */ 325 @Override 326 protected void onHandleIntent(Intent intent) { 327 // Normally we would do some work here, like download a file. 328 // For our sample, we just sleep for 5 seconds. 329 long endTime = System.currentTimeMillis() + 5*1000; 330 while (System.currentTimeMillis() < endTime) { 331 synchronized (this) { 332 try { 333 wait(endTime - System.currentTimeMillis()); 334 } catch (Exception e) { 335 } 336 } 337 } 338 } 339} 340</pre> 341 342<p>Đó là tất cả những gì bạn cần: một hàm dựng và triển khai {@link 343android.app.IntentService#onHandleIntent onHandleIntent()}.</p> 344 345<p>Nếu bạn quyết định cũng khống chế các phương pháp gọi lại khác, chẳng hạn như {@link 346android.app.IntentService#onCreate onCreate()}, {@link 347android.app.IntentService#onStartCommand onStartCommand()}, hoặc {@link 348android.app.IntentService#onDestroy onDestroy()}, hãy nhớ gọi ra siêu triển khai, sao 349cho {@link android.app.IntentService} có thể xử lý hợp lý vòng đời của luồng trình thực hiện.</p> 350 351<p>Ví dụ, {@link android.app.IntentService#onStartCommand onStartCommand()} phải trả về 352triển khai mặc định (đó là cách mà ý định được chuyển tới {@link 353android.app.IntentService#onHandleIntent onHandleIntent()}):</p> 354 355<pre> 356@Override 357public int onStartCommand(Intent intent, int flags, int startId) { 358 Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); 359 return super.onStartCommand(intent,flags,startId); 360} 361</pre> 362 363<p>Bên cạnh {@link android.app.IntentService#onHandleIntent onHandleIntent()}, phương pháp duy nhất mà 364từ đó bạn không cần gọi siêu lớp là {@link android.app.IntentService#onBind 365onBind()} (nhưng bạn chỉ cần triển khai điều đó nếu dịch vụ của bạn cho phép gắn kết).</p> 366 367<p>Trong phần tiếp theo, bạn sẽ thấy cách mà cùng loại dịch vụ được triển khai khi mở rộng 368lớp {@link android.app.Service} cơ sở, nó có nhiều mã hơn nhưng có thể 369phù hợp nếu bạn cần xử lý các yêu cầu bắt đầu đồng thời.</p> 370 371 372<h3 id="ExtendingService">Mở rộng lớp Dịch vụ</h3> 373 374<p>Như bạn thấy trong phần trước, sử dụng {@link android.app.IntentService} giúp việc 375triển khai một dịch vụ được bắt đầu của bạn trở nên rất đơn giản. Tuy nhiên, nếu bạn cần dịch vụ của mình 376thực hiện tạo đa luồng (thay vì xử lý các yêu cầu bắt đầu thông qua một hàng đợi công việc), khi đó bạn 377có thể mở rộng lớp {@link android.app.Service} để xử lý từng ý định.</p> 378 379<p>Để so sánh, đoạn mã mẫu sau là triển khai lớp {@link 380android.app.Service} mà thực hiện chính xác cùng công việc như ví dụ bên trên bằng cách sử dụng {@link 381android.app.IntentService}. Cụ thể, đối với mỗi yêu cầu bắt đầu, nó sẽ sử dụng một luồng trình thực hiện để thực hiện 382công việc và chỉ xử lý lần lượt từng yêu cầu một.</p> 383 384<pre> 385public class HelloService extends Service { 386 private Looper mServiceLooper; 387 private ServiceHandler mServiceHandler; 388 389 // Handler that receives messages from the thread 390 private final class ServiceHandler extends Handler { 391 public ServiceHandler(Looper looper) { 392 super(looper); 393 } 394 @Override 395 public void handleMessage(Message msg) { 396 // Normally we would do some work here, like download a file. 397 // For our sample, we just sleep for 5 seconds. 398 long endTime = System.currentTimeMillis() + 5*1000; 399 while (System.currentTimeMillis() < endTime) { 400 synchronized (this) { 401 try { 402 wait(endTime - System.currentTimeMillis()); 403 } catch (Exception e) { 404 } 405 } 406 } 407 // Stop the service using the startId, so that we don't stop 408 // the service in the middle of handling another job 409 stopSelf(msg.arg1); 410 } 411 } 412 413 @Override 414 public void onCreate() { 415 // Start up the thread running the service. Note that we create a 416 // separate thread because the service normally runs in the process's 417 // main thread, which we don't want to block. We also make it 418 // background priority so CPU-intensive work will not disrupt our UI. 419 HandlerThread thread = new HandlerThread("ServiceStartArguments", 420 Process.THREAD_PRIORITY_BACKGROUND); 421 thread.start(); 422 423 // Get the HandlerThread's Looper and use it for our Handler 424 mServiceLooper = thread.getLooper(); 425 mServiceHandler = new ServiceHandler(mServiceLooper); 426 } 427 428 @Override 429 public int onStartCommand(Intent intent, int flags, int startId) { 430 Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); 431 432 // For each start request, send a message to start a job and deliver the 433 // start ID so we know which request we're stopping when we finish the job 434 Message msg = mServiceHandler.obtainMessage(); 435 msg.arg1 = startId; 436 mServiceHandler.sendMessage(msg); 437 438 // If we get killed, after returning from here, restart 439 return START_STICKY; 440 } 441 442 @Override 443 public IBinder onBind(Intent intent) { 444 // We don't provide binding, so return null 445 return null; 446 } 447 448 @Override 449 public void onDestroy() { 450 Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); 451 } 452} 453</pre> 454 455<p>Như bạn có thể thấy, có nhiều việc hơn nhiều so với việc sử dụng {@link android.app.IntentService}.</p> 456 457<p>Tuy nhiên, do bạn tự mình xử lý từng lệnh gọi đến {@link android.app.Service#onStartCommand 458onStartCommand()}, bạn có thể thực hiện nhiều yêu cầu một cách đồng thời. Đó không phải là việc 459mà ví dụ này làm, nhưng nếu đó là việc bạn muốn, vậy bạn có thể tạo một luồng mới cho từng 460yêu cầu và ngay lập tức trả chúng về (thay vì đợi tới khi yêu cầu trước hoàn thành).</p> 461 462<p>Để ý rằng phương pháp {@link android.app.Service#onStartCommand onStartCommand()} phải trả về một 463số nguyên. Số nguyên là một giá trị mô tả cách hệ thống nên tiếp tục dịch vụ trong 464trường hợp hệ thống tắt bỏ nó (như được đề cập ở trên, triển khai mặc định cho {@link 465android.app.IntentService} sẽ xử lý điều này cho bạn dù bạn có thể sửa đổi nó). Giá trị trả về 466từ {@link android.app.Service#onStartCommand onStartCommand()} phải là một trong các 467hằng số sau:</p> 468 469<dl> 470 <dt>{@link android.app.Service#START_NOT_STICKY}</dt> 471 <dd>Nếu hệ thống tắt bỏ dịch vụ sau khi {@link android.app.Service#onStartCommand 472onStartCommand()} trả về, <em>không</em> được tạo lại dịch vụ đó, trừ khi có các ý định 473đang chờ để được chuyển. Đây là lựa chọn an toàn nhất để tránh chạy dịch vụ của bạn khi không cần thiết 474và khi ứng dụng của bạn có thể đơn thuần khởi động lại bất kỳ công việc chưa hoàn thành nào.</dd> 475 <dt>{@link android.app.Service#START_STICKY}</dt> 476 <dd>Nếu hệ thống tắt bỏ dịch vụ sau khi {@link android.app.Service#onStartCommand 477onStartCommand()} trả về, hãy tạo lại dịch vụ và gọi {@link 478android.app.Service#onStartCommand onStartCommand()}, nhưng <em>không</em> chuyển lại ý định cuối cùng. 479Thay vào đó, hệ thống sẽ gọi {@link android.app.Service#onStartCommand onStartCommand()} bằng một 480ý định rỗng, trừ khi có các ý định đang chờ để bắt đầu dịch vụ, trong trường hợp đó, 481những ý định này sẽ được chuyển. Điều này phù hợp với các trình phát phương tiện (hoặc dịch vụ tương tự) mà không 482đang thực thi lệnh, nhưng đang chạy vô thời hạn và chờ một tác vụ.</dd> 483 <dt>{@link android.app.Service#START_REDELIVER_INTENT}</dt> 484 <dd>Nếu hệ thống tắt bỏ dịch vụ sau khi {@link android.app.Service#onStartCommand 485onStartCommand()} trả về, hãy tạo lại dịch vụ và gọi {@link 486android.app.Service#onStartCommand onStartCommand()} bằng ý định cuối cùng được chuyển tới 487dịch vụ. Mọi ý định chờ đều được chuyển lần lượt. Điều này phù hợp với các dịch vụ đang 488chủ động thực hiện một công việc mà nên được tiếp tục ngay lập tức, chẳng hạn như tải xuống một tệp.</dd> 489</dl> 490<p>Để biết thêm chi tiết về những giá trị trả về này, hãy xem tài liệu tham khảo được liên kết cho từng 491hằng số.</p> 492 493 494 495<h3 id="StartingAService">Bắt đầu một Dịch vụ</h3> 496 497<p>Bạn có thể bắt đầu một dịch vụ từ một hoạt động hoặc thành phần ứng dụng khác bằng cách chuyển một 498{@link android.content.Intent} (quy định dịch vụ sẽ bắt đầu) đến {@link 499android.content.Context#startService startService()}. Hệ thống Android sẽ gọi phương pháp {@link 500android.app.Service#onStartCommand onStartCommand()} của dịch vụ và chuyển cho nó {@link 501android.content.Intent}. (Bạn tuyệt đối không nên trực tiếp gọi {@link android.app.Service#onStartCommand 502onStartCommand()}.)</p> 503 504<p>Ví dụ, một hoạt động có thể bắt đầu dịch vụ ví dụ trong phần trước ({@code 505HelloSevice}) bằng cách sử dụng một ý định biểu thị với {@link android.content.Context#startService 506startService()}:</p> 507 508<pre> 509Intent intent = new Intent(this, HelloService.class); 510startService(intent); 511</pre> 512 513<p>Phương pháp {@link android.content.Context#startService startService()} ngay lập tức trả về và 514hệ thống Android sẽ gọi phương pháp {@link android.app.Service#onStartCommand 515onStartCommand()} của dịch vụ. Nếu dịch vụ không đang chạy, trước tiên hệ thống sẽ gọi {@link 516android.app.Service#onCreate onCreate()}, rồi gọi {@link android.app.Service#onStartCommand 517onStartCommand()}.</p> 518 519<p>Nếu dịch vụ cũng không cung cấp khả năng gắn kết, ý định được chuyển bằng {@link 520android.content.Context#startService startService()} sẽ là phương thức giao tiếp duy nhất giữa 521thành phần ứng dụng và dịch vụ. Tuy nhiên, nếu bạn muốn dịch vụ gửi một kết quả trở lại, khi đó 522máy khách mà bắt đầu dịch vụ có thể tạo một {@link android.app.PendingIntent} cho một quảng bá 523(bằng {@link android.app.PendingIntent#getBroadcast getBroadcast()}) và chuyển nó tới dịch vụ 524trong {@link android.content.Intent} mà bắt đầu dịch vụ. Khi đó, dịch vụ có thể sử dụng 525quảng bá để chuyển kết quả.</p> 526 527<p>Nhiều yêu cầu bắt đầu dịch vụ sẽ dẫn đến nhiều lệnh gọi tương ứng tới 528{@link android.app.Service#onStartCommand onStartCommand()} của dịch vụ. Tuy nhiên, chỉ có một yêu cầu dừng 529dịch vụ (bằng {@link android.app.Service#stopSelf stopSelf()} hoặc {@link 530android.content.Context#stopService stopService()}) là bắt buộc để dừng nó.</p> 531 532 533<h3 id="Stopping">Dừng một dịch vụ</h3> 534 535<p>Dịch vụ được bắt đầu phải quản lý vòng đời của chính nó. Cụ thể, hệ thống không dừng 536hay hủy dịch vụ trừ khi nó phải khôi phục bộ nhớ của hệ thống và dịch vụ 537sẽ tiếp tục chạy sau khi {@link android.app.Service#onStartCommand onStartCommand()} trả về. Vì vậy, 538dịch vụ phải tự dừng bằng cách gọi {@link android.app.Service#stopSelf stopSelf()} hoặc một thành phần 539khác có thể dừng nó bằng cách gọi {@link android.content.Context#stopService stopService()}.</p> 540 541<p>Sau khi được yêu cầu dừng bằng {@link android.app.Service#stopSelf stopSelf()} hoặc {@link 542android.content.Context#stopService stopService()}, hệ thống sẽ hủy dịch vụ ngay khi 543có thể.</p> 544 545<p>Tuy nhiên, nếu dịch vụ của bạn xử lý nhiều yêu cầu {@link 546android.app.Service#onStartCommand onStartCommand()} đồng thời, khi đó bạn không nên dừng 547dịch vụ khi bạn đã hoàn thành xử lý yêu cầu bắt đầu, vì bạn có thể đã nhận được một 548yêu cầu bắt đầu mới kể từ thời điểm đó (dừng khi kết thúc yêu cầu thứ nhất sẽ chấm dứt yêu cầu thứ hai). Để tránh 549vấn đề này, bạn có thể sử dụng {@link android.app.Service#stopSelf(int)} để đảm bảo rằng yêu cầu 550dừng dịch vụ của bạn luôn được dựa trên yêu cầu bắt đầu gần đây nhất. Cụ thể, khi bạn gọi {@link 551android.app.Service#stopSelf(int)}, bạn sẽ chuyển ID của yêu cầu bắt đầu (<code>startId</code> 552được chuyển tới {@link android.app.Service#onStartCommand onStartCommand()}) mà yêu cầu dừng của bạn 553tương ứng với. Khi đó, nếu dịch vụ đã nhận được một yêu cầu bắt đầu mới trước khi bạn có thể gọi {@link 554android.app.Service#stopSelf(int)}, vậy ID sẽ không khớp và dịch vụ sẽ không dừng.</p> 555 556<p class="caution"><strong>Chú ý:</strong> Điều quan trọng là ứng dụng của bạn dừng dịch vụ của nó 557khi nó hoàn thành xong công việc để tránh lãng phí tài nguyên của hệ thống và tốn pin. Nếu cần, 558các thành phần khác có thể dừng dịch vụ bằng cách gọi {@link 559android.content.Context#stopService stopService()}. Ngay cả khi bạn kích hoạt gắn kết cho dịch vụ, 560bạn phải luôn tự mình dừng dịch vụ nếu dịch vụ đã nhận được lệnh gọi tới {@link 561android.app.Service#onStartCommand onStartCommand()}.</p> 562 563<p>Để biết thêm thông tin về vòng đời của một dịch vụ, hãy xem phần bên dưới về <a href="#Lifecycle">Quản lý Vòng đời của một Dịch vụ</a>.</p> 564 565 566 567<h2 id="CreatingBoundService">Tạo một Dịch vụ Gắn kết</h2> 568 569<p>Dịch vụ gắn kết là một dịch vụ cho phép các thành phần ứng dụng gắn kết với nó bằng cách gọi {@link 570android.content.Context#bindService bindService()} để tạo một kết nối lâu dài 571(và thường không cho phép các thành phần <em>bắt đầu</em> nó bằng cách gọi {@link 572android.content.Context#startService startService()}).</p> 573 574<p>Bạn nên tạo một dịch vụ gắn kết khi muốn tương tác với dịch vụ từ hoạt động 575và các thành phần khác trong ứng dụng của mình hoặc để hiển thị một số tính năng trong ứng dụng của bạn cho 576các ứng dụng khác thông qua truyền thông liên tiến trình (IPC).</p> 577 578<p>Để tạo một dịch vụ gắn kết, bạn phải triển khai phương pháp gọi lại {@link 579android.app.Service#onBind onBind()} để trả về một {@link android.os.IBinder} mà 580định nghĩa giao diện cho giao tiếp với dịch vụ đó. Khi đó, các thành phần ứng dụng khác có thể gọi 581{@link android.content.Context#bindService bindService()} để truy xuất giao diện và 582bắt đầu các phương pháp gọi trên dịch vụ. Dịch vụ tồn tại chỉ nhằm phục vụ thành phần ứng dụng mà 583được gắn kết với nó, vì thế khi không có thành phần được gắn kết với dịch vụ, hệ thống sẽ hủy nó 584(bạn <em>không</em> cần dừng một dịch vụ gắn kết theo cách phải làm khi dịch vụ được bắt đầu 585thông qua {@link android.app.Service#onStartCommand onStartCommand()}).</p> 586 587<p>Để tạo một dịch vụ gắn kết, điều đầu tiên bạn phải làm là định nghĩa giao diện quy định 588cách thức mà một máy khách có thể giao tiếp với dịch vụ. Giao diện giữa dịch vụ và 589máy khách này phải là một triển khai {@link android.os.IBinder} và được dịch vụ của bạn phải 590trả về từ phương pháp gọi lại {@link android.app.Service#onBind 591onBind()}. Sau khi máy khách nhận được {@link android.os.IBinder}, nó có thể bắt đầu 592tương tác với dịch vụ thông qua giao diện đó.</p> 593 594<p>Nhiều máy khách có thể gắn kết với dịch vụ đồng thời. Khi một máy khách hoàn thành tương tác với 595dịch vụ, nó sẽ gọi {@link android.content.Context#unbindService unbindService()} để bỏ gắn kết. Sau khi 596không còn máy khách nào được gắn kết với dịch vụ, hệ thống sẽ hủy dịch vụ.</p> 597 598<p>Có nhiều cách để triển khai một dịch vụ gắn kết và triển khai sẽ phức tạp 599hơn so với dịch vụ được bắt đầu, vì thế nội dung bàn về dịch vụ gắn kết được trình bày trong một 600tài liệu riêng về <a href="{@docRoot}guide/components/bound-services.html">Dịch vụ Gắn kết</a>.</p> 601 602 603 604<h2 id="Notifications">Gửi Thông báo tới Người dùng</h2> 605 606<p>Sau khi chạy, một dịch vụ có thể thông báo cho người dùng về sự kiện bằng cách sử dụng <a href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Thông báo Cửa sổ</a> hoặc <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Thông báo Thanh Trạng thái</a>.</p> 607 608<p>Thông báo cửa sổ là một thông báo xuất hiện một lúc trên bề mặt của cửa sổ hiện tại 609rồi biến mất, trong khi thông báo thanh trạng thái cung cấp một biểu tượng trong thanh trạng thái cùng một 610thông báo, người dùng có thể chọn nó để thực hiện một hành động (chẳng hạn như bắt đầu một hoạt động).</p> 611 612<p>Thông thường thông báo thanh trạng thái là kỹ thuật tốt nhất khi một công việc nền nào đó đã hoàn thành 613(chẳng hạn như một tệp đã hoàn thành 614việc tải xuống) và lúc này người dùng có thể hành động dựa trên nó. Khi người dùng chọn thông báo từ dạng xem mở rộng 615, thông báo có thể bắt đầu một hoạt động (chẳng hạn như xem tệp được tải xuống).</p> 616 617<p>Xem hướng dẫn dành cho nhà phát triển <a href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Thông báo Cửa sổ</a> hoặc <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Thông báo Thanh Trạng thái</a> 618để biết thêm thông tin.</p> 619 620 621 622<h2 id="Foreground">Chạy một Dịch vụ trong Tiền cảnh</h2> 623 624<p>Dịch vụ tiền cảnh là một dịch vụ được coi là điều mà 625người dùng đang chủ động quan tâm, vì thế nó không được đề nghị để hệ thống tắt bỏ khi bộ nhớ thấp. Dịch vụ 626tiền cảnh phải cung cấp một thông báo cho thanh trạng thái, nó được đặt dưới tiêu đề 627"Đang diễn ra", điều này có nghĩa là thông báo không thể loại bỏ được trừ khi dịch vụ 628bị dừng hoặc loại bỏ khỏi tiền cảnh.</p> 629 630<p>Ví dụ, một trình chơi nhạc đang phát nhạc từ một dịch vụ nên được đặt để chạy trong 631tiền cảnh, vì người dùng rõ ràng ý thức được 632hoạt động của nó. Thông báo trong thanh trạng thái có thể cho biết bài hát đang chơi và cho phép 633người dùng khởi chạy một hoạt động để tương tác với trình chơi nhạc.</p> 634 635<p>Để yêu cầu dịch vụ của bạn chạy trong tiền cảnh, hãy gọi {@link 636android.app.Service#startForeground startForeground()}. Phương pháp này dùng hai tham số: một số nguyên 637để xác định duy nhất thông báo và {@link 638android.app.Notification} cho thanh trạng thái. Ví dụ:</p> 639 640<pre> 641Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text), 642 System.currentTimeMillis()); 643Intent notificationIntent = new Intent(this, ExampleActivity.class); 644PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); 645notification.setLatestEventInfo(this, getText(R.string.notification_title), 646 getText(R.string.notification_message), pendingIntent); 647startForeground(ONGOING_NOTIFICATION_ID, notification); 648</pre> 649 650<p class="caution"><strong>Chú ý:</strong> ID số nguyên mà bạn cấp cho {@link 651android.app.Service#startForeground startForeground()} không được bằng 0.</p> 652 653 654<p>Để xóa bỏ dịch vụ khỏi tiền cảnh, hãy gọi {@link 655android.app.Service#stopForeground stopForeground()}. Phương pháp này dùng một boolean, cho biết 656có loại bỏ cả thông báo thanh trạng thái hay không. Phương pháp này <em>không</em> dừng 657dịch vụ. Tuy nhiên, nếu bạn dừng dịch vụ trong khi nó vẫn đang chạy trong tiền cảnh, khi đó thông báo 658cũng bị loại bỏ.</p> 659 660<p>Để biết thêm thông tin về thông báo, hãy xem phần <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Tạo Thông báo 661Thanh Trạng thái</a>.</p> 662 663 664 665<h2 id="Lifecycle">Quản lý Vòng đời của một Dịch vụ</h2> 666 667<p>Vòng đời của một dịch vụ đơn giản hơn nhiều so với vòng đời của một hoạt động. Tuy nhiên, một điều thậm chí còn quan trọng hơn 668đó là bạn phải thật chú ý tới cách dịch vụ của bạn được tạo và hủy, bởi một dịch vụ 669có thể chạy ngầm mà người dùng không biết.</p> 670 671<p>Vòng đời của dịch vụ—từ khi nó được tạo tới khi nó bị hủy—có thể đi theo hai 672con đường khác nhau:</p> 673 674<ul> 675<li>Dịch vụ được bắt đầu 676 <p>Dịch vụ được tạo khi một thành phần khác gọi {@link 677android.content.Context#startService startService()}. Sau đó, dịch vụ sẽ chạy vô thời hạn và phải 678tự dừng bằng cách gọi {@link 679android.app.Service#stopSelf() stopSelf()}. Một thành phần khác cũng có thể dừng 680dịch vụ bằng cách gọi {@link android.content.Context#stopService 681stopService()}. Khi dịch vụ bị dừng, hệ thống sẽ hủy nó.</p></li> 682 683<li>Dịch vụ gắn kết 684 <p>Dịch vụ được tạo khi một thành phần khác (máy khách) gọi {@link 685android.content.Context#bindService bindService()}. Khi đó, máy khách giao tiếp với dịch vụ 686thông qua một giao diện {@link android.os.IBinder}. Máy khách có thể đóng kết nối bằng cách gọi 687{@link android.content.Context#unbindService unbindService()}. Nhiều máy khách có thể gắn kết với 688cùng dịch vụ và khi tất cả chúng bỏ gắn kết, hệ thống sẽ hủy dịch vụ. (Dịch vụ 689<em>không</em> cần tự mình dừng.)</p></li> 690</ul> 691 692<p>Hai con đường này hoàn toàn riêng biệt. Cụ thể, bạn có thể gắn kết với một dịch vụ đã 693được bắt đầu bằng {@link android.content.Context#startService startService()}. Ví dụ, một dịch vụ 694nhạc nền có thể được bắt đầu bằng cách gọi {@link android.content.Context#startService 695startService()} bằng một {@link android.content.Intent} mà sẽ nhận biết nhạc để phát. Sau đó, 696có thể là khi người dùng muốn thực thi một quyền điều khiển đối với trình phát đó hoặc lấy thông tin về 697bài hát đang phát, hoạt động có thể gắn kết với dịch vụ bằng cách gọi {@link 698android.content.Context#bindService bindService()}. Trong những trường hợp như vậy, {@link 699android.content.Context#stopService stopService()} hoặc {@link android.app.Service#stopSelf 700stopSelf()} không thực sự dừng dịch vụ tới khi tất cả máy khách bỏ gắn kết. </p> 701 702 703<h3 id="LifecycleCallbacks">Triển khai gọi lại vòng đời</h3> 704 705<p>Giống như một hoạt động, dịch vụ có các phương pháp gọi lại vòng đời mà bạn có thể triển khai để theo dõi 706những thay đổi về trạng thái của dịch vụ và thực hiện công việc tại những thời điểm phù hợp. Dịch vụ khung sau 707minh họa từng phương pháp vòng đời:</p> 708 709<pre> 710public class ExampleService extends Service { 711 int mStartMode; // indicates how to behave if the service is killed 712 IBinder mBinder; // interface for clients that bind 713 boolean mAllowRebind; // indicates whether onRebind should be used 714 715 @Override 716 public void {@link android.app.Service#onCreate onCreate}() { 717 // The service is being created 718 } 719 @Override 720 public int {@link android.app.Service#onStartCommand onStartCommand}(Intent intent, int flags, int startId) { 721 // The service is starting, due to a call to {@link android.content.Context#startService startService()} 722 return <em>mStartMode</em>; 723 } 724 @Override 725 public IBinder {@link android.app.Service#onBind onBind}(Intent intent) { 726 // A client is binding to the service with {@link android.content.Context#bindService bindService()} 727 return <em>mBinder</em>; 728 } 729 @Override 730 public boolean {@link android.app.Service#onUnbind onUnbind}(Intent intent) { 731 // All clients have unbound with {@link android.content.Context#unbindService unbindService()} 732 return <em>mAllowRebind</em>; 733 } 734 @Override 735 public void {@link android.app.Service#onRebind onRebind}(Intent intent) { 736 // A client is binding to the service with {@link android.content.Context#bindService bindService()}, 737 // after onUnbind() has already been called 738 } 739 @Override 740 public void {@link android.app.Service#onDestroy onDestroy}() { 741 // The service is no longer used and is being destroyed 742 } 743} 744</pre> 745 746<p class="note"><strong>Lưu ý:</strong> Không như các phương pháp gọi lại vòng đời của hoạt động, bạn 747<em>không</em> phải gọi triển khai siêu lớp với những phương pháp gọi lại này.</p> 748 749<img src="{@docRoot}images/service_lifecycle.png" alt="" /> 750<p class="img-caption"><strong>Hình 2.</strong> Vòng đời dịch vụ. Sơ đồ phía bên trái 751minh họa vòng đời khi dịch vụ được tạo bằng {@link android.content.Context#startService 752startService()} và sơ đồ phía bên phải minh họa vòng đời khi dịch vụ được tạo 753bằng {@link android.content.Context#bindService bindService()}.</p> 754 755<p>Bằng việc triển khai những phương pháp này, bạn có thể theo dõi hai vòng lặp lồng nhau trong vòng đời của dịch vụ: </p> 756 757<ul> 758<li><strong>Toàn bộ vòng đời</strong> của một dịch vụ xảy ra giữa thời điểm gọi {@link 759android.app.Service#onCreate onCreate()} và thời điểm {@link 760android.app.Service#onDestroy} trả về. Giống như hoạt động, dịch vụ thực hiện thiết lập ban đầu của nó trong 761{@link android.app.Service#onCreate onCreate()} và giải phóng tất cả tài nguyên còn lại trong {@link 762android.app.Service#onDestroy onDestroy()}. Ví dụ, một 763dịch vụ phát lại nhạc có thể tạo luồng mà tại đó nhạc sẽ được phát trong {@link 764android.app.Service#onCreate onCreate()}, sau đó dừng luồng trong {@link 765android.app.Service#onDestroy onDestroy()}. 766 767<p>Các phương pháp {@link android.app.Service#onCreate onCreate()} và {@link android.app.Service#onDestroy 768onDestroy()} được gọi cho tất cả dịch vụ, dù 769chúng được tạo bởi {@link android.content.Context#startService startService()} hay {@link 770android.content.Context#bindService bindService()}.</p></li> 771 772<li><strong>Vòng đời hiện hoạt</strong> của một dịch vụ sẽ bắt đầu bằng một lệnh gọi đến hoặc {@link 773android.app.Service#onStartCommand onStartCommand()} hoặc {@link android.app.Service#onBind onBind()}. 774Mỗi phương pháp sẽ được giao {@link 775android.content.Intent} mà được chuyển tương ứng cho hoặc {@link android.content.Context#startService 776startService()} hoặc {@link android.content.Context#bindService bindService()}. 777<p>Nếu dịch vụ được bắt đầu, vòng đời hiện hoạt sẽ chấm dứt tại cùng thời điểm khi toàn bộ vòng đời 778chấm dứt (dịch vụ sẽ vẫn hiện hoạt ngay cả sau khi {@link android.app.Service#onStartCommand 779onStartCommand()} trả về). Nếu dịch vụ bị gắn kết, vòng đời hiện hoạt sẽ chấm dứt khi {@link 780android.app.Service#onUnbind onUnbind()} trả về.</p> 781</li> 782</ul> 783 784<p class="note"><strong>Lưu ý:</strong> Mặc dù dịch vụ được bắt đầu bị dừng bởi một lệnh gọi đến 785hoặc {@link android.app.Service#stopSelf stopSelf()} hoặc {@link 786android.content.Context#stopService stopService()}, sẽ không có một lệnh gọi lại tương ứng cho 787dịch vụ (không có lệnh gọi lại {@code onStop()}). Vì thế, trừ khi dịch vụ được gắn kết với một máy khách, 788hệ thống sẽ hủy nó khi dịch vụ bị dừng—{@link 789android.app.Service#onDestroy onDestroy()} là lệnh gọi lại duy nhất nhận được.</p> 790 791<p>Hình 2 minh họa các phương pháp gọi lại điển hình cho một dịch vụ. Mặc dù hình tách riêng 792các dịch vụ được tạo bởi {@link android.content.Context#startService startService()} với các dịch vụ 793được tạo bởi {@link android.content.Context#bindService bindService()}, hãy 794ghi nhớ rằng bất kỳ dịch vụ nào, dù được bắt đầu như thế nào, đều có thể cho phép máy khách gắn kết với nó. 795Vì thế, một dịch vụ được bắt đầu từ đầu bằng {@link android.app.Service#onStartCommand 796onStartCommand()} (bởi một máy khách gọi {@link android.content.Context#startService startService()}) 797vẫn có thể nhận một lệnh gọi đến {@link android.app.Service#onBind onBind()} (khi máy khách gọi 798{@link android.content.Context#bindService bindService()}).</p> 799 800<p>Để biết thêm thông tin về việc tao một dịch vụ có tính năng gắn kết, hãy xem tài liệu <a href="{@docRoot}guide/components/bound-services.html">Dịch vụ Gắn kết</a>, 801trong đó có thêm thông tin về phương pháp gọi lại {@link android.app.Service#onRebind onRebind()} 802trong phần về <a href="{@docRoot}guide/components/bound-services.html#Lifecycle">Quản lý Vòng đời của 803một Dịch vụ Gắn kết</a>.</p> 804 805 806<!-- 807<h2>Beginner's Path</h2> 808 809<p>To learn how to query data from the system or other applications (such as contacts or media 810stored on the device), continue with the <b><a 811href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a></b> 812document.</p> 813--> 814