Android-Binder之一:简单IPC

版权声明:转载请邮件联系我([email protected]),以取得授权,谢谢! https://blog.csdn.net/yeshennet/article/details/82960102

引文

Binder 是android中一个很基础的概念,设计上很简洁。因为是基础 IPC 模块,所以基本上 Android 的核心内容都对它有依赖。所以掌握了 Binder ,算是掌握了 Android 系统的一把钥匙。
网络上有不少文章对 Binder 做了剖析,假设你已经看完了所有资料,也过了一边源码。

这个系列是使用 Binder 的笔记,包括 简单IPC 、创建&使用系统级服务。这是第一篇 :)

简单IPC

AndroidManifest

<service android:name=".RemoteService" android:process=":remote"/>

aidl

org.yeshen.ipc.ipctest.IRemoteService.aidl

package org.yeshen.ipc.ipctest;

import org.yeshen.ipc.ipctest.EchoData;

interface IRemoteService {
    EchoData echo(String msg);
}

org.yeshen.ipc.ipctest.EchoData.aidl

package org.yeshen.ipc.ipctest;

parcelable EchoData;

impl

org.yeshen.ipc.ipctest.MainActivity.java

package org.yeshen.ipc.ipctest;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private IRemoteService mRemoteService;
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mRemoteService = IRemoteService.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mRemoteService = null;
        }
    };
    private TextView mPrintView;
    private boolean mIsBound = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mPrintView = findViewById(R.id.print_view);
    }

    public void performEcho(View v) {
        if (!mIsBound || mRemoteService == null) {
            Toast.makeText(this, "not bind yet", Toast.LENGTH_SHORT).show();
            return;
        }
        try {
            String now = "utc[" + System.currentTimeMillis() + "]";
            mPrintView.setText(mRemoteService.echo(now).toString());
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    public void performBind(View v) {
        Intent intent = new Intent(MainActivity.this, RemoteService.class);
        intent.setAction(IRemoteService.class.getName());
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        mIsBound = true;
    }

    public void performUnBind(View v) {
        if (!mIsBound) return;
        unbindService(mConnection);
        mIsBound = false;
    }

    public void performKill(View v) {
        if (mRemoteService == null) return;
        try {
            android.os.Process.killProcess(mRemoteService.echo("").getPid());
            mIsBound = false;
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

}

org.yeshen.ipc.ipctest.RemoteService.java

package org.yeshen.ipc.ipctest;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;

public class RemoteService extends Service {

    EchoData mData;

    @Override
    public void onCreate() {
        super.onCreate();
        mData = new EchoData();
        mData.setPid(android.os.Process.myPid());
    }

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

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {

        @Override
        public EchoData echo(String msg) throws RemoteException {
            mData.setMsg(msg);
            mData.increaseEcho();
            return mData;
        }

        @Override
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
            return super.onTransact(code, data, reply, flags);
        }
    };
}

org.yeshen.ipc.ipctest.EchoData.java

package org.yeshen.ipc.ipctest;

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

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

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

    private String msg;
    private int pid;
    private int echo;

    public EchoData() {
    }

    protected EchoData(Parcel in) {
        readFromParcel(in);
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(msg);
        dest.writeInt(pid);
        dest.writeInt(echo);
    }

    private void readFromParcel(Parcel in) {
        msg = in.readString();
        pid = in.readInt();
        echo = in.readInt();
    }

    public int getPid() {
        return pid;
    }

    public void setPid(int pid) {
        this.pid = pid;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public void increaseEcho() {
        this.echo++;
    }

    @Override
    public String toString() {
        return "msg = " + msg + ",\n pid=" + pid + ",\n times=" + this.echo;
    }
}

在这里插入图片描述

小结:

这样就实现了一个最简单的自定义数据读写和跨进程通讯。

创建&使用系统级服务

做一个系统级别的服务。考虑在Android系统中写一个 EchoServer 服务,功能如下:

在context中可以获得这个服务;
消息传到 EchoServer;
EchoServer 再原样返回给调用者。

// TODO

猜你喜欢

转载自blog.csdn.net/yeshennet/article/details/82960102