Service跨应用的用法和通信

本文介绍在Android中如何实现跨应用启动与绑定Service,并通过AIDL机制实现跨应用通信,包括具体步骤与示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一)跨应用启动Service

有时候我们需要在一个程序里面启动另一个程序的服务,在Android5.0之前可以跟跨应用启动Activity的方法相似,使用action的隐式Intent来启动,但是现在5.0之后必须用显示Intent来启动,那么怎么显式启动一个跨程序的Service呢?

答案是通过Intent的setComponent(),传入的ComponetName()第一个参数是要启动的Service所在的程序包名,第二个通过全路径名字传入Service。这样就是显示使用Intent.

 serviceIntent = new Intent();
        serviceIntent.setComponent(new ComponentName("demo.com.servicetest",
                "demo.com.servicetest.MyService"));
然后在按钮里就可以直接启动

 btn_start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startService(serviceIntent);
            }
        });

        btn_stop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopService(serviceIntent);
            }
        });

二)跨应用绑定Service

先在Service里面新建一个AIDL文件,系统会自动的实现一些抽象类,然后我们可以在onBind()里返回这个AIDL文件的类型

  return new IMyAidlInterface.Stub() {
            @Override
            public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

            }
        };
    }
如果系统没有找到这个AIDL名字,我们需要在build选项里选择ReBuild Project.

然后在另一个程序里启动Service

   serviceIntent=new Intent();
        serviceIntent.setComponent(new ComponentName("demo.com.servicetest","demo.com.servicetest.MyService"));
        bindService= (Button) findViewById(R.id.btn_bindService);
        bindService .setOnClickListener(this);
        unbindService= (Button) findViewById(R.id.btn_unbindService);
        unbindService.setOnClickListener(this);


    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_bindService:
                bindService(serviceIntent, this, Context.BIND_AUTO_CREATE);
                break;
            case R.id.btn_unbindService:
                unbindService(this);
        }
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {

        System.out.println("Bind Service");
        System.out.println(service);

    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
bindService()传入的三个参数,第一个是Intent,第二个是ServiceConnection,传入this需要重写它的两个方法

onServiceConnected
还有
onServiceDisconnected
第三个参数是绑定的类型

然后unbindService()传入的参数也是Service Connection.

这样就实现跨程序绑定服务了。

三)跨程序绑定Service并且通信

绑定服务的目的就是为了通信,那么如何在另一个程序里实现跨程序通信呢?答案仍然是AIDL机制。

比如我们在某个Service里打印数据出来,在已经绑定此服务的另一个程序里面进行改变数据,使Service输出的数据发生改变。

首先在AIDL文件里定义一个设置数据方法setData()

// IMyAidlInterface.aidl
package demo.com.servicetest;

// Declare any non-default types here with import statements

interface IMyAidlInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

    setData(String data);

然后ReBuild Project会报错,因为在Service里面没有这个方法,我们需要在Service里声明setData(),在这个方法里实现改变数据的功能。

 @Override
    public IBinder onBind(Intent intent) {

        return new IMyAidlInterface.Stub() {
            @Override
            public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

            }

         @Override
            public void setData(String data) throws RemoteException {
                MyService.this.data=data;
            }
        };
    }

在Service的onCreate()里开一个线程,每隔一秒钟打印一次data,方便我们观察结果

 @Override
    public void onCreate() {
        super.onCreate();
        System.out.println("create service");
  
          new Thread(){
            @Override
            public void run() {
                super.run();

                 runing=true;
                while (runing){
                    System.out.println(data);

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        System.out.println("destory service");
        runing=false;
    }

然后要在另一个程序里绑定Service,并且改变data的值,绑定Service的方法本文第二条刚刚写过,那么如何进行通信呢?

我们需要新建AIDL文件,并且包名要和Service所在程序的AIDL文件所在的包名一样,然后将AIDL文件复制到这个包下面即可。

然后定义AIDL对象binder,设置为null,注意在onSerivceConnected()里给binder实例化,不能直接把service赋值给它强制类型转换,因为AIDL是在两个不同的程序声明的,虽然内容一样,但是内存不一样,不是同一个,不能直接强制转换类型。

  private IMyAidlInterface binder=null;

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {

        System.out.println("Bind Service");
        System.out.println(service);

      binder=IMyAidlInterface.Stub.asInterface(service);
    }
在按钮的点击事件里将EditText的内容传给AIDL的setData()

注意setData要进行捕获异常,如果在Android Studio里面,alt+enter可以方便的进行捕获异常

case R.id.btn_sync:
                   if (binder!=null){
                       try {
                           binder.setData(et.getText().toString());
                       } catch (RemoteException e) {
                           e.printStackTrace();
                       }
                   }
这个时候编译运行程序,点击btn_sync的话,Service所在的程序就会输出我们传进去的值,而原来的值被改变,这也就是实现了跨程序绑定服务的通信功能,主要运用了安卓的AIDL机制,注意AIDL的使用方法。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值