IPC机制(三)--ContentProvider、Socket和Binder池

1.ContentProvider

ContentProvider的底层实现是基于Binder,系统为我们做了深度的封装,让我们使用起来非常容易。

// 第一步
// 实现一个内容提供者,每个CURD方法中实现对数据的提供,可以是大多是从数据库加载数据
public class BookProvider extends ContentProvider {

    private static final String AUTHORITY = "com.gacrnd.gcs.ipc.BookProvider";
    public static final Uri BOOK_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/book");
    public static final Uri USER_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/user");

    public static final int BOOK_URI_CODE = 0;
    public static final int USER_URI_CODE = 1;

    private Context mContext;
    private SQLiteDatabase mDatabase;

    private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    static {
        sUriMatcher.addURI(AUTHORITY,"book",BOOK_URI_CODE);
        sUriMatcher.addURI(AUTHORITY,"user",USER_URI_CODE);
    }

    // 通过uri获取表名
    private String getTableName(Uri uri) {
        String tableName = null;
        switch (sUriMatcher.match(uri)) {
            case BOOK_URI_CODE:
                tableName = DbOpenHelper.BOOK_TABLE_NAME;
                break;
            case USER_URI_CODE:
                tableName = DbOpenHelper.USER_TABLE_NAME;
                break;
            default:
                break;
        }
        return tableName;
    }

    @Override
    public boolean onCreate() {
        mContext = getContext();
        //以下应该在子线程中加载数据库
        initDatabase();
        return true;
    }

    // 初始化数据库
    private void initDatabase() {
        mDatabase = new DbOpenHelper(mContext).getWritableDatabase();
        mDatabase.execSQL("DELETE FROM " + DbOpenHelper.BOOK_TABLE_NAME);
        mDatabase.execSQL("DELETE FROM " + DbOpenHelper.USER_TABLE_NAME);
        mDatabase.execSQL("INSERT INTO book VALUES(1,'ANDROID 1');");
        mDatabase.execSQL("INSERT INTO book VALUES(2,'ANDROID 2');");
        mDatabase.execSQL("INSERT INTO book VALUES(3,'ANDROID 3');");
        mDatabase.execSQL("INSERT INTO user VALUES(1,'JackOu',0);");
        mDatabase.execSQL("INSERT INTO user VALUES(2,'DY',1);");
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        Log.i("JackOu","query:" + Thread.currentThread().getName());
        String tableName = getTableName(uri);
        if (tableName == null) {
            throw new IllegalArgumentException("uri illegal!");
        }
        return mDatabase.query(tableName,projection,selection,selectionArgs,null,sortOrder,null);
    }

    ......
    //需要基于数据库实现对应的CURD操作
}
// 第二步 在manifest中声明该Provider
<provider
    android:authorities="com.gacrnd.gcs.ipc.BookProvider"
    android:name=".BookProvider"
    android:permission="com.gacrnd.gcs.PROVIDER"
    android:process=":provider"/>
// 第三步
public class DbOpenHelper extends SQLiteOpenHelper {

    private static final String DB_NAME = "book_provider.db";
    public static final String BOOK_TABLE_NAME = "book";
    public static final String USER_TABLE_NAME = "user";

    private String CREATE_BOOK_TABLE = "CREATE TABLE IF NOT EXISTS " + BOOK_TABLE_NAME
            + "(_id INTEGER PRIMARY KEY, name TEXT)";
    private String CREATE_USER_TABLE = "CREATE TABLE IF NOT EXISTS " + USER_TABLE_NAME
            + "(_id INTEGER PRIMARY KEY, name TEXT, sex INT)";

    private static final int DB_VERSION = 1;

    public DbOpenHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_BOOK_TABLE);
        db.execSQL(CREATE_USER_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // 忽略数据库版本升级
    }
}
// 第四步在需要使用的地方获取数据即可
Uri uri = Uri.parse("content://com.gacrnd.gcs.ipc.BookProvider");
getContentResolver().query(uri,null,null,null,null); // 写两个主要是想打印工作线程信息
getContentResolver().query(uri,null,null,null,null);

2. Socket

Socket称为“套接字”,是网络通信中的概念,分为流式套接字和用户数据报套接字两种,分别对应网络传输控制层的TCP和UDP协议。TCP协议是面向连接的协议,提供稳定的双向通信功能,TCP连接的建立需要经过“三次握手”才能完成,为了提供稳定的数据传输功能,其本身提供了超时重传机制,因此具有很高的稳定性。而UDP是无连接的,提供不稳定的单向/双向通信功能,在性能上,UDP协议不需要握手和挥手,效率会更高

2.1 Socket服务端
public class TCPServerService extends Service {

    private boolean mDestory = false;
    
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        // 正常应该用一个线程池来处理客户端来的请求的,但是作为demo,就暴力的新开一个线程处理
        new Thread(new TcpServer()).start();
        super.onCreate();
    }

    private class TcpServer implements Runnable {
        @Override
        public void run() {
            ServerSocket serverSocket = null;
            try {
                serverSocket = new ServerSocket(10000);
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }
            // 死循环处理客户端的请求
            while (!mDestory) {
                try {
                    // 接收客户端
                    final Socket client = serverSocket.accept();
                    new Thread() {
                        @Override
                        public void run() {
                            try {
                                //处理客户端发来的内容并且回复客户端
                                responseClient(client);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }.start();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void responseClient(Socket client) throws IOException{
        //接收客户端的消息
        BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
        //发送数据到客户端
        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())));
        while (!mDestory) {
            String fromClient = in.readLine();
            System.out.println("msg from client:" + fromClient);
            if (fromClient == null) {
                //客户端断开,直接返回
                break;
            }
            out.println("收到你的消息");
        }
        //交流完毕
        in.close();
        out.close();
        client.close();
    }

    @Override
    public void onDestroy() {
        mDestory = true;
        super.onDestroy();
    }
}
2.2 Socket客户端
//很粗暴的连接服务端,接收并且发送,主要是演示socket通信过程
private void connectServerSocket() {
    PrintWriter pw = null;
    BufferedReader br= null;
    Socket socket = null;
    try {
        while (!mDestory) {
            socket = new Socket("localhost",10000);
            pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
            pw.println("client send msg");
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            System.out.println("receive from server:" + br.readLine());
         }
        pw.close();
        br.close();
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
3. Binder池

由于项目业务逻辑越来越服务,需要和多个AIDL交互,如果一个一个绑定,调用,这样显得比较麻烦,所以就有了Binder池的概念出来。所有要请求服务端都放在Binder池中,客户端通过Binder池拿到自己需要服务的客户端。

Binder池.png

3.1 binder池服务端
public class BinderPoolService extends Service {

    private Binder mBinderPool = new BinderPoolImpl();

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

public class BinderPoolImpl extends IBinderPool.Stub {

    private static final int SECURITY_SERVICE_PROXY = 0;
    private static final int COMPUTE_SERVICE_PROXY = 1;

    public BinderPoolImpl() {
        super();
    }

    @Override
    public IBinder queryBinder(int binderCode) throws RemoteException {
        IBinder binder = null;
        switch (binderCode) {
            case SECURITY_SERVICE_PROXY:
                // 此处用伪代码实现,返回SecurityCenterImpl,他继承ISecurityCenter.Stub(),实现了对应接口
                //binder = new SecurityCenterImpl();
                break;
            case COMPUTE_SERVICE_PROXY:
                //binder = new ComputerImpl();
                break;
            default:
                break;
        }
        return binder;
    }
}
3.2 Binder池客户端
public class BinderPool {

    private static volatile BinderPool sInstance = null;
    private IBinderPool mBinderPool = null;
    // 用于等待连接BinderPool,如果没有连接就一直阻塞等待
    private CountDownLatch mCountDownLatch;
    private ServiceConnection mServiceConnection = new BinderPoolServiceConnection();
    private IBinder.DeathRecipient mDeathRecipient = new BinderPoolDeathRecipient();
    private Context mContext;

    public BinderPool(Context context) {
        this.mContext = context.getApplicationContext();
        connectBinderPoolService();
    }

    public static BinderPool getInstance(Context context) {
        if (sInstance == null) {
            synchronized (BinderPool.class) {
                if (sInstance == null) {
                    sInstance = new BinderPool(context);
                }
            }
        }
        return sInstance;
    }

    private synchronized void connectBinderPoolService() {
        mCountDownLatch = new CountDownLatch(1);
        Intent intent = new Intent(mContext, BinderPoolService.class);
        mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
        try {
            mCountDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
    * 查询binder接口
    */
    public IBinder queryBinder(int binderCode) {
        IBinder binder = null;
        if (mBinderPool != null) {
            try {
                // 从Binder服务端查询需要的接口
                binder = mBinderPool.queryBinder(binderCode);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        return binder;
    }

    private class BinderPoolServiceConnection implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mBinderPool = IBinderPool.Stub.asInterface(service);
            try {
                mBinderPool.asBinder().linkToDeath(mDeathRecipient, 0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            //绑定成功,释放线程继续执行
            mCountDownLatch.countDown();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }

    private class BinderPoolDeathRecipient implements IBinder.DeathRecipient {
        @Override
        public void binderDied() {
            mBinderPool.asBinder().unlinkToDeath(mDeathRecipient, 0);
            mBinderPool = null;
            connectBinderPoolService();
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值