首先引申下AIDL。什么是AIDL呢?IPC? ------ Designing a Remote Interface Using AIDL

通常情况下,我们在同一进程内会使用Binder、BroadCastReciver让Service跟Activity进行通信。数据交互,数据共享。可是跨进程呢?

IPC:IPC接口,IPC接口本地代理  ------  Implementing IPC Using AIDL

AIDL意为:Android Interface Define Language 即 Android 接口描写叙述语言

与J2ee的差别:Java中不同意跨进程内存共享,仅仅传递对象,採用RMI方式,也能够通过序列化传递对象

Android AIDL: 採用AIDL方式。能够传递Bundle,实现起来略微麻烦些

实现过程:在服务端定义AIDL文件,ADT插件编译器将其编译之后。会在R文件同级文件夹文件下生成.java文件,轻量级,使用代理类在client和实现层间传

递值

语法:能够申明接口和方法,參数和返回值不是不论什么类型,不须要申明import,String。charSequence等

AIDL使用起来也不是非常麻烦。我个人感觉非常有用!

所以今天就说说关于AIDL的特性。非常多朋友在自己的博客仅仅是说它的理论而不是写一些实例来解说。我个人感觉你仅仅是说说他的

理论,一般人根本就看不懂。并且本来就是非常抽象的东西,又摸不着,你们写了也是白写。

全然不顾新手的感受。应该是写一些小样例,让大家參与进来一起学习和探讨效果才最佳!

并且也不是一大堆的文字,看起来也不会那么乏味。大家说是不?

以下就開始今天的AIDL/IPC解说与学习吧~,概念都讲的差点儿相同了,接下来就是实战。代码小样例给刚開始学习的人细嚼慢咽

从服务端线程開始写,结构图:

EngineerJspRemoteService.aidl 写完之后保存,就会在gen文件自己主动创建一个.java文件

EngineerJspService.java

package com.example.engineerjspserver;
/**
* AIDL/IPC
* @author Engineer-Jsp
* @date 2014.11.17
* */
import java.io.FileDescriptor;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class EngineerJspService extends Service{
private static final String TAG = "EngineerJspService";
MediaPlayer player;
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "EngineerJspService is onBind..."+"\n来自client的绑定操作已经完毕...");
if(player==null){
player = MediaPlayer.create(this, R.raw.music);
player = new MediaPlayer();
try {
FileDescriptor file = getResources().openRawResourceFd(R.raw.music).getFileDescriptor();
player.setDataSource(file);
player.setLooping(true);
} catch (Exception e) {
Log.d(TAG, e.toString());
}
Log.d(TAG, "player is created..."+"\n服务端播放器已经实例化。准备就绪...");
}
return binder;
}
private IBinder binder = new EngineerJspRemoteService.Stub() { @Override
public void onStop() throws RemoteException {
try {
if(player.isPlaying()){
Log.d(TAG, "client进程对服务端进程运行了暂停操作...");
player.stop();
}
} catch (Exception e) {
Log.d(TAG, e.toString());
}
} @Override
public void onPause() throws RemoteException {
try {
if(player.isPlaying()){
return;
}
Log.d(TAG, "client进程对服务端进程运行了開始操作...");
player.prepare();
player.start();
} catch (Exception e) {
Log.d(TAG, e.toString());
}
}
};
public boolean onUnbind(Intent intent) {
if(player!=null){
player.release();
}
Log.d(TAG, "EngineerJspService is onUnBind..."+"\nclient已经解绑断线,服务停止了...");
return super.onUnbind(intent); }; }

配置文件:

<?xml version="1.0" encoding="utf-8"?

>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.engineerjspserver"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="18" /> <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.engineerjspserver.MainAcivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".EngineerJspService" android:process=":remote">
<intent-filter >
<action android:name="com.example.engineerjspserver.EngineerJspService"/>
</intent-filter>
</service>
</application> </manifest>

当完毕上述操作之后。须要在res文件夹下导入測试文件,比方我的測试文件一个music.mp3,须要与layout文件同级

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvanNwcGluZw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

搞定服务端之后。接下来就是client线程编写,之后进行进程通信測试

把服务端的aidl文件所在的包所有复制到client的src下。把aidl文件除外的所有删掉

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvanNwcGluZw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

EngineerJspActivity.java

package com.example.engineerjspclient;
/**
* AIDL/IPC
* @author Engineer-Jsp
* @date 2014.11.17
* */
import com.example.engineerjspserver.EngineerJspRemoteService; import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
public class EngineerJspActivity extends Activity {
private static final String TAG = "EngineerJspActivity";
private static final String ACTION = "com.example.engineerjspserver.EngineerJspService";
private EngineerJspRemoteService EJService;
private boolean isBind = false;
private Button onPause,onStart; private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
isBind = false;
EJService = null;
Log.d(TAG, "onServiceDisconnected" +
"————"+"包名:"+name.getPackageName()+" "+"类名: "+name.getClassName()+"\n当client线程断线操作。服务将被清空...");
}
@Override
public void onServiceConnected(ComponentName name, IBinder ibinder) {
EJService = EngineerJspRemoteService.Stub.asInterface(ibinder);
isBind = true;
Log.d(TAG, "onServiceConnected————"+"包名:"+name.getPackageName()+" "+"类名: "+name.getClassName()+" "+"ibinder对象: "+ibinder.toString()+"\nclient线程与服务端线程连接中...");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_engineer_jsp);
Log.d(TAG, "client线程Activity创建成功,初始化控件与绑定服务中...");
Bind();
intiView();
}
@Override
protected void onDestroy() {
UnBind();
Log.d(TAG, "client线程被销毁,活动被解绑停止了...");
super.onDestroy();
}
public void Bind(){
Log.d(TAG, "Activity已经创建完毕,运行绑定服务端线程活动中...");
Intent intent = new Intent(ACTION);
bindService(intent, connection, BIND_AUTO_CREATE);
}
public void UnBind(){
if(isBind){
Log.d(TAG, "Activity被销毁了,与服务端线程的通信将被解绑停止...");
unbindService(connection);
EJService = null;
isBind = false;
}
}
private void intiView(){
onPause = (Button)findViewById(R.id.onPause);
onStart = (Button)findViewById(R.id.onStop);
onPause.setOnClickListener(listener);
onStart.setOnClickListener(listener);
Log.d(TAG, "服务端线程的组件初始化完毕...");
}
private OnClickListener listener = new OnClickListener(){ @Override
public void onClick(View view) {
if(view.getId()==R.id.onPause){
try {
EJService.onPause();
Log.d(TAG, "client线程对服务端线程运行了播放操作...");
Toast.makeText(EngineerJspActivity.this,"client线程对服务端线程运行了播放操作...", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Log.d(TAG, e.toString());
}
}else{
try {
EJService.onStop();
Log.d(TAG, "client线程对服务端线程运行了暂停操作...");
Toast.makeText(EngineerJspActivity.this,"client线程对服务端线程运行了暂停操作...", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Log.d(TAG, e.toString());
}
}
} };
}

activity_engineer_jsp.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".EngineerJspActivity" > <Button
android:id="@+id/onStop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_below="@+id/button1"
android:layout_marginTop="42dp"
android:text="onStop" /> <Button
android:id="@+id/onPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/onStop"
android:layout_alignParentRight="true"
android:layout_below="@+id/onStop"
android:text="onPause" /> </RelativeLayout>

配置文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.engineerjspclient"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="18" /> <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.engineerjspclient.EngineerJspActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application> </manifest>

启动服务端进程与client进程(不在同一个进程内,也就是不在同一个APK程序之内)。在DDMS里进行进程和堆栈查看

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvanNwcGluZw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

当服务端进程开启之后,会等待client进程接入与操作,类似c/s模式,Socket,client进程开启之后,服务端測试数据例如以下



client測试数据:



服务測试:

client进程对服务端进程运行了播放操作:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvanNwcGluZw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">



client进程对服务端进程运行了暂停操作:







两个进程项目图结构:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvanNwcGluZw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

AIDL这个小实例内容就这么多,概念也说得差点儿相同了,你们好好看看,消化消化~

很多其它精彩尽在本博。欢迎大家一起学习和交流~!

AIDL/IPC Android AIDL/IPC 进程通信机制——超具体解说及使用方法案例剖析(播放器)的更多相关文章

  1. 图文详解 Android Binder跨进程通信机制 原理

    图文详解 Android Binder跨进程通信机制 原理 目录 目录 1. Binder到底是什么? 中文即 粘合剂,意思为粘合了两个不同的进程 网上有很多对Binder的定义,但都说不清楚:Bin ...

  2. Android 进程通信机制之 AIDL

    什么是 AIDL AIDL 全称 Android Interface Definition Language,即 安卓接口描述语言.听起来很深奥,其实它的本质就是生成进程间通信接口的辅助工具.它的存在 ...

  3. Qt 的内部进程通信机制

    Qt 的内部进程通信机制 续欣 (xxin76@hotmail.com), 博士.大学讲师 2004 年 4 月 01 日 Qt 作为一种跨平台的基于 C++ 的 GUI 系统,能够提供给用户构造图形 ...

  4. Android中的常见通信机制和Linux中的通信机制

    Handler Handler是Android系统中的一种消息传递机制,起作用是应对多线程场景.将A进程的消息传递给B线程,实现异步消息处理.很多情况是将工作线程中需要更新UI的操作消息传递给UI主线 ...

  5. 我所理解的Android组件化之通信机制

    之前写过一篇关于Android组件化的文章,<Android组件化框架设计与实践>,之前没看过的小伙伴可以先点击阅读.那篇文章是从实战中进行总结得来,是公司的一个真实项目进行组件化架构改造 ...

  6. Storm进程通信机制

    storm的worker进程之间消息传递机制图: 每个worker都有一个独立的监听进程,监听配置文件中配置过的端口列表supervisor.slots.ports,topology.receiver ...

  7. Socket进程通信机制及应用

    Socket通常称为“套接字”,用于描述IP地址和端口,是一个通信链的句柄.应用程序通过套接字向网络发出请求或者应答网络请求.Socket即不是一个程序,也不是一个协议,其只是操作系统提供的通信层的一 ...

  8. Socket进程通信机制

    1.Socket通常称为“套接字”,用于描述IP地址和端口,是一个通信链的句柄. 2.应用程序通过套接字向网络发出请求或者应答网络请求. 3.Socket既不是一个程序,也不是一种协议,其只是操作系统 ...

  9. Android(java)学习笔记234: 服务(service)之音乐播放器

    1.我们播放音乐,希望在后台长期运行,不希望因为内存不足等等原因,从而导致被gc回收,音乐播放终止,所以我们这里使用服务Service创建一个音乐播放器. 2.创建一个音乐播放器项目(使用服务) (1 ...

随机推荐

  1. java中HashMap,LinkedHashMap,TreeMap,HashTable的区别

    java为数据结构中的映射定义了一个接口java.util.Map;它有四个实现类,分别是HashMap Hashtable LinkedHashMap 和TreeMap Map主要用于存储健值对,根 ...

  2. ios之UITableView

    今天要分享的是IOS开发中一个使用率非常高的一个控件-------UITableView,这两天正在使用tableview做信息的显示,在写代码时对tableview和tableviewcell的几种 ...

  3. Linux环境下挂载SD卡的教程

    1.插入SD卡 如果系统能够识别SD卡,则会打印一些信息: 2.查看系统给SD卡分配的设备名 命令如下: fdisk -l 命令 说明:通常是根据SD卡的存储容量来确定的. 比如下面的信息: 3.挂载 ...

  4. Hash冲突的几种解决方法

    1. 开放定值法: 也叫再散列法,当关键字key的哈希地址p=H(key)出现冲突时,以p为基础,产生另一个哈希地址p1,如果p1仍然冲突,再以p为基础,产生另一个哈希地址p2,…,直到找出一个不冲突 ...

  5. PHP基于phpqrcode类生成二维码的方法详解

    前期准备: 1.phpqrcode类文件下载,下载地址:https://sourceforge.net/projects/phpqrcode/2.PHP环境必须开启支持GD2扩展库支持(一般情况下都是 ...

  6. transformer模型解读

    最近在关注谷歌发布关于BERT模型,它是以Transformer的双向编码器表示.顺便回顾了<Attention is all you need>这篇文章主要讲解Transformer编码 ...

  7. python编程之API入门: (二)python3中使用新浪微博API

    回顾API使用的流程 通过百度地图API的使用,我理解API调用的一般流程为:生成API规定格式的url->通过urllib读取url中数据->对json格式的数据进行解析.下一步,开始研 ...

  8. 可编辑div的createRange()

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 // 在元素的指定位 ...

  9. Leetcode 224.基本计算器

    基本计算器 实现一个基本的计算器来计算一个简单的字符串表达式的值. 字符串表达式可以包含左括号 ( ,右括号 ),加号 + ,减号 -,非负整数和空格  . 示例 1: 输入: "1 + 1 ...

  10. Mac安装Protobuf

    1. 下载protobuf2.6.1:https://github.com/google/protobuf/releases/download/v2.6.1/protobuf-2.6.1.tar.gz ...