代码片段(4)[全屏查看所有代码]
1. [代码]一、创建AIDL文件
1
2
3
4
5
6
7
8
9
10
11
12
|
ackage cn.com.android123;
引入声明
import
cn.com.android123.IAtmService;
// 声明一个接口,这里演示的是银行ATM程序
interface
IBankAccountService {
int
getAccountBalance();
//返回整数,无参数
void
setOwnerNames(in List<String> names);
//不返回,包含一个传入List参数
BankAccount createAccount(in String name,
int
startingDeposit, in IAtmService atmService);
//返回一个自定义类型
int
getCustomerList(in String branch, out String[] customerList);
//返回整形,输入一个分支,输出一个客户列表
}
|
2. [代码]二、实现一个接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
//显示的提供一个导出接口,为客户端提供绑定。
public
class
RemoteService
extends
Service {
@Override
public
IBinder onBind(Intent intent) {
if
(IRemoteService.
class
.getName().equals(intent.getAction())) {
return
mBinder;
}
if
(ISecondary.
class
.getName().equals(intent.getAction())) {
return
mSecondaryBinder;
}
return
null
;
}
//第一个接口
private
final
IRemoteService.Stub mBinder =
new
IRemoteService.Stub() {
public
void
registerCallback(IRemoteServiceCallback cb) {
if
(cb !=
null
) mCallbacks.register(cb);
}
public
void
unregisterCallback(IRemoteServiceCallback cb) {
if
(cb !=
null
) mCallbacks.unregister(cb);
}
};
//第二个接口
private
final
ISecondary.Stub mSecondaryBinder =
new
ISecondary.Stub() {
public
int
getPid() {
return
Process.myPid();
}
public
void
basicTypes(
int
anInt,
long
aLong,
boolean
aBoolean,
float
aFloat,
double
aDouble, String aString) {
}
};
}
|
3. [代码]三、客户端交互
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
/**
通过Android.os提供的Parcelable类型来传递数据,通常我们使用Eclipse+ADT插件来完成,在Eclipse中在Package Explorer view视图上单击鼠标右键,选择Create Aidl preprocess file for Parcelable classes(创建aidl预编译文件),最终我们创建一个名为android123.aidl文件
*/
import
android.os.Parcel;
import
android.os.Parcelable;
public
final
class
Rect
implements
Parcelable {
public
int
left;
public
int
top;
public
int
right;
public
int
bottom;
public
static
final
Parcelable.Creator<Rect> CREATOR =
new
Parcelable.Creator<Rect>() {
public
Rect createFromParcel(Parcel in) {
return
new
Rect(in);
}
public
Rect[] newArray(
int
size) {
return
new
Rect[size];
}
};
public
Rect() {
}
private
Rect(Parcel in) {
readFromParcel(in);
}
public
void
writeToParcel(Parcel out) {
//当前数据写入到Parcel中
out.writeInt(left);
out.writeInt(top);
out.writeInt(right);
out.writeInt(bottom);
}
public
void
readFromParcel(Parcel in) {
//从Parcel中读取数据
left = in.readInt();
top = in.readInt();
right = in.readInt();
bottom = in.readInt();
}
}
|
4. [代码]IPC调用方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
public
class
RemoteServiceBinding
extends
Activity {
/** The primary interface we will be calling on the service. */
IRemoteService mService =
null
;
/** Another interface we use on the service. */
ISecondary mSecondaryService =
null
;
Button mKillButton;
TextView mCallbackText;
private
boolean
mIsBound;
/**
* Standard initialization of this activity. Set up the UI, then wait
* for the user to poke it before doing anything.
*/
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.remote_service_binding);
// Watch for button clicks.
Button button = (Button)findViewById(R.id.bind);
button.setOnClickListener(mBindListener);
button = (Button)findViewById(R.id.unbind);
button.setOnClickListener(mUnbindListener);
mKillButton = (Button)findViewById(R.id.kill);
mKillButton.setOnClickListener(mKillListener);
mKillButton.setEnabled(
false
);
mCallbackText = (TextView)findViewById(R.id.callback);
mCallbackText.setText(
"Not attached."
);
}
/**
* Class for interacting with the main interface of the service.
*/
private
ServiceConnection mConnection =
new
ServiceConnection() {
public
void
onServiceConnected(ComponentName className,
IBinder service) {
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. We are communicating with our
// service through an IDL interface, so get a client-side
// representation of that from the raw service object.
mService = IRemoteService.Stub.asInterface(service);
mKillButton.setEnabled(
true
);
mCallbackText.setText(
"Attached."
);
// We want to monitor the service for as long as we are
// connected to it.
try
{
mService.registerCallback(mCallback);
}
catch
(RemoteException e) {
// In this case the service has crashed before we could even
// do anything with it; we can count on soon being
// disconnected (and then reconnected if it can be restarted)
// so there is no need to do anything here.
}
// As part of the sample, tell the user what happened.
Toast.makeText(RemoteServiceBinding.
this
, R.string.remote_service_connected,
Toast.LENGTH_SHORT).show();
}
public
void
onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService =
null
;
mKillButton.setEnabled(
false
);
mCallbackText.setText(
"Disconnected."
);
// As part of the sample, tell the user what happened.
Toast.makeText(RemoteServiceBinding.
this
, R.string.remote_service_disconnected,
Toast.LENGTH_SHORT).show();
}
};
/**
* Class for interacting with the secondary interface of the service.
*/
private
ServiceConnection mSecondaryConnection =
new
ServiceConnection() {
public
void
onServiceConnected(ComponentName className,
IBinder service) {
// Connecting to a secondary interface is the same as any
// other interface.
mSecondaryService = ISecondary.Stub.asInterface(service);
mKillButton.setEnabled(
true
);
}
public
void
onServiceDisconnected(ComponentName className) {
mSecondaryService =
null
;
mKillButton.setEnabled(
false
);
}
};
private
OnClickListener mBindListener =
new
OnClickListener() {
public
void
onClick(View v) {
// Establish a couple connections with the service, binding
// by interface names. This allows other applications to be
// installed that replace the remote service by implementing
// the same interface.
bindService(
new
Intent(IRemoteService.
class
.getName()),
mConnection, Context.BIND_AUTO_CREATE);
bindService(
new
Intent(ISecondary.
class
.getName()),
mSecondaryConnection, Context.BIND_AUTO_CREATE);
mIsBound =
true
;
mCallbackText.setText(
"Binding."
);
}
};
private
OnClickListener mUnbindListener =
new
OnClickListener() {
public
void
onClick(View v) {
if
(mIsBound) {
// If we have received the service, and hence registered with
// it, then now is the time to unregister.
if
(mService !=
null
) {
try
{
mService.unregisterCallback(mCallback);
}
catch
(RemoteException e) {
// There is nothing special we need to do if the service
// has crashed.
}
}
// Detach our existing connection.
unbindService(mConnection);
unbindService(mSecondaryConnection);
mKillButton.setEnabled(
false
);
mIsBound =
false
;
mCallbackText.setText(
"Unbinding."
);
}
}
};
private
OnClickListener mKillListener =
new
OnClickListener() {
public
void
onClick(View v) {
// To kill the process hosting our service, we need to know its
// PID. Conveniently our service has a call that will return
// to us that information.
if
(mSecondaryService !=
null
) {
try
{
int
pid = mSecondaryService.getPid();
// Note that, though this API allows us to request to
// kill any process based on its PID, the kernel will
// still impose standard restrictions on which PIDs you
// are actually able to kill. Typically this means only
// the process running your application and any additional
// processes created by that app as shown here; packages
// sharing a common UID will also be able to kill each
// other's processes.
Process.killProcess(pid);
mCallbackText.setText(
"Killed service process."
);
}
catch
(RemoteException ex) {
// Recover gracefully from the process hosting the
// server dying.
// Just for purposes of the sample, put up a notification.
Toast.makeText(RemoteServiceBinding.
this
,
R.string.remote_call_failed,
Toast.LENGTH_SHORT).show();
}
}
}
};
// ----------------------------------------------------------------------
// Code showing how to deal with callbacks.
// ----------------------------------------------------------------------
/**
* This implementation is used to receive callbacks from the remote
* service.
*/
private
IRemoteServiceCallback mCallback =
new
IRemoteServiceCallback.Stub() {
/**
* This is called by the remote service regularly to tell us about
* new values. Note that IPC calls are dispatched through a thread
* pool running in each process, so the code executing here will
* NOT be running in our main thread like most other things -- so,
* to update the UI, we need to use a Handler to hop over there.
*/
public
void
valueChanged(
int
value) {
mHandler.sendMessage(mHandler.obtainMessage(BUMP_MSG, value,
0
));
}
};
private
static
final
int
BUMP_MSG =
1
;
private
Handler mHandler =
new
Handler() {
@Override
public
void
handleMessage(Message msg) {
switch
(msg.what) {
case
BUMP_MSG:
mCallbackText.setText(
"Received from service: "
+ msg.arg1);
break
;
default
:
super
.handleMessage(msg);
}
}
};
|