Android AIDL:服务到 Activity 通信
Android AIDL: Service-to-Activity communication
我尝试实施 Android AIDL 通信策略。
我有一个 Activity 和一个 Service。
我的Activity可以成功"talk"到我的服务,但是反向过程好像不行。
总而言之,Activity和Service运行在不同的进程中,不能共享任何数据都会抛出 IBinder
接口。
因此 onServiceConnected()
方法改为接收 AIDL 接口。
该接口是服务端实现的,旨在被使用(调用)Activity端。
我将此 接口 用于 register()
另一个 AIDL。
这个新的AIDL在Activity端实现,通过AIDL接口调用Service端。
它就像一个倾听者。
可惜这个新AIDL的方法好像没有被调用
Service 运行 在其自己的进程中感谢 AndroidManifest.xml
中的以下行:
AndroidManifest.xml
<service android:name=".DemoService" android:process=":DemoServiceProcess" />
我有 2 个 AIDL 文件,一个知道另一个。
IAidlActivity.aidl
package app.test.aidldemo;
interface IAidlActivity {
void publish(int count);
}
IAidlService.aidl
package app.test.aidldemo;
import app.test.aidldemo.IAidlActivity;
interface IAidlService {
void startCounter();
void register(IAidlActivity activity);
}
服务实现 onBind()
和 运行 一个 处理程序 负责递增计数器。
DemoService.java
package app.test.aidldemo;
import [...]
public class DemoService extends Service
{
protected IAidlActivity aidlActivity;
@Override
public IBinder onBind(Intent intent)
{
return new IAidlService.Stub() {
@Override
public void startCounter() {
DemoService.this.startJob();
}
@Override
public void register(IAidlActivity activity) {
DemoService.this.aidlActivity = activity;
}
};
}
public void startJob() {
final Handler handler = new Handler();
handler.post(new Runnable() {
protected int count = 0;
@Override
public void run() {
if (count < 500) {
count++; // increment counter
try { // then publish it to view
DemoService.this.aidlActivity.publish(count); // interface, implemented activity-side
} catch (RemoteException e) {}
handler.postDelayed(this, 2000); // 2sec.
}
}
});
}
}
Activity只包含一个TextView。
它使用 Service 启动 bounding 并不时更新视图。
它也应该在 publish()
被调用时更新视图。
但这并没有发生。
MainActivity.java
package app.test.aidldemo;
import [...]
public class MainActivity extends Activity {
protected TextView view;
protected ServiceConnection connection;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
view = new TextView(this);
setContentView(view);
appendToView("Let's go!");
connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IAidlService aidlService = IAidlService.Stub.asInterface(service);
appendToView("IAidlService accessed");
IAidlActivity.Stub aidlActivity = new IAidlActivity.Stub() {
@Override
public void publish(int count) {
appendToView("*** Hey, new count is: " + count + "!! ***");
}
};
appendToView("IAidlActivity created");
try {
aidlService.register(aidlActivity);
aidlService.startCounter(); // interface, implemented service-side
}
catch (RemoteException e) { appendToView(e.toString()); }
}
@Override
public void onServiceDisconnected(ComponentName name) {}
};
Intent intent = new Intent(MainActivity.this, DemoService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
@Override
public void onDestroy() {
unbindService(connection);
super.onDestroy();
}
public void appendToView(String text) {
view.append(text + "\n");
}
}
我也尝试了一些变体,例如:
- 运行把
appendToView("*** Hey...
改成runOnUiThread()
- 使用另一个处理程序延迟
bindService()
+ postDelayed()
我的后备技术是只使用 IAidlService 并有一个 "watcher" Activity 端不断检查计数器。
但我更想了解为什么它不起作用,以及使用 AIDL 的正确方法是什么。
总结
2 个要更改的语句。
DemoService.java
final Handler handler = new Handler(DemoService.this.getMainLooper());
MainActivity.java
public void appendToView(String text) {
view.post(new Runnable() {
@Override
public void run() {
view.append(text + "\n");
}
});
}
我尝试实施 Android AIDL 通信策略。 我有一个 Activity 和一个 Service。 我的Activity可以成功"talk"到我的服务,但是反向过程好像不行。
总而言之,Activity和Service运行在不同的进程中,不能共享任何数据都会抛出 IBinder
接口。
因此 onServiceConnected()
方法改为接收 AIDL 接口。
该接口是服务端实现的,旨在被使用(调用)Activity端。
我将此 接口 用于 register()
另一个 AIDL。
这个新的AIDL在Activity端实现,通过AIDL接口调用Service端。
它就像一个倾听者。
可惜这个新AIDL的方法好像没有被调用
Service 运行 在其自己的进程中感谢 AndroidManifest.xml
中的以下行:
AndroidManifest.xml
<service android:name=".DemoService" android:process=":DemoServiceProcess" />
我有 2 个 AIDL 文件,一个知道另一个。
IAidlActivity.aidl
package app.test.aidldemo;
interface IAidlActivity {
void publish(int count);
}
IAidlService.aidl
package app.test.aidldemo;
import app.test.aidldemo.IAidlActivity;
interface IAidlService {
void startCounter();
void register(IAidlActivity activity);
}
服务实现 onBind()
和 运行 一个 处理程序 负责递增计数器。
DemoService.java
package app.test.aidldemo;
import [...]
public class DemoService extends Service
{
protected IAidlActivity aidlActivity;
@Override
public IBinder onBind(Intent intent)
{
return new IAidlService.Stub() {
@Override
public void startCounter() {
DemoService.this.startJob();
}
@Override
public void register(IAidlActivity activity) {
DemoService.this.aidlActivity = activity;
}
};
}
public void startJob() {
final Handler handler = new Handler();
handler.post(new Runnable() {
protected int count = 0;
@Override
public void run() {
if (count < 500) {
count++; // increment counter
try { // then publish it to view
DemoService.this.aidlActivity.publish(count); // interface, implemented activity-side
} catch (RemoteException e) {}
handler.postDelayed(this, 2000); // 2sec.
}
}
});
}
}
Activity只包含一个TextView。
它使用 Service 启动 bounding 并不时更新视图。
它也应该在 publish()
被调用时更新视图。
但这并没有发生。
MainActivity.java
package app.test.aidldemo;
import [...]
public class MainActivity extends Activity {
protected TextView view;
protected ServiceConnection connection;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
view = new TextView(this);
setContentView(view);
appendToView("Let's go!");
connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IAidlService aidlService = IAidlService.Stub.asInterface(service);
appendToView("IAidlService accessed");
IAidlActivity.Stub aidlActivity = new IAidlActivity.Stub() {
@Override
public void publish(int count) {
appendToView("*** Hey, new count is: " + count + "!! ***");
}
};
appendToView("IAidlActivity created");
try {
aidlService.register(aidlActivity);
aidlService.startCounter(); // interface, implemented service-side
}
catch (RemoteException e) { appendToView(e.toString()); }
}
@Override
public void onServiceDisconnected(ComponentName name) {}
};
Intent intent = new Intent(MainActivity.this, DemoService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
@Override
public void onDestroy() {
unbindService(connection);
super.onDestroy();
}
public void appendToView(String text) {
view.append(text + "\n");
}
}
我也尝试了一些变体,例如:
- 运行把
appendToView("*** Hey...
改成runOnUiThread()
- 使用另一个处理程序延迟
bindService()
+postDelayed()
我的后备技术是只使用 IAidlService 并有一个 "watcher" Activity 端不断检查计数器。 但我更想了解为什么它不起作用,以及使用 AIDL 的正确方法是什么。
总结
2 个要更改的语句。
DemoService.java
final Handler handler = new Handler(DemoService.this.getMainLooper());
MainActivity.java
public void appendToView(String text) {
view.post(new Runnable() {
@Override
public void run() {
view.append(text + "\n");
}
});
}