2. Service là gì?
●
●
Là cơ chế xử lý công việc ở thread khác với
Activity thread (UI thread).
Không ngắt ngang luồng xử lý của UI thread khi
có một công việc xen ngang.
Activity
Activity
Service
♫
♫
Không dùng Service
Dùng Service
3. Các loại service
●
Trong Android có hai loại service:
●
Unbound service (Started service)
●
Bound service
4. Vòng đời của service
startService()
onCreate()
onCreate()
onStartCommand()
Service stop bởi
service hoặc
client
bindService()
onBind()
Service
Running
Active Lifetime
Service
Running
onUnbind()
onDestroy()
Service
Shutdown
Unbound Service
onDestroy()
Service
Shutdown
Bound Service
Client gọi
unbindService()
5. Hiện thực Unbound Service
●
Tạo service
●
Đăng ký trong AndroidManifest.xml
●
●
Sử dụng phương thức startService() để start
service.
Sử dụng phương thức stopService() để stop
service
6. Tạo Service
●
●
●
Tạo lớp kế thừa từ lớp Service.
Hiện thực phương thức onBind: Trả về null vì ở
đây là unbound service.
Hiện thức các phương thức callback: onCreate,
onStartComand, onDestroy nếu cần thiết.
7. Tạo Service
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class SampleService extends Service {
@Override
public IBinder onBind(Intent arg0) {
return null;
}
}
@Override
public void onCreate() {
Log.d(“SampleService", "onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Thread t = new Thread() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.d("SampleService", e.toString());
}
}
};
t.start();
return START_STICKY;
}
@Override
public void onDestroy() {
Log.d(“SampleService", "onDestroy");
}
8. Đăng ký trong AndroidManifest.xml
1.Mở file AndroidManifest.xml chọn
“Application” tab
2.Click nút “Add” ở mục “Application Nodes”
2
1
9. Đăng ký trong AndroidManifest.xml
3.Chọn “Service” rồi nhấn nút “OK”.
※ Trong trường hợp cursor đang nằm trong ô
nhập liệu thì dòng “Create a new element in the
selected element, ...”, chọn lại dòng trên
※
3
10. Đăng ký trong AndroidManifest.xml
4.Kiểm tra là bạn đang chọn “Service” trong
“Application Nodes”. Nhập tên của service bạn
muốn đăng ký vào “Name”.
Nhấn vào nút “Browse”,
giúp bạn tìm ra tên service
cầnnhập vào dễ dàng hơn
4
11. Start Service
●
●
Tạo đối tượng Intent.
Sử dụng phương thức Context#startService để
start service.
Intent intent = new Intent(this, SampleService.class);
startService(intent);
12. Bài tập 01
●
Thiết kế chương trình có một màn hình + 1
service.
●
Màn hình có một nút “Start” và nút “Stop”.
–
–
●
Nhấn vào nút “Start” thì start service.
Nhấn vào nút “Stop” thì stop service.
Service in log ra logcat mỗi 1 giây.
13. Bind Service
●
Bind service
●
Gọi các phương thức do service cung cấp.
●
Get và set dữ liệu cho service.
●
Sử dụng ServiceConnection interface.
15. Start Binding A Service
Phía Client
1. Gọi bindService() để kết nối đến service.
2. bindService() return ngay lập tức (bất đồng
bộ).
3. Khi kết nối giữa client và service được tạo,
hệ thống sẽ gọi phương thức
onServiceConnected() ở phía client và truyền
IBinder instance cho client để client dùng để
giao tiếp với service.
Phía Server
1. Khi client đầu tiên bind vào
service, hệ thống gọi phương
thức onBind() để lấy IBinder
instance một lần .
2. IBinder instance này được
dùng cho tất cả các kết nối từ
các client khác.
16. Stop Binding Service
●
Khi client cuối cùng gọi phương thức
unbindService() để ngắt kết nối với service
(unbind), hệ thống sẽ huỷ bỏ service.
17. Hiện thực IBinder
●
Có ba phương pháp sau:
●
Extend lớp Binder.
●
Sử dụng Messenger.
●
Sử dụng AIDL.
18. Extend Lớp Binder
●
Phương pháp này chỉ dùng cho local & private
client (client & server cùng process và cùng ứng
dụng)
Phía Client
1.Gọi bindService() để kết nối service.
2.Lấy đối tượng IBinder từ
onServiceConnected().
3.Gọi các public method do server cung
cấp để thực hiện các yệu cầu nghiệp
vụ
Phía Server
1.Trong phương thức onBind(), tạo đối
tượng Binder theo 1 trong 3 cách sau:
● Đối tượng có các public methods →
client có thể sử dụng.
● Đối tượng có getter return instance
của chính service → client có thể sử
dụng các public method của service.
● Đối tượng có getter return một
instance của lớp khác thuộc service→
client có thể sử dụng các public
method của lớp này.
2.Return đối tượng Binder.
19. Extend Lớp Binder: Phía Server
1.mBinder return cho hệ
thống.Đối tượng này
được dùng để gửi đến
các client qua
onServiceConnected()
2.Return cho client,
client dùng Ibinder này
để gọi public method
getService() và lấy
con trỏ đến đối tượng
service
3.Sau khi có refence
đến đối tượng service,
client có thể gọi
phương thức
sampleMethod() để
thực hiện nghiệp vụ
public class SampleLocalService extends Service {
// Binder gui den client
private final IBinder mBinder = new SampleLocalBinder();
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/**
* Lop hien thuc lop Binder. Do service va client thuc thi cung process
* va ung dung nen khong quan tam den IPC.
*/
public class SampleLocalBinder extends Binder {
SampleLocalService getService() {
// Return chinh instance cua service, client goi public method.
return SampleLocalService.this;
}
}
//Sample public method ma client co the goi
public void sampleMethod() {
//Thuc hien nghiep vu nao do.
}
}
20. Extend Lớp Binder: Phía Client
public class SampleActivity extends Activity {
SampleLocalService mService;
boolean mIsBound = false;
1.Gọi bindService()
với Intent hợp lí sẽ
bind vào service và
onBind() callback
trên server sẽ được
gọi.
Instance của
anonymous class sẽ
định nghĩa slide sau
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onStart() {
super.onStart();
// Bind vào SampleLocalService
Intent intent = new Intent(this, SampleLocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
// Unbind với service
if (mIsBound) {
unbindService(mConnection);
mIsBound = false;
}
}
21. Extend Lớp Binder: Phía Client
2. Lớp
anonymous,
gọi một lần
ở 1. nó tạo
ra đối tượng
và các hàm
callback.
3.Khi nút
được ấn
cần kiểm
tra service
đã bind
chưa. Nếu
đã bind gọi
public
method
của service
//Định nghĩa các callback khi service bind, truyền cho bindService()
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,IBinder service) {
// SampleLocalService vừa bind, cast IBinder và nhận reference đến
//SampleLocalService
SampleLocalBinder binder = (SampleLocalBinder) service;
mService = binder.getService();
mIsBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mIsBound = false;
}
};
//Được gọi khi nút được nhấn.
public void onButtonClick(View v) {
if (mIsBound) {
// Gọi phương thức của SampleLocalService.Lời gọi này đôi khi làm cho chương
//trình bị treo.Do đó nên thực hiện lời gọi này ở thread khác.
mService.sampleMethod();
}}}
23. Sử dụng Messenger
●
Phương pháp này phù hợp cho trường hợp client
và server khác process (IPC)
Phía Client
1.Gọi bindService() để kết nối
service trong onStart() hoặc
onCreate().
2.Định nghĩa lớp
ServiceConnection với
onServiceConnected() callback.
3.Khi nhận được IBinder thì khởi
tạo Messenger.
4.Sử dụng Messenger để trao đổi
thông tin giữa client & server
Phía Server
1.Định nghĩa message
handler.
2.Tạo đối tượng của lớp
Messanger với message
handler đã tạo ở bước 1.
3.Return IBinder của đối
tượng Messenger ở bước 2
cho phía client trong
phương thức onBind().
24. Sử dụng Messenger: Phía Server
public class SampleService extends Service {
//Khai báo mã câu lệnh để server thực hiện nghiệp vụ nào đó
static final int MSG_SAMPLE_COMMAND = 1;
1.Hiện thực lớp
MyIncommingHandler
kế thừa lớp Handler để
xử lý tất cả các thông
điệp nhận được từ phía
client trong phương thức
handleMessage()
//Trình xử lý các câu lệnh nhận được từ phía client.
class MyIncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAMPLE_COMMAND:
//Thực hiện một nghiệp vụ nào đó.
break;
default:
super.handleMessage(msg);
}
}
}
25. Sử dụng Messenger: Phía Server
2. Tạo đối tượng mMessenger (Messenger) có trình
xử lý thông điệp xây dựng ở bước 1. Tất cả các
thông điệp gửi qua Messenger này đều gửi đến
MyInCommingHandler.
/**
* Thông điệp gửi đến MyIncomingHandler .
*/
final Messenger mMessenger = new Messenger(new MyIncomingHandler());
/**
* Khi service được bide, interface của messenger được return về cho client
* tạo ra kênh để client cò thể gửi thông điệp đến server.
*/
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
}
3. Sử dụng phương thức getBinder() của lớp
Messenger để lấy reference đến đối tượng IBinder
và return về cho phía client.
26. Sử dụng Messenger: Phía Client
1.Hiện thực một
anonymous class từ
ServiceConnection
interface. Trong đó có
phương thức
onServiceConnected
được gọi khi service được
bind và Ibinder được
truyền vào qua thông số.
Sử dụng Ibinder để tạo
đối tượng Messenger.
public class SampleActivity extends Activity {
//Messenger dùng để trao đổi thông điệp với service
Messenger mService = null;
//Cờ để đánh dấu là service đã bind chưa.
boolean mIsBound = false;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
//Phương thức này được gọi khi service được bind thành công.
//IBinder được truyền vào qua tham số của phương thức.
//Chúng ta sử dụng IBinder này để tạo đối tượng Messenger.
mService = new Messenger(service);
mIsBound = true;
}
public void onServiceDisconnected(ComponentName className) {
//Phương thức này được gọi khi kết nối bị đứt bất thường như
//process chết.
mService = null;
mIsBound = false;
}
};
27. Sử dụng Messenger: Phía Client
public void doCommand(View v) {
if (!mIsBound) return;
// Tạo thông điệp và gửi đến service
Message msg = Message.obtain(null, SampleService.MSG_SAMPLE_COMMAND, 0, 0);
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
2.Mỗi khi phương thức
setContentView(R.layout.main);
doCommand() được gọi, sử
}
dụng phương thức obtain của
lớp Message để tạo ra đối
tượng Message. Sử dụng các
giá trị định nghĩa trong what lớp
SampleService. Sau đó sử
dụng đối tượng mService tạo ra
ở bước 1 để gửi thông điệp
đến service
28. Sử dụng Messenger: Phía Client
@Override
protected void onStart() {
super.onStart();
// Bind service
bindService(new Intent(this, SampleService.class), mConnection,
Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
// Unbind service
if (mIsBound) {
unbindService(mConnection);
mIsBound = false;
}
}
}
3.Mỗi khi Activity start
& resume thì service
được bind bằng cách
dùng phương thức
bindService với
mConnection tạo ra ở
bước 1.
30. Sử dụng AIDL
●
●
Phương pháp này rất ít gặp trong thực tế vì chỉ phù hợp với các
ứng dụng đa luồng, hiện thực khá phức tạp.
Tập tin AIDL là gì?
●
●
●
●
●
Tập tin định nghĩa interface cho các phương thức được hiện
thực trong service có thể truy xuất từ xa.
Tập tin AIDL có phần mở rộng là aidl.
Tập tin này được đặt cùng thư mục các tập tin mã nguồn
khác.
Eclipse sẽ tự động biên dịch tập tin này sang tập tin Java
tương ứng. Trong tập tin này interface Stub được tạo ra. Sử
dụng interface này để giao tiếp giữa client và server.
Các kiểu sau đây hay các Array của các kiểu sau đây là hợp
lệ dùng trong AIDL: Kiểu cơ bản, String, Parcelable, List,
Map, AIDL interface
31. Sử dụng AIDL
●
Tạo AIDL file:
●
Chọn vào thư mục tương ứng với package name của
interface sinh ra từ file AIDL và nhấn chuột phải chọn
New > File (Xem hình)
32. Sử dụng AIDL
●
●
Định nghĩa các phương thức trong interface:
package com.example.aidlsampleservice;
interface IMySampleService{
void doSomething();
}
Tập tin Java tương ứng tự động sinh ra:
33. Sử dụng AIDL
●
Interface IMySampleService.Stub được sinh
ra:
public interface IMySampleService extends
android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends
android.os.Binder implements
com.example.aidlsampleservice.IMySampleService
{
…
public static com.example.aidlsampleservice.IMySampleService
asInterface(android.os.IBinder obj)
{
…
public void doSomething() throws
android.os.RemoteException;
}
34. Sử dụng AIDL
Phía Client
1.Gọi bindService() để kết nối
service trong onStart() hoặc
onCreate().
2.Định nghĩa lớp
ServiceConnection với
onServiceConnected() callback.
Khi nhận được IBinder thì khởi
tạo IMySampleService sử dụng
phương thức asInterface của Stub.
3.Sử dụng các phương thức trong
IMySampleService để trao đổi
với server.
Phía Server
1.Tạo đối tượng binder từ
lớp nội hiện thực Stub
interface.
2.Return binder được tạo
ở bước 1 cho phía client
trong phương thức
onBind().
35. Sử dụng AIDL
Step 1
●
Phía Server:
Step 2
public class AIDLSampleService extends Service {
// Dinh nghia service Stub
private IMySampleService.Stub binder =
new IMySampleService.Stub(){
public void doSomething(){
//Nội dung cần thực hiện
}
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}
36. Sử dụng AIDL
●
Phía Client:
private IMySampleService mService;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
mService = IMySampleService.Stub.asInterface(binder);
}
};
37. Bài tập 02
●
Hiện thực lại Bài tập 01 sử dụng 3 kỹ thuật hiện
thực bound service.
39. Toast là gì?
●
●
●
Dùng để trình bày một thông điệp lên màn hình
trong thời gian ngắn.
Người dùng không thể tương tác với Toast vì
Toast không bao giờ được focus.
Toast thường được dùng với những thành phần
không có GUI như service, thread, ...
40. Sử dụng Toast
●
Android cung cấp hai phương thức sau đây để
tạo đối tượng Toast
public static Toast makeText (Context context, CharSequence text, int duration)
public static Toast makeText (Context context, int resId, int duration)
●
context: context để trình bày Toast
●
text (resId): Thông điệp cần trình bày.
●
duration: Một trong hai giá trị:
–
–
●
Toast.LENGTH_LONG
Toast.LENGTH_SHORT
Sử dụng Toast#show để trình bày Toast lên màn
Toast.makeText(this,R.string.testtoast, Toast.LENGTH_LONG).show()
hình.Ví dụ:
42. Customize Toast
●
Thay đổi vị trí hiển thị:
●
Sử dụng phương thức:
public void setGravity(int gravity, int xOffset, int yOffset)
●
Chúng ta có thể sử dụng phép toán bit_or (|) để kết nối các
hằng sau đây cho tham số gravity:
–
–
–
●
CENTER
CENTER_HORIZONTAL
CENTER_VERTICAL
Thay đổi View:
●
Sử dụng phương thức:
public void setView(View view)
●
Có thể sử dụng LayoutInflater để inflate từ xml layout file
43. Bài tập 03
●
Hiện thực Toast mô tả trong hình ở Slide
“Customize Toast”
44. Lưu ý Bảo mật
●
Xem video clip về TapJacking.
●
Khi lập trình cần:
●
●
Có cơ chế bảo vệ tường minh cho các View nhạy
cảm như nút “Mua hàng”, “Chuyển tiền”, “Chấp
nhận”, …
Đối với các control lớn cần override phương thức:
public boolean onFilterTouchEventForSecurity
(MotionEvent event)