首页 文章

Android AIDL:服务与活动的通信

提问于
浏览
2

我尝试实现Android AIDL通信策略 . 我有活动和服务 . 我的活动可以成功"talk"到我的服务,但反向过程似乎不起作用 .

总而言之,当Activity和Service在不同的进程中运行时,它们无法共享任何数据抛出 IBinder 接口 . 所以 onServiceConnected() 方法接收一个AIDL接口 . 此接口在服务端实现,旨在使用(称为)活动端 . 我使用这个界面 register() 另一个AIDL . 这个新的AIDL实现了Activity-side,并通过AIDL接口称为Service-side . 它就像一个倾听者 . 不幸的是,这个新的AIDL的方法似乎没有被调用 .

由于 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.
                }
            }
        });
    }
}

活动仅包含TextView . 它开始与服务绑定并不时更新视图 . 当调用 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"活动端来不断检查计数器 . 但我宁愿理解为什么它不起作用,以及使用AIDL的正确方法是什么 .

2 回答

  • 0

    摘要

    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");
           }
        });
    }
    
  • 0

    我用同样的方式做了 . 我能够注册活动实例 .

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

    DemoService.java .

    但是在调用下面的代码

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

    你能帮我解决这个问题吗?

相关问题