Android Binder机制

记录一则AIDL案例

以下将通过一个案例具体去介绍通过AIDL来实现跨进程进行通信的方式。具备知识点:bindService启动服务,aidl文件类型 数据类型等

        <service
            android:name=".ipc.service.RemoteService"
            android:process=":remote"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.zxl.service.remote" />
            </intent-filter>
        </service>

Activity.java代码

   findViewById(R.id.btnEnd).setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View v) {
           if (null != mIMusic){
               try {
                   mIMusic.stop();
               } catch (RemoteException e) {
                   e.printStackTrace();
               }
           }
       }
   });

    private void startService(){
        Intent intent = new Intent();
        intent.setAction("com.zxl.service.remote");
        // 服务所在包名
        intent.setPackage("com.example.mydairytestproject");
        mActyServiceConn = new ActyServiceConn();
        bindService(intent,mActyServiceConn, Context.BIND_AUTO_CREATE);
    }

    private void stopService(){
        if (mActyServiceConn != null){
            unbindService(mActyServiceConn);
            mActyServiceConn = null;
        }
    }

    private class ActyServiceConn implements ServiceConnection{

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mIMusic = IMusic.Stub.asInterface(service);
            // 设置回调方法的方式,让service回调Activity方法
            // 记得注册的是 x.Stub()方法
            try {
                mIMusic.registerStop(new IStopBackAction.Stub() {
                    @Override
                    public void stopCallBack(ProgressData progressData) throws RemoteException {
                        Log.e("返回数据", "stopCallBack: "+progressData.getName() );
                        if (progressData.getProgress() == 100){
                            stopService();
                            ServiceActivity.this.finish();
                        }
                    }
                });
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.e("线程", Thread.currentThread().getId()+"");
    }

    @Override
    protected void onDestroy() {
        if (mActyServiceConn != null){
            stopService();
        }
        super.onDestroy();
    }

ProgressData实体类

package com.example.mydairytestproject.ipc.IInterface;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Created by apple on 2019-10-31.
 * description:
 */
public class ProgressData  implements Parcelable {
    private int progress;
    private String name;

    public ProgressData(int progress, String name) {
        this.progress = progress;
        this.name = name;
    }

    public int getProgress() {
        return progress;
    }

    public void setProgress(int progress) {
        this.progress = progress;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public static Creator<ProgressData> getCREATOR() {
        return CREATOR;
    }

    private ProgressData(Parcel in) {
        progress = in.readInt();
        name = in.readString();
    }

    public static final Creator<ProgressData> CREATOR = new Creator<ProgressData>() {
        @Override
        public ProgressData createFromParcel(Parcel in) {
            return new ProgressData(in);
        }

        @Override
        public ProgressData[] newArray(int size) {
            return new ProgressData[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(progress);
        dest.writeString(name);
    }

    public void readFromParcel(Parcel in) {
        progress = in.readInt();
        name = in.readString();
    }
}

// IMusic.aidl
package com.example.mydairytestproject.ipc.IInterface;

// Declare any non-default types here with import statements
// aidl文件里的变量类型得用parcelable
import com.example.mydairytestproject.ipc.IInterface.IStopBackAction;

// 方法得实现parcelable
interface IMusic {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */

    void play();

    void pause();

    void stop();

    void registerStop(in IStopBackAction iStopBackAction);
}
// IStopBackAction.aidl
package com.example.mydairytestproject.ipc.IInterface;

// Declare any non-default types here with import statements
import com.example.mydairytestproject.ipc.IInterface.ProgressData;
interface IStopBackAction {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
     void stopCallBack(in ProgressData progressData);
}
// ProgressData.aidl
// 先查创建再修改名字
package com.example.mydairytestproject.ipc.IInterface;

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

parcelable ProgressData;

Service.java

public class RemoteService extends Service {
    public RemoteService() {

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e("线程", Thread.currentThread().getId()+"");

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new MusicClass();
    }


    private class MusicClass extends IMusic.Stub {

        @Override
        public void play() {
            Log.e("服务运行", "play: 音乐开启" );
        }

        @Override
        public void pause() {
            Log.e("服务运行", "play: 音乐暂停" );
        }

        @Override
        public void stop() {
            Log.e("服务运行", "play: 音乐结束" );
            // 回调Activity进行传值
            if (mIStopBackAction != null){
                try {
                    mIStopBackAction.stopCallBack(new ProgressData(100,"数据"));
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }

        IStopBackAction mIStopBackAction;

        @Override
        public void registerStop(IStopBackAction iStopBackAction) {
            this.mIStopBackAction = iStopBackAction;
        }
    }
}

in:参数由客户端设置,或者理解成客户端传入参数值。
out:参数由服务端设置,或者理解成由服务端返回值。
inout:客户端输入端都可以设置,或者理解成可以双向通信。

Proxy.pause():
写入方法参数等,然后调用 transact来发送RPC(远程过程调用)请求,同时当前线程挂起,然后服务端的onTranscat 会根据具体方法的key进行调用进行返回,当前线程继续执行,返回数据。
如果远程方法很耗时,那么不能在UI线程发起远程请求。

参考文章

1、binder c/s交互有个宏观的认识
但这里面最后一张图讲述的,binder通过共享内存的方法存放数据有问题
Android-彻底地理解Binder

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值