blob: fc2a7eaeb77f7dd5c0ac9cd2b063b287ae1ce627 [file] [log] [blame]
page.title=Dch v
@jd:body
<div id="qv-wrapper">
<ol id="qv">
<h2>Trong tài liu này</h2>
<ol>
<li><a href="#Basics">Ni dung Cơ bn</a></li>
<ol>
<li><a href="#Declaring">Khai báo mt dch v trong bn kê khai</a></li>
</ol>
<li><a href="#CreatingAService">To mt Dch v được Bt đầu</a>
<ol>
<li><a href="#ExtendingIntentService">M rng lp IntentService</a></li>
<li><a href="#ExtendingService">M rng lp Dch vụ</a></li>
<li><a href="#StartingAService">Bt đầu mt dch vụ</a></li>
<li><a href="#Stopping">Dng mt dch vụ</a></li>
</ol>
</li>
<li><a href="#CreatingBoundService">To mt Dch v Gn kết</a></li>
<li><a href="#Notifications">Gi Thông báo ti Người dùng</a></li>
<li><a href="#Foreground">Chy mt Dch v trong Tin cnh</a></li>
<li><a href="#Lifecycle">Qun lý Vòng đời ca mt Dch vụ</a>
<ol>
<li><a href="#LifecycleCallbacks">Trin khai gi li vòng đời</a></li>
</ol>
</li>
</ol>
<h2>Lp khóa</h2>
<ol>
<li>{@link android.app.Service}</li>
<li>{@link android.app.IntentService}</li>
</ol>
<h2>Mu</h2>
<ol>
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.html">{@code
ServiceStartArguments}</a></li>
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
LocalService}</a></li>
</ol>
<h2>Xem thêm</h2>
<ol>
<li><a href="{@docRoot}guide/components/bound-services.html">Dch v Gn kết</a></li>
</ol>
</div>
<p>{@link android.app.Service} là mt thành phn ng dng có kh năng thc hin
các thao tác chy kéo dài trong nn và không cung cp giao din người dùng. Mt
thành phn ng dng khác có th bt đầu mt dch v và nó s tiếp tc chy ngm ngay c khi người dùng
chuyn sang mt ng dng khác. Ngoài ra, mt thành phn có th gn kết vi mt dch v để
tương tác vi nó và thm chí thc hin truyn thông liên tiến trình (IPC). Ví dụ, mt dch v có th
x lý các giao dch mng, phát nhc, thc hin I/O tp, hoc tương tác vi mt trình cung cp ni dung, tt c
đều xut phát t nn.</p>
<p>V cơ bn, mt dch v có th có hai dng:</p>
<dl>
<dt>Được bt đầu</dt>
<dd>Dch v có dng "được bắt đầu" khi mt thành phn ng dng (chng hn như mt hot động) bt đầu nó bng cách
gi {@link android.content.Context#startService startService()}. Sau khi được bắt đầu, dịch vụ
có th chy ngm vô thi hn, ngay c khi thành phn bt đầu nó b hy. Thông thường,
dch v được bt đầu s thc hin mt thao tác đơn l và không tr v kết qu cho hàm gi.
Ví dụ, nó có th ti xung hoc ti lên mt tp thông qua mng. Khi thao tác được hoàn thành, dch v
t nó s dng li.</dd>
<dt>Gn kết</dt>
<dd>Dch v có dng "gắn kết" khi mt thành phn ng dng gn kết vi nó bng cách gi {@link
android.content.Context#bindService bindService()}. Dịch vụ gắn kết sẽ đưa ra
mt giao din máy khách-máy ch cho phép các thành phn tương tác vi dch vụ, gi yêu cu, nhn kết quả, và thm chí
làm vy thông qua truyn thông liên tiến trình (IPC). Dch v gn kết ch chy trong khi
mt thành phn ng dng khác được gn kết vi nó. Nhiu thành phn có th gn kết cùng lúc vi dch vụ,
nhưng khi tt c b b gn kết thì dch v s b hy.</dd>
</dl>
<p>Mc dù tài liu này thường đề cp ti hai loi dch v riêng rẽ, dch v
ca bn có th hot động theo c hai cách&mdash;nó có th được bt đầu (để chy vô thi hn) và cũng cho phép gn kết.
Đó đơn gin là vn đề bn có trin khai mt cp phương pháp gi li hay không: {@link
android.app.Service#onStartCommand onStartCommand()} để cho phép thành phần bắt đầu nó và {@link
android.app.Service#onBind onBind()} để cho phép nó gắn kết.</p>
<p>Không ph thuc vào vic ng dng ca bn được bt đầu, gn kết, hay c hai, bt k thành phn ng dng nào
cũng có th s dng dch v (thm chí t mt ng dng riêng bit), ging như cách mà bt k thành phn nào cũng có th s dng
mt hot động&mdash;bng cách bt đầu nó bng mt {@link android.content.Intent}. Tuy nhiên, bn có th khai báo
dch v là riêng tư trong tp bn kê khai, và chn truy cp t các ng dng khác. Điu này
được trình bày k hơn trong phn v <a href="#Declaring">Khai báo dch v trong
bn kê khai</a>.</p>
<p class="caution"><strong>Chú ý:</strong> Mt dch v chy trong
lung chính ca tiến trình lưu tr ca nó&mdash;dch v <strong>không</strong> to lung ca chính nó
và <strong>không</strong> chy trong mt tiến trình riêng bit (tr khi bn quy định khác). Điu này có nghĩa
là, nếu dch v ca bn định thc hin bt k công vic nng nào đối vi CPU hay chn các thao tác (chng hn như phát li MP3
hay kết ni mng), bn nên to mt lung mi bên trong dch v để thc hin công vic đó. Bng cách s dng
mt lung riêng bit, bn s gim ri ro gp li ng dng Không Hi đáp (ANR) và lung chính ca ng dng có th
vn dành riêng cho tương tác gia người dùng vi các hot động ca bn.</p>
<h2 id="Basics">Ni dung Cơ bn</h2>
<div class="sidebox-wrapper">
<div class="sidebox">
<h3>Bn nên s dng dch v hay lung?</h3>
<p>Dch v đơn thun là mt thành phn có th chy ngm ngay c khi người dùng không
đang tương tác vi ng dng ca bn. Vì thế, bn ch nên to mt dch v nếu đó là điu bn
cn.</p>
<p>Nếu bn cn thc hin công vic bên ngoài lung chính ca mình, nhưng ch trong khi người dùng đang tương tác vi
ng dng ca bn, thì thay vào đó, bn nên to mt lung mi ch không phi mt dch vụ. Ví
dụ, nếu bn mun phát mt bn nhc, nhưng ch trong khi hot động ca bn đang chy, bn có th to
mt lung trong {@link android.app.Activity#onCreate onCreate()}, bắt đầu chạy nó trong {@link
android.app.Activity#onStart onStart()}, rồi dừng nó trong {@link android.app.Activity#onStop
onStop()}. Cũng xem xét vic s dng {@link android.os.AsyncTask} hoc {@link android.os.HandlerThread},
thay vì s dng lp {@link java.lang.Thread} truyn thng. Xem tài liu <a href="{@docRoot}guide/components/processes-and-threads.html#Threads">Tiến trình và
Lung</a> để biết thêm thông tin về luồng.</p>
<p>Hãy nh rng nếu bn s dng mt dch vụ, nó vn chy trong lung chính ca ng dng ca bn theo
mc định, vì thế bn vn nên to mt lung mi trong dch v nếu nó thc hin các thao tác tăng cường hoc
chn.</p>
</div>
</div>
<p>Để to mt dch vụ, bn phi to mt lp con ca {@link android.app.Service} (hoc mt
trong các lp con hin ti ca nó). Trong trin khai ca mình, bn cn khng chế mt s phương pháp gi li có chc năng
x lý nhng khía cnh chính trong vòng đời ca dch v và cung cp mt cơ chế để các thành phn gn kết vi
dch v đó, nếu phù hp. Nhng phương pháp gi li quan trng nht mà bn nên khng chế là:</p>
<dl>
<dt>{@link android.app.Service#onStartCommand onStartCommand()}</dt>
<dd>H thng s gi phương pháp này khi mt thành phn khác, chng hn như mt hot động,
yêu cu dch v phi được bt đầu, bng cách gi {@link android.content.Context#startService
startService()}. Sau khi phương pháp này thc thi, dch v s được bt đầu và có th chy vô thi hn trong
nn. Nếu bn trin khai điu này, bn có trách nhim dng dch v khi
công vic ca nó được hoàn thành, bng cách gi {@link android.app.Service#stopSelf stopSelf()} hoặc {@link
android.content.Context#stopService stopService()}. (Nếu chỉ muốn cung cấp khả năng gắn kết, bạn không
cn trin khai phương pháp này.)</dd>
<dt>{@link android.app.Service#onBind onBind()}</dt>
<dd>H thng s gi phương pháp này khi mt thành phn khác mun gn kết vi
dch v (chng hn như để thc hin RPC), bng cách gi {@link android.content.Context#bindService
bindService()}. Trong trin khai phương pháp này ca mình, bn phi cung cp mt giao din mà các máy khách
s dng để giao tiếp vi dch vụ, bng cách tr v {@link android.os.IBinder}. Bn phi luôn
trin khai phương pháp này, nhưng nếu bn không mun cho phép gn kết thì bn nên tr v rng.</dd>
<dt>{@link android.app.Service#onCreate()}</dt>
<dd>H thng s gi phương pháp này khi dch v được to lp ln đầu, để thc hin quy trình thiết lp mt ln
(trước khi nó có th gi hoc {@link android.app.Service#onStartCommand onStartCommand()} hoặc
{@link android.app.Service#onBind onBind()}). Nếu dịch vụ đã đang chạy, phương pháp này sẽ không được
gi.</dd>
<dt>{@link android.app.Service#onDestroy()}</dt>
<dd>H thng s gi phương pháp này khi dch v không còn được s dng và đang b hy.
Dch v ca bn s trin khai phương pháp này để dn dp mi tài nguyên như lung, đối tượng theo dõi
được đăng ký, hàm nhn, v.v... Đây là lnh gi cui cùng mà dch v nhn được.</dd>
</dl>
<p>Nếu mt thành phn bt đầu dch v bng cách gi {@link
android.content.Context#startService startService()} (kết quả là một lệnh gọi tới {@link
android.app.Service#onStartCommand onStartCommand()}), khi đó dịch vụ
s vn chy ti khi t nó dng bng {@link android.app.Service#stopSelf()} hoặc một
thành phn khác dng nó bng cách gi {@link android.content.Context#stopService stopService()}.</p>
<p>Nếu mt thành phn gi
{@link android.content.Context#bindService bindService()} để tạo dịch vụ (và {@link
android.app.Service#onStartCommand onStartCommand()} <em>không</em> được gọi), khi đó dịch vụ sẽ chỉ chạy
khi nào mà thành phn đó còn gn kết vi nó. Sau khi dch v được b gn kết khi tt c máy khách, h thng
s hy nó.</p>
<p>H thng Android s buc dng mt dch v ch khi b nh thp và nó phi khôi phc tài nguyên
ca h thng cho hot động có tiêu đim ca người dùng. Nếu dch v gn kết vi mt hot động mà có tiêu đim
ca người dùng, khi đó s có ít kh năng nó s b tt b hơn, và nếu dch v được khai báo là <a href="#Foreground">chy trong tin cnh</a> (đề cp sau), khi đó nó s hu như không bao gi b tt bỏ.
Mt khác, nếu dch v được bt đầu và chy trong thi gian dài, h thng s h thp v trí ca nó
trong danh sách tác v chy ngm qua thi gian và dch v s rt có th b
tt bỏ&mdash;nếu dch v ca bn được bt đầu, khi đó bn phi thiết kế nó để
x lý vic khi động li do h thng mt cách uyn chuyn. Nếu h thng tt b dch v ca bn, nó s khi động li dch v ngay khi tài nguyên
có sn tr li (mc dù điu này cũng ph thuc vào giá tr mà bn tr v t {@link
android.app.Service#onStartCommand onStartCommand()}, vấn đề này sẽ được bàn sau). Để biết thêm thông tin
v thi đim mà h thng có th hy mt dch vụ, hãy xem tài liu <a href="{@docRoot}guide/components/processes-and-threads.html">Tiến trình và Lung</a>
.</p>
<p>Trong nhng phn sau, bn s thy cách bn có th to tng loi dch v và cách s dng
nó t các thành phn ng dng khác.</p>
<h3 id="Declaring">Khai báo mt dch v trong bn kê khai</h3>
<p>Ging như hot động (và các thành phn khác), bn phi khai báo tt c dch v trong tp bn kê khai
ca ng dng ca mình.</p>
<p>Để khai báo dch v ca bn, hãy thêm mt phn t <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a> làm
con ca phn t <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code &lt;application&gt;}</a>
. Ví dụ:</p>
<pre>
&lt;manifest ... &gt;
...
&lt;application ... &gt;
&lt;service android:name=".ExampleService" /&gt;
...
&lt;/application&gt;
&lt;/manifest&gt;
</pre>
<p>Xem tham chiếu phn t <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a>
để biết thêm thông tin v vic khai báo dch v ca bn trong bn kê khai.</p>
<p>Có các thuc tính khác mà bn có th bao gm trong phn t <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a> để
định nghĩa các tính cht chng hn như nhng quyn cn để bt đầu dch v và tiến trình mà
dch v s chy trong đó. Thuc tính <a href="{@docRoot}guide/topics/manifest/service-element.html#nm">{@code android:name}</a>
là thuc tính bt buc duy nht&mdash;nó quy định tên lp ca dch vụ. Mt khi
bn phát hành ng dng ca mình, bn không nên thay đổi tên này, vì nếu bn làm vy, bn s gp ri ro làm gãy
mã do s ph thuc vào các ý định biu th để bt đầu hoc gn kết dch v (đọc bài đăng blog, <a href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Nhng Điu
Không Thay Đổi Được</a>).
<p>Để đảm bo ng dng ca bn được bo mt, <strong>luôn s dng mt ý định biu th khi bt đầu hoc gn kết
{@link android.app.Service}</strong> ca bn và không được khai báo b lc ý định cho dch vụ. Nếu
điu trng yếu là bn phi cho phép mt chút không rõ ràng v dch v nào s bt đầu, bn có th
cung cp b lc ý định cho dch v ca mình và loi b tên thành phn khi {@link
android.content.Intent}, nhưng sau đó bn có th đặt gói cho ý định bng {@link
android.content.Intent#setPackage setPackage()}, điều này cung cấp sự không rõ ràng vừa đủ cho
dch v mc tiêu đó.</p>
<p>Ngoài ra, bn có th đảm bo rng dch v ca mình ch sn có cho ng dng ca bn bng cách
đưa vào thuc tính <a href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code android:exported}</a>
và đặt nó thành {@code "false"}. Điu này s dng vic các ng dng khác bt đầu
dch v ca bn, ngay c khi s dng mt ý định biu thị.</p>
<h2 id="CreatingStartedService">To mt Dch v được Bt đầu</h2>
<p>Dch v được bt đầu là dch v mà mt thành phn khác bt đầu bng cách gi {@link
android.content.Context#startService startService()}, kết quả là một lệnh gọi tới phương pháp
{@link android.app.Service#onStartCommand onStartCommand()} của dịch vụ.</p>
<p>Khi mt dch v được bt đầu, nó có mt vòng đời độc lp vi
thành phn đã bt đầu nó và dch v có th chy ngm vô thi hn, ngay c khi
thành phn bt đầu nó b hy. Như vy, dch v s t dng khi làm xong công vic ca nó
bng cách gi {@link android.app.Service#stopSelf stopSelf()}, hoặc một thành phần khác có thể dừng nó
bng cách gi {@link android.content.Context#stopService stopService()}.</p>
<p>Mt thành phn ng dng chng hn như mt hot động có th bt đầu dch v bng cách gi {@link
android.content.Context#startService startService()} và chuyển một {@link android.content.Intent}
trong đó quy định dch v và bao gm bt k d liu nào để cho dch v s dng. Dch v s nhn
{@link android.content.Intent} này trong phương pháp {@link android.app.Service#onStartCommand
onStartCommand()}.</p>
<p>Ví dụ, gi s mt hot động cn lưu mt s d liu vào cơ s d liu trc tuyến. Hot động có th
bt đầu mt dch v đồng hành và truyn cho nó d liu để lưu bng cách chuyn mt ý định ti {@link
android.content.Context#startService startService()}. Dịch vụ sẽ nhận ý định trong {@link
android.app.Service#onStartCommand onStartCommand()}, kết nối với Internet và thực hiện
giao tác cơ s d liu. Khi giao tác được thc hin, dch v s t dng li và nó b
hy.</p>
<p class="caution"><strong>Chú ý:</strong> Mt dch v s chy trong cùng tiến trình như ng dng
mà nó được khai báo trong đó và trong lung chính ca ng dng đó theo mc định. Vì vy, nếu dch v ca bn
thc hin các thao tác tăng cường hoc chn trong khi người dùng tương tác vi mt hot động t cùng
ng dng, dch v s làm chm hiu năng ca hot động. Để tránh tác động ti hiu năng ca
ng dng, bn nên bt đầu mt lung mi bên trong dch vụ.</p>
<p>Thông thường, có hai lp mà bn có th m rng để to mt dch v được bt đầu:</p>
<dl>
<dt>{@link android.app.Service}</dt>
<dd>Đây là lp cơ bn cho tt c dch vụ. Khi bn m rng lp này, điu quan trng là
bn to mt lung mi để thc hin tt c công vic ca dch v trong đó, do dch v s dng lung chính
ca ng dng ca bn, theo mc định, điu này có th làm chm hiu năng ca bt k hot động nào mà ng dng
ca bn đang chy.</dd>
<dt>{@link android.app.IntentService}</dt>
<dd>Đây là mt lp con ca {@link android.app.Service} có chc năng s dng mt lung trình thc hin để x lý tt c
yêu cu bt đầu mt cách ln lượt. Đây là la chn tt nht nếu bn không yêu cu dch v ca mình
x lý đồng thi nhiu yêu cu. Tt c nhng gì bn cn làm đó là trin khai {@link
android.app.IntentService#onHandleIntent onHandleIntent()}, nó sẽ nhận ý định cho mỗi
yêu cu bt đầu để bn có th thc hin công vic chy ngm.</dd>
</dl>
<p>Các phn sau mô t cách bn có th trin khai dch v ca mình bng cách s dng mt trong các cách cho nhng lp
này.</p>
<h3 id="ExtendingIntentService">M rng lp IntentService</h3>
<p>Vì phn ln các dch v được bt đầu không cn x lý nhiu yêu cu mt cách đồng thi
iu này thc s có th là mt kch bn to đa lung nguy him), có l tt nht là nếu bn
trin khai dch v ca mình bng cách s dng lp {@link android.app.IntentService}.</p>
<p>{@link android.app.IntentService} làm điu sau đây:</p>
<ul>
<li>To mt lung trình thc hin mc định để thc thi tt c ý định được chuyn ti {@link
android.app.Service#onStartCommand onStartCommand()} tách riêng với luồng
chính ca ng dng ca bn.</li>
<li>To mt hàng đợi công vic để chuyn ln lượt tng ý định ti trin khai {@link
android.app.IntentService#onHandleIntent onHandleIntent()} của bạn, vì thế bạn không bao giờ phải
lo lng v vn đề to đa lung.</li>
<li>Dng dch v sau khi tt c yêu cu bt đầu đều đã được x lý, vì thế bn không bao gi phi gi
{@link android.app.Service#stopSelf}.</li>
<li>Cung cp trin khai mc định ca {@link android.app.IntentService#onBind onBind()} mà
tr v rng.</li>
<li>Cung cp trin khai mc định ca {@link android.app.IntentService#onStartCommand
onStartCommand()} mà gi ý định ti hàng đợi công vic ri ti trin khai {@link
android.app.IntentService#onHandleIntent onHandleIntent()} của bạn.</li>
</ul>
<p>Tt c đều nói lên mt thc tế rng tt c nhng vic bn cn làm đó là trin khai {@link
android.app.IntentService#onHandleIntent onHandleIntent()} để thực hiện công việc mà
máy khách cung cp. (Mc dù bn cũng cn cung cp mt hàm dng nh cho dch vụ.)</p>
<p>Sau đây là ví d v trin khai {@link android.app.IntentService}:</p>
<pre>
public class HelloIntentService extends IntentService {
/**
* A constructor is required, and must call the super {@link android.app.IntentService#IntentService}
* constructor with a name for the worker thread.
*/
public HelloIntentService() {
super("HelloIntentService");
}
/**
* The IntentService calls this method from the default worker thread with
* the intent that started the service. When this method returns, IntentService
* stops the service, as appropriate.
*/
&#64;Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() &lt; endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
}
}
</pre>
<p>Đó là tt c nhng gì bn cn: mt hàm dng và trin khai {@link
android.app.IntentService#onHandleIntent onHandleIntent()}.</p>
<p>Nếu bn quyết định cũng khng chế các phương pháp gi li khác, chng hn như {@link
android.app.IntentService#onCreate onCreate()}, {@link
android.app.IntentService#onStartCommand onStartCommand()}, hoặc {@link
android.app.IntentService#onDestroy onDestroy()}, hãy nhớ gọi ra siêu triển khai, sao
cho {@link android.app.IntentService} có th x lý hp lý vòng đời ca lung trình thc hin.</p>
<p>Ví dụ, {@link android.app.IntentService#onStartCommand onStartCommand()} phải trả về
trin khai mc định (đó là cách mà ý định được chuyn ti {@link
android.app.IntentService#onHandleIntent onHandleIntent()}):</p>
<pre>
&#64;Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent,flags,startId);
}
</pre>
<p>Bên cnh {@link android.app.IntentService#onHandleIntent onHandleIntent()}, phương pháp duy nhất mà
t đó bn không cn gi siêu lp là {@link android.app.IntentService#onBind
onBind()} (nhưng bn ch cn trin khai điu đó nếu dch v ca bn cho phép gn kết).</p>
<p>Trong phn tiếp theo, bn s thy cách mà cùng loi dch v được trin khai khi m rng
lp {@link android.app.Service} cơ sở, nó có nhiu mã hơn nhưng có th
phù hp nếu bn cn x lý các yêu cu bt đầu đồng thi.</p>
<h3 id="ExtendingService">M rng lp Dch vụ</h3>
<p>Như bn thy trong phn trước, s dng {@link android.app.IntentService} giúp vic
trin khai mt dch v được bt đầu ca bn tr nên rt đơn gin. Tuy nhiên, nếu bn cn dch v ca mình
thc hin to đa lung (thay vì x lý các yêu cu bt đầu thông qua mt hàng đợi công vic), khi đó bn
có th m rng lp {@link android.app.Service} để x lý tng ý định.</p>
<p>Để so sánh, đon mã mu sau là trin khai lp {@link
android.app.Service} mà thc hin chính xác cùng công vic như ví d bên trên bng cách s dng {@link
android.app.IntentService}. C thể, đối vi mi yêu cu bt đầu, nó s s dng mt lung trình thc hin để thc hin
công vic và ch x lý ln lượt tng yêu cu mt.</p>
<pre>
public class HelloService extends Service {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
// Handler that receives messages from the thread
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
&#64;Override
public void handleMessage(Message msg) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() &lt; endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
// Stop the service using the startId, so that we don't stop
// the service in the middle of handling another job
stopSelf(msg.arg1);
}
}
&#64;Override
public void onCreate() {
// Start up the thread running the service. Note that we create a
// separate thread because the service normally runs in the process's
// main thread, which we don't want to block. We also make it
// background priority so CPU-intensive work will not disrupt our UI.
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
&#64;Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
// If we get killed, after returning from here, restart
return START_STICKY;
}
&#64;Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
&#64;Override
public void onDestroy() {
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
}
</pre>
<p>Như bn có th thy, có nhiu vic hơn nhiu so vi vic s dng {@link android.app.IntentService}.</p>
<p>Tuy nhiên, do bn t mình x lý tng lnh gi đến {@link android.app.Service#onStartCommand
onStartCommand()}, bn có th thc hin nhiu yêu cu mt cách đồng thi. Đó không phi là vic
mà ví d này làm, nhưng nếu đó là vic bn mun, vy bn có th to mt lung mi cho tng
yêu cu và ngay lp tc tr chúng v (thay vì đợi ti khi yêu cu trước hoàn thành).</p>
<p>Để ý rng phương pháp {@link android.app.Service#onStartCommand onStartCommand()} phải trả về một
s nguyên. S nguyên là mt giá tr mô t cách h thng nên tiếp tc dch v trong
trường hp h thng tt b nó (như được đề cp trên, trin khai mc định cho {@link
android.app.IntentService} s x lý điu này cho bn dù bn có th sa đổi nó). Giá tr tr v
t {@link android.app.Service#onStartCommand onStartCommand()} phải là một trong các
hng s sau:</p>
<dl>
<dt>{@link android.app.Service#START_NOT_STICKY}</dt>
<dd>Nếu h thng tt b dch v sau khi {@link android.app.Service#onStartCommand
onStartCommand()} tr về, <em>không</em> được to li dch v đó, tr khi có các ý định
đang ch để được chuyn. Đây là la chn an toàn nht để tránh chy dch v ca bn khi không cn thiết
và khi ng dng ca bn có th đơn thun khi động li bt k công vic chưa hoàn thành nào.</dd>
<dt>{@link android.app.Service#START_STICKY}</dt>
<dd>Nếu h thng tt b dch v sau khi {@link android.app.Service#onStartCommand
onStartCommand()} tr về, hãy to li dch v và gi {@link
android.app.Service#onStartCommand onStartCommand()}, nhưng <em>không</em> chuyển lại ý định cuối cùng.
Thay vào đó, h thng s gi {@link android.app.Service#onStartCommand onStartCommand()} bằng một
ý định rng, tr khi có các ý định đang ch để bt đầu dch vụ, trong trường hp đó,
nhng ý định này s được chuyn. Điu này phù hp vi các trình phát phương tin (hoc dch v tương tự) mà không
đang thc thi lnh, nhưng đang chy vô thi hn và ch mt tác vụ.</dd>
<dt>{@link android.app.Service#START_REDELIVER_INTENT}</dt>
<dd>Nếu h thng tt b dch v sau khi {@link android.app.Service#onStartCommand
onStartCommand()} tr về, hãy to li dch v và gi {@link
android.app.Service#onStartCommand onStartCommand()} bằng ý định cuối cùng được chuyển tới
dch vụ. Mi ý định ch đều được chuyn ln lượt. Điu này phù hp vi các dch v đang
ch động thc hin mt công vic mà nên được tiếp tc ngay lp tc, chng hn như ti xung mt tp.</dd>
</dl>
<p>Để biết thêm chi tiết v nhng giá tr tr v này, hãy xem tài liu tham kho được liên kết cho tng
hng số.</p>
<h3 id="StartingAService">Bt đầu mt Dch vụ</h3>
<p>Bn có th bt đầu mt dch v t mt hot động hoc thành phn ng dng khác bng cách chuyn mt
{@link android.content.Intent} (quy định dch v s bt đầu) đến {@link
android.content.Context#startService startService()}. Hệ thống Android sẽ gọi phương pháp {@link
android.app.Service#onStartCommand onStartCommand()} của dịch vụ và chuyển cho nó {@link
android.content.Intent}. (Bn tuyt đối không nên trc tiếp gi {@link android.app.Service#onStartCommand
onStartCommand()}.)</p>
<p>Ví dụ, mt hot động có th bt đầu dch v ví d trong phn trước ({@code
HelloSevice}) bng cách s dng mt ý định biu th vi {@link android.content.Context#startService
startService()}:</p>
<pre>
Intent intent = new Intent(this, HelloService.class);
startService(intent);
</pre>
<p>Phương pháp {@link android.content.Context#startService startService()} ngay lập tức trả về và
h thng Android s gi phương pháp {@link android.app.Service#onStartCommand
onStartCommand()} ca dch vụ. Nếu dch v không đang chy, trước tiên h thng s gi {@link
android.app.Service#onCreate onCreate()}, rồi gọi {@link android.app.Service#onStartCommand
onStartCommand()}.</p>
<p>Nếu dch v cũng không cung cp kh năng gn kết, ý định được chuyn bng {@link
android.content.Context#startService startService()} sẽ là phương thức giao tiếp duy nhất giữa
thành phn ng dng và dch vụ. Tuy nhiên, nếu bn mun dch v gi mt kết qu tr li, khi đó
máy khách mà bt đầu dch v có th to mt {@link android.app.PendingIntent} cho mt qung bá
(bng {@link android.app.PendingIntent#getBroadcast getBroadcast()}) và chuyển nó tới dịch vụ
trong {@link android.content.Intent} mà bt đầu dch vụ. Khi đó, dch v có th s dng
qung bá để chuyn kết quả.</p>
<p>Nhiu yêu cu bt đầu dch v s dn đến nhiu lnh gi tương ng ti
{@link android.app.Service#onStartCommand onStartCommand()} của dịch vụ. Tuy nhiên, chỉ có một yêu cầu dừng
dch v (bng {@link android.app.Service#stopSelf stopSelf()} hoặc {@link
android.content.Context#stopService stopService()}) là bắt buộc để dừng nó.</p>
<h3 id="Stopping">Dng mt dch vụ</h3>
<p>Dch v được bt đầu phi qun lý vòng đời ca chính nó. C thể, h thng không dng
hay hy dch v tr khi nó phi khôi phc bộ nh ca h thng và dch v
s tiếp tc chy sau khi {@link android.app.Service#onStartCommand onStartCommand()} trả về. Vì vậy,
dch v phi t dng bng cách gi {@link android.app.Service#stopSelf stopSelf()} hoặc một thành phần
khác có th dng nó bng cách gi {@link android.content.Context#stopService stopService()}.</p>
<p>Sau khi được yêu cu dng bng {@link android.app.Service#stopSelf stopSelf()} hoặc {@link
android.content.Context#stopService stopService()}, hệ thống sẽ hủy dịch vụ ngay khi
có thể.</p>
<p>Tuy nhiên, nếu dch v ca bn x lý nhiu yêu cu {@link
android.app.Service#onStartCommand onStartCommand()} đồng thời, khi đó bạn không nên dừng
dch v khi bn đã hoàn thành x lý yêu cu bt đầu, vì bn có th đã nhn được mt
yêu cu bt đầu mi k t thi đim đó (dng khi kết thúc yêu cu th nht s chm dt yêu cu th hai). Để tránh
vn đề này, bn có th s dng {@link android.app.Service#stopSelf(int)} để đảm bảo rằng yêu cầu
dng dch v ca bn luôn được da trên yêu cu bt đầu gn đây nht. C thể, khi bn gi {@link
android.app.Service#stopSelf(int)}, bạn sẽ chuyển ID của yêu cầu bắt đầu (<code>startId</code>
được chuyn ti {@link android.app.Service#onStartCommand onStartCommand()}) mà yêu cầu dừng của bạn
tương ng vi. Khi đó, nếu dch v đã nhn được mt yêu cu bt đầu mi trước khi bn có th gi {@link
android.app.Service#stopSelf(int)}, vậy ID sẽ không khớp và dịch vụ sẽ không dừng.</p>
<p class="caution"><strong>Chú ý:</strong> Điu quan trng là ng dng ca bn dng dch v ca nó
khi nó hoàn thành xong công vic để tránh lãng phí tài nguyên ca h thng và tn pin. Nếu cn,
các thành phn khác có th dng dch v bng cách gi {@link
android.content.Context#stopService stopService()}. Ngay cả khi bạn kích hoạt gắn kết cho dịch vụ,
bn phi luôn t mình dng dch v nếu dch v đã nhn được lnh gi ti {@link
android.app.Service#onStartCommand onStartCommand()}.</p>
<p>Để biết thêm thông tin v vòng đời ca mt dch vụ, hãy xem phn bên dưới v <a href="#Lifecycle">Qun lý Vòng đời ca mt Dch vụ</a>.</p>
<h2 id="CreatingBoundService">To mt Dch v Gn kết</h2>
<p>Dch v gn kết là mt dch v cho phép các thành phn ng dng gn kết vi nó bng cách gi {@link
android.content.Context#bindService bindService()} để tạo một kết nối lâu dài
(và thường không cho phép các thành phn <em>bt đầu</em> nó bng cách gi {@link
android.content.Context#startService startService()}).</p>
<p>Bn nên to mt dch v gn kết khi mun tương tác vi dch v t hot động
và các thành phn khác trong ng dng ca mình hoc để hin th mt s tính năng trong ng dng ca bn cho
các ng dng khác thông qua truyn thông liên tiến trình (IPC).</p>
<p>Để to mt dch v gn kết, bn phi trin khai phương pháp gi li {@link
android.app.Service#onBind onBind()} để trả về một {@link android.os.IBinder} mà
định nghĩa giao din cho giao tiếp vi dch v đó. Khi đó, các thành phn ng dng khác có th gi
{@link android.content.Context#bindService bindService()} để truy xuất giao diện và
bt đầu các phương pháp gi trên dch vụ. Dch v tn ti ch nhm phc v thành phn ng dng mà
được gn kết vi nó, vì thế khi không có thành phn được gn kết vi dch vụ, h thng s hy nó
(bn <em>không</em> cn dng mt dch v gn kết theo cách phi làm khi dch v được bt đầu
thông qua {@link android.app.Service#onStartCommand onStartCommand()}).</p>
<p>Để to mt dch v gn kết, điu đầu tiên bn phi làm là định nghĩa giao din quy định
cách thc mà mt máy khách có th giao tiếp vi dch vụ. Giao din gia dch v và
máy khách này phi là mt trin khai {@link android.os.IBinder} và được dch v ca bn phi
tr v t phương pháp gi li {@link android.app.Service#onBind
onBind()}. Sau khi máy khách nhn được {@link android.os.IBinder}, nó có th bt đầu
tương tác vi dch v thông qua giao din đó.</p>
<p>Nhiu máy khách có th gn kết vi dch v đồng thi. Khi mt máy khách hoàn thành tương tác vi
dch vụ, nó s gi {@link android.content.Context#unbindService unbindService()} để bỏ gắn kết. Sau khi
không còn máy khách nào được gn kết vi dch vụ, h thng s hy dch vụ.</p>
<p>Có nhiu cách để trin khai mt dch v gn kết và trin khai s phc tp
hơn so vi dch v được bt đầu, vì thế ni dung bàn v dch v gn kết được trình bày trong mt
tài liu riêng v <a href="{@docRoot}guide/components/bound-services.html">Dch v Gn kết</a>.</p>
<h2 id="Notifications">Gi Thông báo ti Người dùng</h2>
<p>Sau khi chy, mt dch v có th thông báo cho người dùng v s kin bng cách s dng <a href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Thông báo Ca sổ</a> hoặc <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Thông báo Thanh Trạng thái</a>.</p>
<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
rồ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
thô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>
<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
(chẳng hạn như một tệp đã hoàn thành
việ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
, 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>
<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>
để biết thêm thông tin.</p>
<h2 id="Foreground">Chạy một Dịch vụ trong Tiền cảnh</h2>
<p>Dịch vụ tiền cảnh là một dịch vụ được coi là điều mà
ngườ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ụ
tiề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 đề
"Đang din 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ụ
bị dừng hoặc loại bỏ khỏi tiền cảnh.</p>
<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
tiền cảnh, vì người dùng rõ ràng ý thức được
hoạ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
ngườ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>
<p>Để yêu cầu dịch vụ của bạn chạy trong tiền cảnh, hãy gọi {@link
android.app.Service#startForeground startForeground()}. Phương pháp này dùng hai tham số: một số nguyên
để xác định duy nhất thông báo và {@link
android.app.Notification} cho thanh trạng thái. Ví dụ:</p>
<pre>
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
</pre>
<p class="caution"><strong>Chú ý:</strong> ID số nguyên mà bạn cấp cho {@link
android.app.Service#startForeground startForeground()} không được bằng 0.</p>
<p>Để xóa bỏ dịch vụ khỏi tiền cảnh, hãy gọi {@link
android.app.Service#stopForeground stopForeground()}. Phương pháp này dùng một boolean, cho biết
có 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
dị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
cũng bị loại bỏ.</p>
<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
Thanh Trạng thái</a>.</p>
<h2 id="Lifecycle">Quản lý Vòng đời của một Dịch vụ</h2>
<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
đó 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ụ
có thể chạy ngầm mà người dùng không biết.</p>
<p>Vòng đời của dịch vụ&mdash;từ khi nó được tạo tới khi nó bị hủy&mdash;có thể đi theo hai
con đường khác nhau:</p>
<ul>
<li>Dịch vụ được bắt đầu
<p>Dịch vụ được tạo khi một thành phần khác gọi {@link
android.content.Context#startService startService()}. Sau đó, dịch vụ sẽ chạy vô thời hạn và phải
tự dừng bằng cách gọi {@link
android.app.Service#stopSelf() stopSelf()}. Một thành phần khác cũng có thể dừng
dịch vụ bằng cách gọi {@link android.content.Context#stopService
stopService()}. Khi dịch vụ bị dừng, hệ thống sẽ hủy nó.</p></li>
<li>Dịch vụ gắn kết
<p>Dịch vụ được tạo khi một thành phần khác (máy khách) gọi {@link
android.content.Context#bindService bindService()}. Khi đó, máy khách giao tiếp với dịch vụ
thô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
{@link android.content.Context#unbindService unbindService()}. Nhiều máy khách có thể gắn kết với
cù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ụ
<em>không</em> cần tự mình dừng.)</p></li>
</ul>
<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ụ đã
được bắt đầu bằng {@link android.content.Context#startService startService()}. Ví dụ, một dịch vụ
nhạc nền có thể được bắt đầu bằng cách gọi {@link android.content.Context#startService
startService()} bằng một {@link android.content.Intent} mà sẽ nhận biết nhạc để phát. Sau đó,
có 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ề
bà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
android.content.Context#bindService bindService()}. Trong những trường hợp như vậy, {@link
android.content.Context#stopService stopService()} hoặc {@link android.app.Service#stopSelf
stopSelf()} 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>
<h3 id="LifecycleCallbacks">Triển khai gọi lại vòng đời</h3>
<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
nhữ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
minh họa từng phương pháp vòng đời:</p>
<pre>
public class ExampleService extends Service {
int mStartMode; // indicates how to behave if the service is killed
IBinder mBinder; // interface for clients that bind
boolean mAllowRebind; // indicates whether onRebind should be used
&#64;Override
public void {@link android.app.Service#onCreate onCreate}() {
// The service is being created
}
&#64;Override
public int {@link android.app.Service#onStartCommand onStartCommand}(Intent intent, int flags, int startId) {
// The service is starting, due to a call to {@link android.content.Context#startService startService()}
return <em>mStartMode</em>;
}
&#64;Override
public IBinder {@link android.app.Service#onBind onBind}(Intent intent) {
// A client is binding to the service with {@link android.content.Context#bindService bindService()}
return <em>mBinder</em>;
}
&#64;Override
public boolean {@link android.app.Service#onUnbind onUnbind}(Intent intent) {
// All clients have unbound with {@link android.content.Context#unbindService unbindService()}
return <em>mAllowRebind</em>;
}
&#64;Override
public void {@link android.app.Service#onRebind onRebind}(Intent intent) {
// A client is binding to the service with {@link android.content.Context#bindService bindService()},
// after onUnbind() has already been called
}
&#64;Override
public void {@link android.app.Service#onDestroy onDestroy}() {
// The service is no longer used and is being destroyed
}
}
</pre>
<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
<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>
<img src="{@docRoot}images/service_lifecycle.png" alt="" />
<p class="img-caption"><strong>Hình 2.</strong> Vòng đời dịch vụ. Sơ đồ phía bên trái
minh họa vòng đời khi dịch vụ được tạo bằng {@link android.content.Context#startService
startService()} và sơ đồ phía bên phải minh họa vòng đời khi dịch vụ được tạo
bằng {@link android.content.Context#bindService bindService()}.</p>
<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>
<ul>
<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
android.app.Service#onCreate onCreate()} và thời điểm {@link
android.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
{@link android.app.Service#onCreate onCreate()} và giải phóng tất cả tài nguyên còn lại trong {@link
android.app.Service#onDestroy onDestroy()}. Ví dụ, một
dị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
android.app.Service#onCreate onCreate()}, sau đó dừng luồng trong {@link
android.app.Service#onDestroy onDestroy()}.
<p>Các phương pháp {@link android.app.Service#onCreate onCreate()} và {@link android.app.Service#onDestroy
onDestroy()} được gọi cho tất cả dịch vụ, dù
chúng được tạo bởi {@link android.content.Context#startService startService()} hay {@link
android.content.Context#bindService bindService()}.</p></li>
<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
android.app.Service#onStartCommand onStartCommand()} hoặc {@link android.app.Service#onBind onBind()}.
Mỗi phương pháp sẽ được giao {@link
android.content.Intent} mà được chuyển tương ứng cho hoặc {@link android.content.Context#startService
startService()} hoặc {@link android.content.Context#bindService bindService()}.
<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
chấm dứt (dịch vụ sẽ vẫn hiện hoạt ngay cả sau khi {@link android.app.Service#onStartCommand
onStartCommand()} 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
android.app.Service#onUnbind onUnbind()} trả về.</p>
</li>
</ul>
<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
hoặc {@link android.app.Service#stopSelf stopSelf()} hoặc {@link
android.content.Context#stopService stopService()}, sẽ không có một lệnh gọi lại tương ứng cho
dị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,
hệ thống sẽ hủy nó khi dịch vụ bị dừng&mdash;{@link
android.app.Service#onDestroy onDestroy()} là lệnh gọi lại duy nhất nhận được.</p>
<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
các dịch vụ được tạo bởi {@link android.content.Context#startService startService()} với các dịch vụ
được tạo bởi {@link android.content.Context#bindService bindService()}, hãy
ghi 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ó.
Vì thế, một dịch vụ được bắt đầu từ đầu bằng {@link android.app.Service#onStartCommand
onStartCommand()} (bởi một máy khách gọi {@link android.content.Context#startService startService()})
vẫ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
{@link android.content.Context#bindService bindService()}).</p>
<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>,
trong đó có thêm thông tin về phương pháp gọi lại {@link android.app.Service#onRebind onRebind()}
trong phần về <a href="{@docRoot}guide/components/bound-services.html#Lifecycle">Quản lý Vòng đời của
mt Dch v Gn kết</a>.</p>
<!--
<h2>Beginner's Path</h2>
<p>To learn how to query data from the system or other applications (such as contacts or media
stored on the device), continue with the <b><a
href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a></b>
document.</p>
-->