我已知Android 的跨进程通信方式有6种,分别为:访问他应用的Activity、接收其他应用的广播、访问其它应用的

开放数据、AIDL、Messenger和socket的跨进程通信。

(1)访问他应用的Activity

举一个简单的例子:

这个就是调用系统打电话的代码。这就是一个简单的Activity的跨进程通信。

private void test_1(){Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:123654789"));  startActivity(callIntent);  }

那么Activity跨进程是怎么实现的呢?

服务端:(注:服务端和客户端是不同应用)

<activityandroid:name="xyzefg.xxx.yyyy.cccc.ServiceActivity" ><intent-filter><action android:name="com.service.activity" /><category android:name="android.intent.category.DEFAULT" /><data android:scheme="service" /></intent-filter></activity>
public class ServiceActivity extends Activity{TextView tv ;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.service);if (getIntent().getData() != null) {String host = getIntent().getData().getHost();Bundle bundle = getIntent().getExtras();String value = bundle .getString("value");tv = (TextView) findViewById(R.id.tv);tv.setText(host+":"+value);}}
}

客户端:

private void test_2(){  Intent callIntent = new Intent("com.service.activity", Uri    .parse("service://跨进程请求Activity" ));  Bundle extras = new Bundle();  extras.putString("value", "我可是跨进程的");  callIntent.putExtras(extras);  startActivity(callIntent);    }  

服务端主要实现分为三步:

1,设置启动的action <action/>

2,定义一个访问协议 <data/>

3,设置默认分类 <category/>

客户端:只要按照对应的action和协议就能请求到服务端的Activity

(2)接收其他应用的广播

举个简单的例子:

动态注册监听系统没分钟变化的广播。

   private void registerTimeReceiver(){IntentFilter intentFilter = new IntentFilter();intentFilter.addAction(Intent.ACTION_TIME_CHANGED);intentFilter.addAction(Intent.ACTION_TIME_TICK);registerReceiver(myReceive, intentFilter);}BroadcastReceiver myReceive = new BroadcastReceiver(){@Overridepublic void onReceive(Context arg0, Intent arg1) {Log.d("TAG","触发了");}};

那么广播的跨进程是怎么实现的呢?

发送者:(注:发送者和接受者是不同的应用)

   private void test_3(){Intent intent = new Intent("com.my.receiver");intent.putExtra("value", "我可是跨进程的");sendBroadcast(intent);}

接收者:

public class MyReceiver extends BroadcastReceiver{public final static String ACTION = "com.my.receiver";@Overridepublic void onReceive(Context arg0, Intent arg1) {if (arg1.getAction() == ACTION) {Log.d("TAG", arg1.getStringExtra("value"));}}
}

注册广播:

①动态注册:

   private void registerTimeReceiver(){IntentFilter intentFilter = new IntentFilter();intentFilter.addAction(MyReceiver.ACTION);registerReceiver(myReceiver, intentFilter);}

② 静态 注册:

<receiver android:name="xyzefg.xxx.yyyy.cccc.MyReceiver" ><intent-filter><action android:name="com.my.receiver" /></intent-filter>
</receiver>

定义一个广播接收需要继承BroadcastReceiver 并从写里面的onReceiver 方法,并且不要忘记注册广播,并且指定广

播接收的Action。发送广播只需要定义一个意图对象的action指向接收的Receiver,然后调用sendBroadcast(Intent)。

(3)访问其它应用的开放数据

举一个简单的例子:

查询手机联系人。

private void test_4(){ContentResolver contentResolver = getContentResolver();Cursor cursor = contentResolver.query(android.provider.Contacts.Phones.CONTENT_URI, null, null, null, null);while (cursor.moveToNext()) {String name = cursor.getString(cursor.getColumnIndex(android.provider.Contacts.Phones.NAME));String num = cursor.getString(cursor.getColumnIndex(android.provider.Contacts.Phones.NUMBER));Log.d("TAG", "name:"+name+"\nPhoneNum:"+num);}}

相比上面2个ContentProvider相对来说是麻烦多了。

服务端:(注:服务端和客户端不是同一个应用)

Andriod:

package com.example.hellojni;import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;@DatabaseTable(tableName = "android")
public class Android {@DatabaseField(columnName="_id",generatedId = true)private Integer id;@DatabaseField(columnName = "name")private String name;@DatabaseField(columnName = "version")private String version;public Android() {}public Android(String name,String version){this.name = name;this.version = version;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getVersion() {return version;}public void setVersion(String version) {this.version = version;} }

DataBaseHelper:

package com.example.hellojni;import java.sql.SQLException;import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;public class DataBaseHelper extends OrmLiteSqliteOpenHelper{private final static String TABLENAME = "android";private static DataBaseHelper instance;private static Dao<Android, Integer> androidDao;private DataBaseHelper(Context context) {super(context, TABLENAME, null, 1);}public static synchronized DataBaseHelper getHelper(Context context)  {  if (instance == null)  {  synchronized (DataBaseHelper.class)  {  if (instance == null)  instance = new DataBaseHelper(context.getApplicationContext());  }  }  return instance;  }  @Overridepublic void onCreate(SQLiteDatabase arg0, ConnectionSource arg1) {try {TableUtils.createTable(arg1, Android.class);} catch (SQLException e) {e.printStackTrace();}}@Overridepublic void onUpgrade(SQLiteDatabase arg0, ConnectionSource arg1, int arg2, int arg3) {try {TableUtils.dropTable(arg1, Android.class, true);onCreate(arg0, arg1);} catch (SQLException e) {e.printStackTrace();}}public Dao<Android, Integer> getAndroidDao(){if (androidDao == null) {try {androidDao = super.getDao(Android.class);} catch (SQLException e) {e.printStackTrace();}}return androidDao;}@Overridepublic void close() {super.close();if (androidDao !=null) {androidDao = null;}}}

ContentProvider:

package com.example.hellojni;import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;public class MyContentProvider extends ContentProvider{private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);private static final int CODE_NOPARAM = 1;private static final int CODE_PARAM = 2;private static final String AUTHORITIES = "cn.siy.provider.database";private static final String PATH_1 = "android";private static final String PATH_2 = "android/#";//集合类型,返回值前面一般是固定的,后面的值是自己添加的,也可以加上包路径 private static final String TYPE_ANDROIDS = "vnd.android.cursor.dir/" + "android";  //非集合类型数据,返回值前面一般是固定的,后面的值是自己添加的,也可以加上包路径 private static final String TYPE_ANDROID = "vnd.android.cursor.item/" + "android";  /*** content://cn.siy.provider.database/android/1/name* * 其中content://是scheme Android规定必须是content* cn.siy.provider.database 是Authority ContentProvider的唯一标示*  /android/1/name 是path 指定对什么数据进行操作(对android表的id为1的name字段操作)*/DataBaseHelper helper;static{matcher.addURI(AUTHORITIES, PATH_1, CODE_NOPARAM);matcher.addURI(AUTHORITIES, PATH_2, CODE_PARAM);}@Overridepublic boolean onCreate() {helper = DataBaseHelper.getHelper(getContext());return true;}@Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {SQLiteDatabase sqLiteDatabase = helper.getWritableDatabase();int count =-1;switch (matcher.match(uri)) {case CODE_NOPARAM:count = sqLiteDatabase.delete(PATH_1, selection, selectionArgs);break;case CODE_PARAM:long id = ContentUris.parseId(uri);String where = "_id = " + id;if (null != selection && !"".equals(selection.trim())){where += " and " + selection;}count =  sqLiteDatabase.delete(PATH_1, where, selectionArgs);break;default:break;}getContext().getContentResolver().notifyChange(uri, null);return count;}@Overridepublic String getType(Uri arg0) {switch (matcher.match(arg0)) {case CODE_NOPARAM:return TYPE_ANDROIDS;case CODE_PARAM:return TYPE_ANDROID;default:break;}return null;}@Overridepublic Uri insert(Uri url, ContentValues values) {SQLiteDatabase db = helper.getWritableDatabase();long id = -1;switch (matcher.match(url)){case CODE_NOPARAM:// 若主键值是自增长的id值则返回值为主键值,否则为行号,但行号并不是RecNo列id = db.insert(PATH_1, "name", values); break;default:break;}if (id>0) {Uri insertUri = ContentUris.withAppendedId(url, id); getContext().getContentResolver().notifyChange(insertUri, null);return insertUri;}return null;}@Overridepublic Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {SQLiteDatabase sqLiteDatabase = helper.getReadableDatabase();Cursor cursor = null;switch (matcher.match(uri)) {case CODE_NOPARAM:cursor =  sqLiteDatabase.query(PATH_1, projection, selection, selectionArgs, null, null, sortOrder);break;case CODE_PARAM:long id = ContentUris.parseId(uri); // 取得跟在URI后面的数字String where = "_id = " + id;if (null != selection && !"".equals(selection.trim())){where += " and " + selection;}cursor = sqLiteDatabase.query(PATH_1, projection, where, selectionArgs, null, null, sortOrder);break;default:break;}cursor.setNotificationUri(getContext().getContentResolver(), uri);return cursor;}@Overridepublic int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {SQLiteDatabase sqLiteDatabase = helper.getWritableDatabase();int count = 0;switch (matcher.match(uri)) {case CODE_NOPARAM:count = sqLiteDatabase.update(PATH_1, values, selection, selectionArgs);break;case CODE_PARAM:long id = ContentUris.parseId(uri);String where = "_id = " + id;if (null != selection && !"".equals(selection.trim())){where += " and " + selection;}count = sqLiteDatabase.update(PATH_1, values, where, selectionArgs);default:break;}getContext().getContentResolver().notifyChange(uri, null);return count;}}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.testndk"android:versionCode="1"android:versionName="1.0" ><uses-sdkandroid:minSdkVersion="8"android:targetSdkVersion="18" /><uses-permission android:name="android.permission.INTERNET"/><uses-permission android:name="android.permission.CALL_PHONE"/><uses-permission android:name="android.permission.READ_CONTACTS" /><applicationandroid:allowBackup="true"android:icon="@drawable/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme" ><activityandroid:name="com.example.hellojni.SiyActivity"android:label="@string/app_name" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><provider android:exported="true"android:name="com.example.hellojni.MyContentProvider"android:authorities="cn.siy.provider.database"></provider></application></manifest>

数据库的操作使用了ormlite框架。

首先我对ContentProvider中增删改查几个方法的参数解释一下吧,因为一开始我自己也是糊涂,这里记录一下防止下

次自己又忘记了。

1)delete(Uri uri, String selection, String[] selectionArgs);

第一个参数 uri:uri怎么解释呢?恩!就是每个内容提供者的唯一标示,用指定你访问的是哪一个内容提供者。

第二个参数 selecttion:他可以单独使用也可以和selectionArgs配合使用。先解释它怎么单独使用例如:

contentResolver.delete(Uri.parse("content://cn.siy.provider.database/android"), "_id in (14,13,12)", null);


上面语句的意思就是删除_id是12,13,14的记录,执行之后的结果

单独使用的时候他就相当于条件语句,放在where 之后。也可以传null表示删除所有。再看看它怎么和selectionArgs配合使用:

contentResolver.delete(Uri.parse("content://cn.siy.provider.database/android"), "_id in(?,?,?)", new String[]{"14","13","12"});

执行结果和上面的结果一样。selecttion你面有多少个“?”,selectionArgs里面就要有多少个数据进行相应的替换,特别注意顺序额!

第三个参数selectionArgs:他就是配合selecttion的,如果selecttion是空的,它也可以传null。

2)insert(Uri uri, ContentValues values)

第一个参数uri:同上不做解释。

第二个参数 values:他是一个类似map的数据结构,可以put进键值对,key是表结构的列名,value是列名对应的值,具体用法如:

ContentValues contentValues = new ContentValues();
contentValues.put("name", "Android-N");
contentValues.put("version", "7.0");
contentResolver.insert(Uri.parse("content://cn.siy.provider.database/android"), contentValues);

3)query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

第一个参数uri:同上不做解释。

第二个参数projection:它表示查询后要显示的列名,可以传null表示查询显示所有,类似如sql语句的“*”。

第三个参数selection:同上不解释。

第四个参数selectionArgs:同上不解释。

第五参数sortOrder:它是指按照什么顺序排序,相当于sql的order by。具体用法如:

Cursor cursor = contentResolver.query(Uri.parse("content://cn.siy.provider.database/android"), null, null, null, "_id desc");


4)update(Uri uri, ContentValues values, String selection, String[] selectionArgs)

参数的意思都能在上面找到我就不说了。

要编写ContentProvider:

1,要继承要写一个类继承ContentProvider然后重写里面的方法,一般会有onCreate(),getType(),delete(),insert(),query(),update()。

2,指定一个唯一标示当前provider的uri。provider的uri的规则content://+Authority+path。content://是Android规定的不允许更改的,Authority自己指定作为provider的唯一标示,最好两级以上,何为两级以上呢?自己领悟!path是标示

操作对象一般表名什么。

举个例子吧:

content://cn.siy.provider.database/android/1/name

其中content://是scheme Android规定必须是content
cn.siy.provider.database 是Authority ContentProvider的唯一标示
 /android/1/name 是path 指定对什么数据进行操作(对android表的id为1的name字段操作)

3,既然uri里面包含这么多信息,那么provider怎么知道呢?Android为我们提供UriMatcher这个类,它允许我们将定

义好的uri添加到其中。

private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);static{matcher.addURI(AUTHORITIES, PATH_1, CODE_NOPARAM);matcher.addURI(AUTHORITIES, PATH_2, CODE_PARAM);}

UriMatcher.NO_MATCH是匹配失败返回的值为-1。CODE_NOPARAM表示匹配path_1返回的值,CODE_PARAM表

示path_2返回的值。其中“匹配”动作可以通过matcher.match(uri)方法实现,这样就可以通过不同的返回值来进行不同的操作了。

4,既然provider是的四大组件之一(Activity,receiver,service,provider),那么它也是要在AndroidManifest.xml注册的。

<provider android:exported="true"android:name="com.example.hellojni.MyContentProvider"android:authorities="cn.siy.provider.database">
</provider>

authorities就是上面说的uri中的authorities,name就是ContentProvider的全类名,exported为true表示它对其他应用可

见。

要使用provider:

1,首先你得有ContentResolver,这个你一调用Activity的getContentResolver()得到。

2, 然后通过ContentResolver的增删改查方法就可以调用provider的增删改查方法了,参数名的意思上面有说。

3,Uri.parse("content://cn.siy.provider.database/android")把字符串编程uri

到此provider的简单实用就解释完了,不说了。

(4)AIDL

例子不知道怎么举了,那就直接上代码吧!

服务端:(注:服务端和客户端不是同一个应用)

IService.aidl

package com.example.mytest.zoomInImanage;import com.example.mytest.zoomInImanage.Android;interface IService{/** 八种基本类型  shot 会报错额**/String input1(byte arg1,/**shot arg2,**/int arg3,char arg4,boolean arg5,float arg6,double arg7,long arg8);String input2(String arg1,CharSequence arg2);/** 需要使用in、out或inout修饰。其中in表示这个值被客户端设置;out表示这个值被服务端设置;inout表示这个值既被客户端设置,又被服务端设置。 **/Android input3(in List<String> arg1,in Map arg2);/** 必须要导包  **/String input4(in Android arg1);
}

Android.java(其实就是上面的Android类实现了Parcelable,哈哈...)

package com.example.mytest.zoomInImanage;import android.os.Parcel;
import android.os.Parcelable;import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;@DatabaseTable(tableName = "android")
public class Android implements Parcelable {@DatabaseField(columnName = "_id", generatedId = true)private Integer id;@DatabaseField(columnName = "name")private String name;@DatabaseField(columnName = "version")private String version;public Android() {}public Android(String name, String version) {this.name = name;this.version = version;}public Android(Integer id,String name, String version) {this.id = id;this.name = name;this.version = version;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getVersion() {return version;}public void setVersion(String version) {this.version = version;}@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel arg0, int arg1) {// 注:Parcel中的数据是按顺序写入和读取的,即先被写入的就会先被读取出来 arg0.writeInt(id);arg0.writeString(name);arg0.writeString(version);}//该静态域是必须要有的,而且名字必须是CREATOR,否则会出错  public static final Parcelable.Creator<Android> CREATOR = new Creator<Android>() {@Overridepublic Android[] newArray(int arg0) {return new Android[arg0];}@Overridepublic Android createFromParcel(Parcel arg0) {//从Parcel读取通过writeToParcel方法写入的Person的相关成员信息  return new Android(arg0.readInt(), arg0.readString(), arg0.readString());}};}

Android.aidl(aidl传输的Parcelable对象,必须顶一个相应的aidl文件)

parcelable Android;

Myservice.java

package com.example.mytest.zoomInImanage;import java.util.List;
import java.util.Map;import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;public class MyService extends Service{class MyBinder extends IService.Stub{@Overridepublic String input1(byte arg1, int arg3, char arg4, boolean arg5, float arg6, double arg7, long arg8)throws RemoteException {return arg1+"-"+arg3+"-"+arg4+"-"+arg5+"-"+arg6+"-"+arg7+"-"+arg8+"-over";}@Overridepublic String input2(String arg1, CharSequence arg2) throws RemoteException {return arg1+"-"+arg2+"-over";}@Overridepublic Android input3(List<String> arg1, Map arg2) throws RemoteException {if (arg2.containsKey(1)) {if (arg2.get(1) instanceof Android) {return (Android)arg2.get(1);}}return null;}@Overridepublic String input4(Android arg1) throws RemoteException {return arg1.getName();}}private MyBinder mybinder;@Overridepublic void onCreate() {super.onCreate();Log.d("TAG", "onCreate");mybinder = new MyBinder();}@Overridepublic IBinder onBind(Intent arg0) {Log.d("TAG", "onBind");return mybinder;}}

AndroidManifest.xml

<service android:name="com.example.mytest.zoomInImanage.MyService"android:exported="true"><intent-filter><!--  指定调用AIDL服务的ID  -->  <action android:name="com.siy.servicer" /></intent-filter></service>

客户端:

Intent intent = new Intent("com.siy.servicer");
IService iservice;
bindService(intent, conn, Context.BIND_AUTO_CREATE);ServiceConnection conn = new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName arg0) {}@Overridepublic void onServiceConnected(ComponentName arg0, IBinder arg1) {Log.d("TAG", arg0+"");iservice = IService.Stub.asInterface(arg1);}};

使用AIDL:

1,首先呢得写一个服务的aidl文件,里面定义一些需要实现的方法。

2,关于方法的参数:

①支持除了shot类型以为的基本类型(byte,char,int,boolean,float,long,double)

②支持String,CharSequence类型

③支持实现Parcelable序列化的类型

④支持List,Map,但是里面传输的类型必须是以上4种

3,如果传输Parcelable序列化的对象,必须定义相应的aidl文件,并且不要忘记在服务的aidl文件中导包

4,实现的服务类,必须在onBind返回服务的aidl的实现类的桩对象(也有人说是句柄对象,随便你叫什么),就是那个

继承.Stub的对象。

5,在AndroidManifest.xml中注册。

6,在客户端绑定服务,用iservice = IService.Stub.asInterface(arg1)获取远程服务对象。注意哈,你的服务端的

.aidl文件都要拷一份给

客户端并且包名不能变。

(5)Messenger

例子不举了吧!

我还是看代码吧!我觉得代码最能让人理解。

MessageService:

public class MessageService extends Service{public static final int FROMCLIENT = 123;private Messenger service = new Messenger(new Handler(){@Overridepublic void handleMessage(Message msg) {Message serviceMessage = Message.obtain();switch (msg.what) {case FROMCLIENT:serviceMessage.what = FROMCLIENT;Android an = (Android)(msg.obj);
//            serviceMessage.obj = an.getName();
//            serviceMessage.arg1 = msg.arg1;Bundle bundle = msg.getData();Android andriod_1 = (Android) bundle.getSerializable("android_1");Android android_2 = (Android) bundle.getSerializable("android_2");Android android = new Android(andriod_1.getId() + android_2.getId(), andriod_1.getName() +android_2.getName(), andriod_1.getVersion() + android_2.getVersion());Bundle bundle_1 = new Bundle();bundle_1.putSerializable("android", android);serviceMessage.setData(bundle_1);try {msg.replyTo.send(serviceMessage);} catch (RemoteException e) {e.printStackTrace();}break;default:break;}super.handleMessage(msg);};});@Overridepublic IBinder onBind(Intent arg0) {return service.getBinder();}}

AndroidManifest.xml

<service android:name="com.example.mytest.photowall.MessageService"android:exported="true"><intent-filter ><action android:name="com.siy.messageservice"/></intent-filter>
</service>

client:

  private static final int FROMCLIENT = 123;private Messenger mServiceMessage;private ServiceConnection messageConn = new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {mServiceMessage = null;}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mServiceMessage = new Messenger(service);Log.d("TAG", "连上了");}};private Messenger client = new Messenger(new Handler(){@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case FROMCLIENT:Bundle bundle = msg.getData();Android android = (Android) bundle.getSerializable("android");Log.d("TAG", "messenger:"+android);break;default:break;}super.handleMessage(msg);}});private void test_7(){Message clientMessage = Message.obtain();clientMessage.what = FROMCLIENT;
//      clientMessage.obj = new Android(1, "andorid-n", "7.0");
//      clientMessage.arg1 = 1;Bundle bundle = new Bundle();bundle.putSerializable("android_1", new Android(1,"andriod-1", "1.0"));bundle.putSerializable("android_2", new Android(2,"android-2", "2.0"));clientMessage.setData(bundle);clientMessage.replyTo = client;try {mServiceMessage.send(clientMessage);} catch (RemoteException e) {e.printStackTrace();}}

使用messenger:

1,在服务器定一个Messenger 并以Handler为参数实例化它。

2,在AndroidManifest.xml注册它

3,在客户端也是用一个Messenger并以Handler参数实例化它进行通信的。

其实messenger的使用非常简单。但是他们通信所传递的对象如果是int型直接用户message.arg1 和message.arg2

就行了,如果是自定义对象不能用message.obj,而要使用message.setData(),而且我发现不能使用Parcelable对象

要使用Serializable,不知道是不是我的使用方式不对,反正我使用Parcelable老是报错的。

(6)Socket:

例子不举了吧!

我还是看代码吧!我觉得代码最能让人理解。

SocketServicer:

public class SocketServicer extends Service{private boolean mIsServideDestoryed = false;private String[] mDefinedMessages = new String[]{"你好啊,哈哈","请问你叫什么名字?","今天深圳的天气不太好诶","你知道吗,我是可以同时和很多人聊天额","给你讲一个笑话吧,一二三,笑话"};@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {new Thread(new TcpService()).start();System.out.println("servicer启动了");super.onCreate();}@Overridepublic void onDestroy() {mIsServideDestoryed=true;super.onDestroy();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {return super.onStartCommand(intent, flags, startId);}private  class TcpService implements Runnable{@Overridepublic void run() {ServerSocket serverSocket = null;//监听本地8688端口try {serverSocket = new ServerSocket(8688);}catch (IOException e){e.printStackTrace();return;}while(!mIsServideDestoryed){try {//接受客户端的请求final Socket client = serverSocket.accept();System.out.println("客户端已经连上了");System.out.println("client_1"+client);new Thread(){@Overridepublic void run() {try{System.out.println("client_2"+client);responseClinet(client);}catch (IOException e){e.printStackTrace();}}}.start();}catch (IOException e){}}}}private void responseClinet(Socket client) throws IOException{//用于接受客户端的消息BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));//用于向客户端发送消息PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())),true);out.println("欢迎大家了来到聊天室");while(!mIsServideDestoryed){String str = in.readLine();System.out.println("msg form client:"+str);if(str == null){//客户端断开break;}int i = new Random().nextInt(mDefinedMessages.length);String msg = mDefinedMessages[i];out.println(msg);}if(in != null){in.close();}if(out!=null){out.close();}if(client!=null){client.close();}System.out.println("client活着4");}
}

SocketClientTest:

public class SocketClientTest extends Activity {private Socket mclientSocket;private BufferedReader mBufferedReader;private PrintWriter mPrintWriter;private static final int MESAGE_RECEIVE_NEW_MSG = 1;private static final int MESAGE_SOCKET_CONNECTED = 2;private EditText client_1;private TextView service_1;private TextView service_2;private TextView service_3;private Button sendbut;private Handler mhandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MESAGE_SOCKET_CONNECTED:break;case MESAGE_RECEIVE_NEW_MSG:if (TextUtils.isEmpty(service_1.getText())){service_1.setText((String)msg.obj);return;}if (TextUtils.isEmpty(service_2.getText())){service_2.setText((String)msg.obj);return;}if (TextUtils.isEmpty(service_3.getText())){service_3.setText((String)msg.obj);}break;}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.socket_service_layout);client_1 = (EditText) findViewById(R.id.clinet_1);service_1 = (TextView) findViewById(R.id.servicer_1);service_2 = (TextView) findViewById(R.id.servicer_2);service_3 = (TextView) findViewById(R.id.servicer_3);sendbut = (Button) findViewById(R.id.send);sendbut.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if(!TextUtils.isEmpty(client_1.getText()) && mPrintWriter !=null){mPrintWriter.println(client_1.getText());client_1.setText("");}}});new Thread() {@Overridepublic void run() {connectSocketServier();}}.start();}@Overrideprotected void onDestroy() {try{if(mclientSocket !=null){mclientSocket.shutdownInput();mclientSocket.close();;}}catch (IOException e){e.printStackTrace();}super.onDestroy();}private void connectSocketServier() {Socket client = null;while (client == null) {try {client = new Socket("localhost", 8688);mclientSocket = client;System.out.println("connect service success");} catch (IOException e) {SystemClock.sleep(1000);System.out.println("connect service failed,retry...");}}try {mBufferedReader = new BufferedReader(new InputStreamReader(mclientSocket.getInputStream()));mPrintWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(mclientSocket.getOutputStream())),true);mhandler.sendEmptyMessage(MESAGE_SOCKET_CONNECTED);while (!SocketClientTest.this.isFinishing()) {String msg = mBufferedReader.readLine();System.out.println("service:" + msg);if (msg != null) {mhandler.obtainMessage(MESAGE_RECEIVE_NEW_MSG, msg).sendToTarget();}}if (mBufferedReader != null) {mBufferedReader.close();}if (mPrintWriter != null) {mPrintWriter.close();}if (mclientSocket != null) {mclientSocket.close();}} catch (IOException e) {e.printStackTrace();}}}
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

以上就socket的跨进程通讯的全部代码,其实socket不仅可跨进程通讯,也可以进行网络的通讯,只要ip彼此可见。

以上6种方式都可以跨进程通讯各有什么优缺点适应什么场景呢?
名称 优点 缺点 使用场景
Bundle 简单易用 名只能传输Bundle支持的类型的数据 四大组件间的进程间的通讯
AIDL 功能强大 使用稍微有点复杂,需要处理好线程同步 一对多通信且有RPC(远程方法调用)需求
Messenger 功能一般,支持一对多串行通信, 支持实时通信 不能很好的处理高并发的情形,不支持RPC,数据通过
Message进行传输,因此只能传输Bundle支持的数据
类型
低并发的一对多即时通讯,无RPC需求,或则无须
返回结果的RPC通讯
ContenProvider 在数据源访问方面功能强大, 支持一对多并发数
据共享,可通过Call方法扩展其他操作
可以理解为受约束的AIDL,主要提供数据源的CRUD
操作
一对多的进程间的数据共享
Socket 功能强大,可以通过网络传输字节流,支持一对
多的实时通讯
实现细节稍微有点繁琐,不支持RPC 网络数据交换

Android 跨进程通讯的方式相关推荐

  1. android 跨进程点击方式总结

    我们在日常的测试中,经常需要模拟用户点击等操作来实现模拟用户各种输入功能,在这里归纳总结一下几种点击方式,以及它们各自的优缺点,目前实现跨进程点击方式大致会有一下四种方式 一 adb shell 命令 ...

  2. Android进阶——Android跨进程通讯机制之Binder、IBinder、Parcel、AIDL

    前言 Binder机制是Android系统提供的跨进程通讯机制,这篇文章开始会从Linux相关的基础概念知识开始介绍,从基础概念知识中引出Binder机制,归纳Binder机制与Linux系统的跨进程 ...

  3. Android跨进程通讯机制之Binder、IBinder、Parcel、AIDL

    https://blog.csdn.net/qq_30379689/article/details/79451596 前言 Binder机制是Android系统提供的跨进程通讯机制,这篇文章开始会从L ...

  4. android中跨进程通讯的4种方式

    由于android系统中应用程序之间不能共享内存.因此,在不同应用程序之间交互数据(跨进程通讯)就稍微麻烦一些.在android SDK中提供了4种用于跨进程通讯的方式.这4种方式正好对应于andro ...

  5. android listview 滑动黑屏,Android 跨进程启动Activity黑屏(白屏)的三种解决方案

    当Android跨进程启动Activity时,过程界面很黑屏(白屏)短暂时间(几百毫秒?).当然从桌面Lunacher启动一个App时也会出现相同情况,那是因为App冷启动也属于跨进程启动Activi ...

  6. linux 跨进程读取内存,Android之Linux跨进程通信的方式

    As we all know,Android是基于Linux内核开发的,而市面上几乎所有的App都离开跨进程通信.可能你会说Android是通过Binder完成进程之间的通信的.但是Binder是怎么 ...

  7. Android ContentProvider实现两个程序间数据共享demo,跨进程通讯

    1.客户端代码: 先实现服务端 SQL创建: public class DBHelper extends SQLiteOpenHelper {// 数据库名private static final S ...

  8. Android AILD跨进程通讯 解决bindService无法启动

    场景:APP-A 服务端,APP-B 客户端.B启动service,通过IBinder,拿到服务端User列表,并向User表中添加人员信息.从而实现两个APP跨进程通讯 一,服务端APP 步骤:1, ...

  9. IPCInvoker,Android跨进程调用如此简单

    一个APP为什么需要多条进程? 如果一条进程能够拥有足够多的资源,且不会被系统kill掉的话,让程序运行在一条进程上是最好的选择.但是系统资源是按进程来分配的,每条进程资源分配是有个上限的,而且当我们 ...

最新文章

  1. curl 安装_记一次因curl版本过低导致zabbix server不停重启问题及解决方法
  2. 如何确定最初克隆本地Git存储库的URL?
  3. c语言330转化成字符,c/字符串,字符转数字,数字转字符(转)
  4. nginx配置文件语法高亮的Sublime Text扩展
  5. Opencv显示创建Mat对象的七种方式
  6. DataUml Design 介绍8-DataUML 1.2版本正式发布
  7. mongodb在aggregate lookup 进行分页查询,获得记录总数
  8. 插入迭代器、流迭代器、反向迭代器、移动迭代器
  9. 遍历删除_面试难题:List 如何一边遍历,一边删除?
  10. python获取类的类属性_在python中获取类和实例的属性
  11. Spring学习手册 1:Spring MVC 返回JSON数据
  12. 曲则全,枉则直;洼则盈,敝则新;少则得,多则惑。
  13. linux 测试post接口
  14. wsdl文件 服务器地址,webservice 的wsdl文件详解
  15. C语言程序设计题目汇总(不断更新中)
  16. JavaScript 身份证验证
  17. word没自动保存?===如何通过asd文件恢复
  18. 线程池的设计与原理解析(二)之---execute()方法
  19. font:12px/1.5 tahoma, arial, \5b8b\4f53, sans-serif详解
  20. SVG不能铺满的问题

热门文章

  1. 设计模式学习笔记(二十四):策略模式
  2. 见微知著,以小“控”大的三极管(七)
  3. #!/usr/bin/env python
  4. uCharts常用图表示例
  5. SQL索引使用以及性能总结
  6. 5分钟让你看懂Consul特性及搭建
  7. 学生成绩管理系统(六):项目总结
  8. Soot(Java静态分析框架)入门
  9. 震源机制(Focal Mechanism)之沙滩球(Beach Ball)
  10. 2011年5月27日 Extjs后台登陆