简体   繁体   English

Android AIDL:服务到活动的通信

[英]Android AIDL: Service-to-Activity communication

I try to implement a Android AIDL communication strategy. 我尝试实现Android AIDL通信策略。 I have an Activity and a Service . 我有活动服务 My Activity can successfully "talk" to my Service , but the reverse process does not seem to work. 我的活动可以成功地与我的服务 “交谈”,但是相反的过程似乎不起作用。

To summarize, as the Activity and the Service run in different processes, they cannot share any data throw the IBinder interface. 总而言之,由于活动服务运行在不同的进程中,因此它们无法共享任何数据,而不会通过IBinder接口进行共享。 So the onServiceConnected() method receive an AIDL interface instead. 因此, onServiceConnected()方法将改为接收AIDL接口。 This interface is implemented Service-side and is aimed at being used (called) Activity-side. 此接口在服务端实现,旨在用于(称为)活动端。 I use this interface to register() another AIDL. 我使用此接口register()另一个AIDL。 This new AIDL is implemented Activity-side and called Service-side through the AIDL interface. 此新的AIDL在活动端实现,并通过AIDL接口称为服务端。 It act like a listener. 它像一个听众。 Unfortunatly, the method of this new AIDL does not seem to be called. 不幸的是,似乎没有调用此新AIDL的方法。

The Service run in its own process thanks to the following line in AndroidManifest.xml : 由于AndroidManifest.xml的以下行,因此该服务以自己的方式运行:

AndroidManifest.xml AndroidManifest.xml中

<service android:name=".DemoService" android:process=":DemoServiceProcess" />

I have 2 AIDL files, one knowing the other. 我有2个AIDL文件,一个知道另一个。

IAidlActivity.aidl IAidlActivity.aidl

package app.test.aidldemo;

interface IAidlActivity {
    void publish(int count);
}

IAidlService.aidl IAidlService.aidl

package app.test.aidldemo;

import app.test.aidldemo.IAidlActivity;
interface IAidlService {
    void startCounter();
    void register(IAidlActivity activity);
}

The Service implements onBind() and run a handler in charge of incrementing a counter. 该服务实现onBind()并运行负责增加计数器的处理程序

DemoService.java 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.
                }
            }
        });
    }
}

The Activity only consist of a TextView . 活动仅包含一个TextView It start the bounding with the Service and update the view from time to time. 它从服务开始边界 ,并不时更新视图。 It is also supposed to update the view when publish() is called. 还应该在调用publish()时更新视图。 But that does not happen. 但这不会发生。

MainActivity.java 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");
    }
}

I also try some variations like: 我也尝试一些变化,例如:

  1. run the appendToView("*** Hey... into runOnUiThread() 运行appendToView("*** Hey... into runOnUiThread()
  2. delay the bindService() by using another handler + postDelayed() 延迟bindService()通过使用另一个处理器+ postDelayed()

My fallback technique would be to only use IAidlService and have a "watcher" Activity-side to constantly check the counter. 我的后备技术是仅使用IAidlService并具有“观察者”活动端来不断检查计数器。 But I would rather understand why it is not working, and what is the correct way to use AIDL. 但是我宁愿理解为什么它不起作用,以及使用AIDL的正确方法是什么。

Summary 摘要

2 statements to change. 2语句更改。

DemoService.java DemoService.java

final Handler handler = new Handler(DemoService.this.getMainLooper());

MainActivity.java MainActivity.java

public void appendToView(String text) {
   view.post(new Runnable() {
       @Override
       public void run() {
           view.append(text + "\n");
       }
    });
}

I did with the same way. 我以同样的方式做。 I am able to register activity instance. 我可以注册活动实例。

public void register(IAidlActivity activity) {
    DemoService.this.aidlActivity = activity
}

in DemoService.java . DemoService.java

But when calling below code 但是当调用下面的代码时

DemoService.this.aidlActivity.publish(count)
- DemoService.this.aidlActivity is coming null.

Can you please help me on this. 你能帮我这个忙吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM