跨进程通信_android跨进程通信 - CSDN
精华内容
参与话题
  • android 四种跨进程通信

    千次阅读 2018-08-14 12:21:12
    1.Intent(显示一般用于同一程序,隐式一般都是跨进程) intent/Bundle支持传递类型: 1.八大基本数据类型 2.String、Character引用类型 3.实现了Serializable和Parcelable接口的对象 action指动作,可以多个...

    区分一下Linux的进程间通信的方式:管道,Binder,socket,共享内存;

     

     

    1.Intent(显示一般用于同一程序,隐式一般都是跨进程)

    intent/Bundle支持传递类型:

    1.八大基本数据类型

    2.String、Character引用类型

    3.实现了Serializable和Parcelable接口的对象

    action指动作,可以多个,但跳转的activity中的infiter一定要包含这个action;

    category(0个或多个):比如指定默认登录主界面:CATEGORY_LAUNCHER;

    data(只有一个)的scheme指的是前缀http等;

    host指的是主机名google.com等

    port指url端口号

    2.Content Provider

    3.广播

    4.AIDL

    首先AIDL支持的类型有(没有Serializable对象):

    八大基本类型;

    String,Character,List,Map;

    实现了Parcelable接口的对象;

     

    步骤:

    1.创建一个服务端(在OnBind方法中返回一个IBinder对象,这个对象是是通过AIDL接口名.Stub来得到的)

    2.创建一个客户端;(在服务端调用OnBind方法后,客户端就可以和服务端连接了;怎么连?实现ServiceConnection类,里面也要用到AIDL接口名来获取各种服务端传过来的值(即把Binder对象转为ADIL接口))

    3.创建AIDL接口文件(直接新建一个普通文件(New->File),取名为 ABXXXService.aidl的aidl后缀文件

     

    首先,先创建一个service子类

     客户端:

    AIDL文件:

     

     

    展开全文
  • IPC进程间通信/跨进程通信

    千次阅读 多人点赞 2019-02-16 09:50:36
    概念进程:一个JVM就是一个进程 线程:最小的调度单元 一个进程可以包含多个线程,在安卓中有一个主线程也就是UI线程,UI线程...比如Windows中通过剪贴板,管道,油槽等进行进程通信,Linux通过命名管道,共享内容

    #概念
    进程:一个JVM就是一个进程
    线程:最小的调度单元
    一个进程可以包含多个线程,在安卓中有一个主线程也就是UI线程,UI线程才可以操作界面,如果在一个线程里面进行大量耗时操作在安卓中就会出现ANR(Application Not Responding)
    #Android中IPC来源
    IPC不是安卓中独有的 ,比如Windows中通过剪贴板,管道,油槽等进行进程间通信,Linux通过命名管道,共享内容,信号量等进行进程间通信,虽然Android基于Linux但是不完全继承Linux,Android中独特的进程间通信Binder,同时也支持socket。
    #Android进程间通信通常用在如下几个方面
    当应用中某个模块需要单独运行在某个进程中;或者相同通过多个进程来扩大应用的内存;当前应用需要向其他应用获取数据(其实COntenProvider去查询数据也是跨进程通信只不过底层分装之后我们察觉不到而已)。
    #Android如何开启多进程
    这里只讨论一个APP内的多进程,暂不讨论两个应用之间的多进程
    这里我们目前讨论正规方式:通过Androidmenifest文件中给四大组件(Activity,BroadCast Receiver,Service,ContentProvide)添加Android:process 属性,暂不讨论通过JNI非正规方式开启新进程
    例:<Activity Android:name:".xxxxActivity" Android:process:".remote"/>
    这样我们启动这个Activity的时候就会新开启一个进程。

    扫码关注公众号“伟大程序猿的诞生“,更多干货新鲜文章等着你~

    公众号回复“资料获取”,获取更多干货哦~

    有问题添加本人微信号“fenghuokeji996” 或扫描博客导航栏本人二维码

    展开全文
  • 跨进程通信IPC方式

    2019-03-09 22:56:44
    四大组件中的三大组件(Activity,Service,Receiver)都支持在intent中传递Bundle数据(Bundle数据实现了Parcelable接口),当我们在一个进程中启动了另一个进程的Activity,Service,Receive,可以在Bundle中附加...

    1.使用Bundle(intent)

    四大组件中的三大组件(Activity,Service,Receiver)都支持在intent中传递Bundle数据(Bundle数据实现了Parcelable接口),当我们在一个进程中启动了另一个进程的Activity,Service,Receive,可以在Bundle中附加我们需要传递给远程进程的信息并通过intent发送出去。
    重点:

    		Intent intent=new Intent("vera.CALL", Uri.parse("infovera://woshiInvoke"));
            intent.putExtra("value","成功");
            startActivity(intent);
    

    示例:
    a.在一个进程中设置Main2Activity的action 、data、category。

            <activity android:name=".Main2Activity">
                <intent-filter>
                    <action android:name="vera.CALL" />
    
                    <data android:scheme="infovera" />
    
                    <category android:name="android.intent.category.DEFAULT" />
                </intent-filter>
            </activity>
    
    

    b.在另一个进程中唤醒这个Main2Activity(新建一个项目invokeApp)

      public class MainActivity extends AppCompatActivity {
    
        @butterknife.BindView(R.id.invoke)
        Button invoke;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            butterknife.ButterKnife.bind(this);
        }
    
        @butterknife.OnClick(R.id.invoke)
        public void onViewClicked() {
            Intent intent=new Intent("vera.CALL", Uri.parse("infovera://woshiInvoke"));
            intent.putExtra("value","成功");
            startActivity(intent);
        }
    }
    
    

    c.在Main2Activity中获取另一个进程传递过来的数据

    public class Main2Activity extends AppCompatActivity {
            public static final String ACTION_CALL = "vera.CALL";
            @BindView(R.id.btn)
            Button btn;
            @BindView(R.id.edit)
            EditText edit;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main2);
            ButterKnife.bind(this);
            if(getIntent().getData()!=null){
    //            获得host,就是infovera://后面的内容
                String host=getIntent().getData().getHost();
                Bundle bundle=getIntent().getExtras();// 与intent.putExtra("value","成功")对应
    //            在bundle中附加的信息
                String value=bundle.getString("value");
                edit.setText(host+";"+value);
            }
        }
    
        @OnClick(R.id.btn)
        public void onViewClicked() {
            Toast.makeText(this, edit.getText().toString(), Toast.LENGTH_SHORT).show();
        }
    }
    

    在第一个activity中显示出来远程进程传递给它的数据

    2.使用文件共享

    两个进程通过读写同一个文件来交换数据。除了交换一些文本信息之外,还可以序列化一个对象到文件系统的同时从另一个进程恢复这个对象。
    一个序列化对象

    package com.example.myapplication;
    
    import java.io.Serializable;
    
    /**
     * <p>文件描述:<p>
     * <p>创建时间:2019/3/9<p>
     */
    public class User implements Serializable {
    
        private static final long serialVersionUID = -4712598323293490897L;
        public int userId;
        public String name;
    
        @Override
        public String toString() {
            return "User{" +
                    "userId=" + userId +
                    ", name='" + name + '\'' +
                    '}';
        }
    
        public User(int userId, String name) {
            this.userId = userId;
            this.name = name;
        }
    
        public static long getSerialVersionUID() {
            return serialVersionUID;
        }
    
        public int getUserId() {
            return userId;
        }
    
        public void setUserId(int userId) {
            this.userId = userId;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

    在清单文件中把Main4Activity设置为另一个进程:

    		<activity android:name=".Main4Activity"
                android:process="vera.activity4"></activity>
    

    实现序列化

    public class Main3Activity extends AppCompatActivity {
        private static final String TAG = "vera";
        User user;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main3);
            if (ContextCompat.checkSelfPermission(Main3Activity.this, Manifest.permission_group.STORAGE)!= PackageManager.PERMISSION_GRANTED){
                ActivityCompat.requestPermissions(this,new String[]{Manifest.permission_group.STORAGE},1);
            }
            user=new User(1,"zhang1");
    
            persistToFile();
        }
    
        private void persistToFile() {
    
    
                    File dir=new File(MyConstants.CHAPTER_2_PATH);
                    if (!dir.exists())dir.mkdirs();
                    File cachedFile=new File(MyConstants.CACHE_FILE_PATH);
                    ObjectOutputStream objectOutputStream=null;
                    try {
                        objectOutputStream=new ObjectOutputStream(new FileOutputStream(cachedFile));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        objectOutputStream.writeObject(user);
                        Log.e(TAG, "writeObject: user"+user );
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        objectOutputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
        }
    }
    
    package com.example.myapplication;
    
    import android.os.Environment;
    
    public class MyConstants {
        public static final String CHAPTER_2_PATH = Environment
                .getExternalStorageDirectory().getPath()
                + "/singwhatiwanna/chapter_2/";
    
        public static final String CACHE_FILE_PATH = CHAPTER_2_PATH + "usercache";
    }
    

    反序列化

    package com.example.myapplication;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    
    public class Main4Activity extends AppCompatActivity {
        private static final String TAG = "vera";
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main4);
            Log.e(TAG, "onCreate: " );
            recoverFromFile();
        }
        private void recoverFromFile() {
    
                    User user=null;
                    File cachedFile=new File(MyConstants.CACHE_FILE_PATH);
                    if(cachedFile.exists()){
                        ObjectInputStream objectInputStream=null;
                        try {
                            objectInputStream=new ObjectInputStream(new FileInputStream(cachedFile));
                            user= (User) objectInputStream.readObject();
                            Log.e(TAG, "run: user:"+user );
                        } catch (IOException e) {
                            e.printStackTrace();
                        } catch (ClassNotFoundException e) {
                            e.printStackTrace();
                        }finally {
                            try {
                                objectInputStream.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
        }
    }
    
    

    3.使用Messenger

    在不同进程中传递Message对象,底层实现是AIDL。Messenger以串行的方式处理客户端的请求,服务端只能一个一个地处理。主要方法是通过Messenger传输message(mMessenger.send(message);)。

    a.服务端进程

    package com.example.messenger;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.os.Messenger;
    import android.util.Log;
    
    public class MyService extends Service {
        public MyService() {
        }
        private static final String TAG = "vera";
    
        private static class MyHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case 1:
                        Log.e(TAG, "handleMessage:from client : " + msg.getData());
                        break;
                    default:
                        super.handleMessage(msg);
                }
    
            }
        }
    //通过创建一个Handler对象来创建一个Messenger对象,Messenger的作用是将客户端发送过来的消息交给Handler处理
        private final Messenger mMessenger = new Messenger(new MyHandler());
    
        @Override
        public IBinder onBind(Intent intent) {
            return mMessenger.getBinder();//返回Messenger对象底层的Binder
        }
    }
    
    

    让service运行在单独的进程里:

            <service
                android:name=".MyService"
                android:enabled="true"
                android:process=":vera"
                android:exported="true"></service>
    
    

    b.客户端进程

    package com.example.messenger;
    
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.IBinder;
    import android.os.Message;
    import android.os.Messenger;
    import android.os.RemoteException;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Intent intent=new Intent(this,MyService.class);
            bindService(intent,mServiceConnection,BIND_AUTO_CREATE);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unbindService(mServiceConnection);
        }
    
        private Messenger mMessenger;
        private ServiceConnection mServiceConnection=new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                mMessenger=new Messenger(service);//用服务端返回的IBinder对象创建一个Messenger
                Message message=Message.obtain(null,1);
                Bundle bundle=new Bundle();
                bundle.putString("value","this is client.");
                message.setData(bundle);//通过这个Messenger发送消息messager
                try {
                    mMessenger.send(message);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
    
    
            }
        };
    }
    
    
    2019-03-09 18:01:26.916 1806-1806/? E/vera: handleMessage:from client : this is client.
    

    如果让服务端回应客户端:
    服务端的改变为

    package com.example.messenger;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.os.Messenger;
    import android.os.RemoteException;
    import android.util.Log;
    
    public class MyService extends Service {
    
    
    
        private static final String TAG = "vera";
    
        private static class MyHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case 1:
                        Log.e(TAG, "handleMessage:from client : " + msg.getData().getString("value"));
                        Messenger client=msg.replyTo;
                        Message replyMessage=Message.obtain(null,2);
                        Bundle bundle=new Bundle();
                        bundle.putString("reply","this is server");
                        replyMessage.setData(bundle);
                        try {
                            client.send(replyMessage);
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                        break;
                    default:
                        super.handleMessage(msg);
                }
    
            }
        }
    //通过创建一个Handler对象来创建一个Messenger对象,Messenger的作用是将客户端发送过来的消息交给Handler处理
        private final Messenger mMessenger = new Messenger(new MyHandler());
    
        @Override
        public IBinder onBind(Intent intent) {
            return mMessenger.getBinder();//返回Messenger对象底层的Binder
        }
    }
    
    

    客户端的改变为

    package com.example.messenger;
    
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.os.Messenger;
    import android.os.RemoteException;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    
    public class MainActivity extends AppCompatActivity {
        private static final String TAG = "vera";
    
        private Messenger mReplyMessenger=new Messenger(new MyHandler());
        public static class MyHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case 2:
                        Log.e(TAG, "handleMessage: from server:  " + msg.getData().getString("reply"));
                        break;
                    default:
                        super.handleMessage(msg);
                }
            }
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Intent intent = new Intent(this, MyService.class);
            bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unbindService(mServiceConnection);
        }
    
        private Messenger mMessenger;
        private ServiceConnection mServiceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                mMessenger = new Messenger(service);//用服务端返回的IBinder对象创建一个Messenger
                Message message = Message.obtain(null, 1);
                Bundle bundle = new Bundle();
                bundle.putString("value", "this is client.");
                message.setData(bundle);//通过这个Messenger发送消息messager
                message.replyTo=mReplyMessenger;
                try {
                    mMessenger.send(message);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
    
    
            }
        };
    }
    
    

    效果如下:

    2019-03-09 18:12:28.014 2076-2076/com.example.messenger:vera E/vera: handleMessage:from client : this is client.
    2019-03-09 18:12:28.044 2057-2057/com.example.messenger E/vera: handleMessage: from server:  this is server
    

    4.使用AIDL

    点击创建aidl文件
    在这里插入图片描述
    Book类实现Parcelable接口

    package com.example.aidl_client;
    
    import android.os.Parcel;
    import android.os.Parcelable;
    
    /**
     * <p>文件描述:<p>
     * <p>创建时间:2019/3/9<p>
     */
    public class Book implements Parcelable {
        public int bookId;
        public String bookName;
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(this.bookId);
            dest.writeString(this.bookName);
        }
    
        public Book() {
        }
    
        protected Book(Parcel in) {
            this.bookId = in.readInt();
            this.bookName = in.readString();
        }
        @Override
        public String toString() {
            return "Book{" +
                    "bookId=" + bookId +
                    ", bookName='" + bookName + '\'' +
                    '}';
        }
        public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() {
            @Override
            public Book createFromParcel(Parcel source) {
                return new Book(source);
            }
    
            @Override
            public Book[] newArray(int size) {
                return new Book[size];
            }
        };
    }
    
    

    Book.aidl是Book类在AIDL中的声明,名字一定要一样。

    // Book.aidl
    package com.example.aidl_client;
    
    // Declare any non-default types here with import statements
    
    parcelable Book;
    
    

    IMyAidlInterface.aidl中一定要导入Book类(import com.example.aidl_client.Book;)

    // IMyAidlInterface.aidl
    package com.example.aidl_client;
    
    // Declare any non-default types here with import statements
    import com.example.aidl_client.Book;
    interface IMyAidlInterface {
        List<Book> getBookList();
        void addBook(in Book book);
    }
    

    点击make,系统自动生成IMyAidlInterface.java
    在这里插入图片描述
    把aidl这个文件夹拷贝到服务端
    在这里插入图片描述
    clean project

    服务端:实现IMyAidlInterface文件中定义的方法

    package com.example.aidl_server;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    import android.os.RemoteException;
    
    import com.example.aidl_client.Book;
    import com.example.aidl_client.IMyAidlInterface;
    
    import java.util.List;
    import java.util.concurrent.CopyOnWriteArrayList;
    
    public class MyService extends Service {
        public MyService() {
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            mBooks.add(new Book(1,"zhang"));
            mBooks.add(new Book(2,"xu"));
        }
    
        private CopyOnWriteArrayList<Book> mBooks=new CopyOnWriteArrayList<Book>();
        private Binder mBinder=new IMyAidlInterface.Stub() {
            @Override
            public List<Book> getBookList() throws RemoteException {
                return mBooks;
            }
    
            @Override
            public void addBook(Book book) throws RemoteException {
    
                mBooks.add(book);
            }
        };
        @Override
        public IBinder onBind(Intent intent) {
    
            return mBinder;
        }
    }
    
    

    客户端调用服务端的方法,隐式调用一定要加包名。

    package com.example.aidl_client;
    
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    
    import java.util.List;
    
    public class MainActivity extends AppCompatActivity {
    
        private static final String TAG = "vera";
        private ServiceConnection mServiceConnection=new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                IMyAidlInterface mIMyAidlInterface=IMyAidlInterface.Stub.asInterface(service);
                try {
                    List<Book> mList=mIMyAidlInterface.getBookList();
                    Log.e(TAG, "onServiceConnected: list type:"+mList.getClass().getCanonicalName() );
                    Log.e(TAG, "onServiceConnected: list "+mList.toString() );
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
    
            }
        };
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Intent intent=new Intent();
            intent.setAction("vera.aidl");
            intent.setPackage("com.example.aidl_server");
    //        intent.setClassName("com.example.aidl_server","com.example.aidl_server.MyService");
            bindService(intent,mServiceConnection,BIND_AUTO_CREATE);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unbindService(mServiceConnection);
        }
    }
    
    

    在build.gradle中加入:

        sourceSets {
            main {
                manifest.srcFile 'src/main/AndroidManifest.xml'
                java.srcDirs = ['src/main/java', 'src/main/aidl']
                resources.srcDirs = ['src/main/java', 'src/main/aidl']
                aidl.srcDirs = ['src/main/aidl']
                res.srcDirs = ['src/main/res']
                assets.srcDirs = ['src/main/assets']
            }
        }
    
    
    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 28
    
    
    
        defaultConfig {
            applicationId "com.example.aidl_server"
            minSdkVersion 19
            targetSdkVersion 28
            versionCode 1
            versionName "1.0"
    
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    
        }
        sourceSets {
            main {
                manifest.srcFile 'src/main/AndroidManifest.xml'
                java.srcDirs = ['src/main/java', 'src/main/aidl']
                resources.srcDirs = ['src/main/java', 'src/main/aidl']
                aidl.srcDirs = ['src/main/aidl']
                res.srcDirs = ['src/main/res']
                assets.srcDirs = ['src/main/assets']
            }
        }
    
    
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            }
        }
    
    }
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
    
        implementation 'com.android.support:appcompat-v7:28.0.0'
        implementation 'com.android.support.constraint:constraint-layout:1.1.3'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'com.android.support.test:runner:1.0.2'
        androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    }
    
    

    效果如下:

    2019-03-09 20:48:36.862 4154-4154/com.example.aidl_client E/vera: onServiceConnected: list [Book{bookId=1, bookName='zhang'}, Book{bookId=2, bookName='xu'}]
    

    5.使用ContentProvider

    6.使用socket

    展开全文
  • 跨进程通信基础篇 含义: 跨进程通信,是指两个进程之间数据交换的过程,英文全称 Inter-Process Communication 缩写IPC 进程和线程的关系: 在移动设备上,一个程序或者一个应用,就是一个进程,一个进程里面可以包含...

    跨进程通信基础篇

    含义:
    跨进程通信,是指两个进程之间数据交换的过程,英文全称 Inter-Process Communication 缩写IPC

    进程和线程的关系:
    在移动设备上,一个程序或者一个应用,就是一个进程,一个进程里面可以包含多个线程
    (例如:一个应用里面有一个主线程(用于更新UI)和多个子线程(执行耗时的任务))

    开启多线程的方法:
    在Android中开启多进程只有一种方法: 那就是给4大组件(Activity,Service,Receiver,ContentProvider)在Menifest中指定android:process属性,除此之外没有其他的方法(通过JNI在native层去fork一个新进程除外)

    实例1如下:

    <activity
        android:name=".activity.Main2Activity"
        android:process=":remote1" />
    

    实例2如下:

    <activity
        android:name=".activity.Main3Activity"
        android:process="com.hlj.demo.remote2" />
    

    说明:
    1.首先实例1中 ":“的含义是指:这是一种简写
    a.当前的进程名称前面要附加上当前的包名 进程完整名称:com.hlj.demo:remote1
    b.以”:"开头的进程属于当前应用的私有进程,其他应用的组件不可以和它跑在同一个进程中
    2,实例2中的进程名称是一种完整的命名方式,不会附加包名信息,其次它属于全局进程,其他应用通过ShareUID方式可以和它跑在同一个进程中.(2个应用的签名也要相同)

    注意:
    程序入口MainActivity,默认没有给它process属性,那么它就运行在默认的进程中,默认的进程名称是包名,如果给它指定了process属性,那么它就运行在该指定进程当中

    如何查看自己开启了多少个进程呢,studio如下图所示:
    在这里插入图片描述
    运行在同一个进程中的组件是属于同一个虚拟机和同一个Application,可以共享Applicaiton下的数据,运行在不同进程中的组件是属于2个不同的虚拟机和2个不同的Application,2个不同的Application数据是不能互通的

    IPC的基础概念: Serializable接口,Parcelable接口,Binder

    Serializable接口:Serializable是java所提供的一个序列化的接口,它是一个空接口,为对象提供序列化和反序列化操作

    //实现Serializable接口即可
    public class UserBean implements Serializable{
        private static final long serialVersionUID=1L;
        public String name;
    }
    
    UserBean user = new UserBean();
    user.name = "hao123";
    if (!StrUtils.IsKong(Environment.getExternalStorageDirectory() + "/" + "demo")) {
          String baseExternalStoragepath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "demo";
          baseDirectory = new File(baseExternalStoragepath);
          if (!baseDirectory.exists()) {
              //先创建文件夹
              baseDirectory.mkdirs();
          }
          //再创建文件
          File wejian = new File(baseDirectory.getPath() + "/" + "user.txt");
          if (!wejian.exists()) {
              wejian.createNewFile();
          }
          //序列化到文件中
          ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(wejian));
          out.writeObject(user);
          out.flush();
          out.close();   
      }
    
    
     //反序列化,从文件中读取文件
      File wejian=new File(baseDirectory.getPath()+"/"+"user.txt");
      ObjectInputStream in=new ObjectInputStream(new FileInputStream(wejian));
      UserBean user=(UserBean)in.readObject();
      in.close();
    

    注意:
    序列化和反序列化需要读写文件,所以需要在清单文件配置读写权限,大于6.0的设备还要动态申请权限

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    

    serialVersionUID:
    一般来说我们应该手动指定serialVersionUID的值,这样做的好处是:当版本升级后,我们可能删除了某个成员变量也可能增加了一些新的成员变量,但指定了这个值以后,反序列化还是可以成功,程序可以最大限度的恢复数据,如果不指定serialVersionUID的值的话,程序会挂掉,但是如果类结构发生了非常规性的改变,例如修改了成员变量的类型结构,这种毁灭性的改变后,反序列化还是会失败,因为无法从老版本的数据中还原一个新的类型结构的对象

    注意:
    1,静态成员属于类不属于对象,所以不会参与序列化的过程
    2,用transient关键字标记的成员变量不会参与序列化的过程

    Parcelable接口
    Parcelable 是android中提供的新的序列化方式,只要实现这个接口,一个类的对象就可以实现序列化,并且可以通过Intent和Binder传输

    实例如下:

    public class User2 implements Parcelable {
        public  int age;
        //体重
        public  int weight;
        public  String name;
        public Book book;
    
        public User2(){
        
        }
    
        public User2(Parcel in) {
        //注意:这里读取字段的属性要和写入字段的顺序一样 age,weight,name,book
            age=in.readInt();
            weight=in.readInt();
            name=in.readString();
            //由于book是另一个序列化对象,所以它的反序列化的过程要传递当前上下文类加载器
            book= in.readParcelable(Thread.currentThread().getContextClassLoader());
            
        }
    
        //studio会自动生成这里
        public static final Creator<User2> CREATOR = new Creator<User2>() {
            @Override
            public User2 createFromParcel(Parcel in) {
                return new User2(in);
            }
    
            @Override
            public User2[] newArray(int size) {
                return new User2[size];
            }
        };
    
        //studio会自动生成这里
        @Override
        public int describeContents() {
            return 0;
        }
    
    
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(age);
            dest.writeInt(weight);
            dest.writeString(name);
            dest.writeParcelable(book,0);
        }
    }
    
    

    说明:
    1,从Parcel in里面读取字段的顺序一定要和writeToParcel字段的顺序一样(否则同一个类型的字段例如age和weight数据会搞混)

    2,由于Book是另一个序列化对象,所以它的反序列化的过程要传递当前上下文类加载器

    Parcelable接口和Serializable接口的比较
    共同点:都能实现序列化并且都可用于Intent间的数据传递
    不同点:Serializable是java中提供的接口,使用起来更加简单,但是开销很大,需要大量的IO操作,Parcelable是android中的序列化方式,所以更适用与android平台,缺点是使用起来稍微麻烦一点,优点是效率高

    Binder:
    直观来讲,Binder是android中的一个类,它实现了IBinder接口.从IPC的角度来讲,Binder是Android中的一种跨进程通信方式,从AndroidFramework角度来讲,Binder是ServiceManager连接各种Manager(ActivityNamager,WindowManger等等)的桥梁;从Android应用层来讲,Binder是客户端和服务端进行通信的媒介,当binderService的时候,服务端会返回一个包含服务端业务调用的Binder对象,通过这个Binder对象,客户端就可以获取服务端提供的服务或者数据,这里的服务包含普通的服务和基于AIDL的服务,普通的service服务不涉及进程间通信,主要是AIDL会涉及binder的核心

    结尾:
    下一篇会总结跨进程通信的几种方式,尽情期待啦~^^

    展开全文
  • Android跨进程通信的四种方式

    万次阅读 2016-07-03 23:04:39
    因此,在不同应用程序之间交互数据(跨进程通讯)就稍微麻烦一些。在android SDK中提供了4种用于跨进程通讯的方式。这4种方式正好对应于android系统中4种应用程序组件:Activity、Content Provider、Broadcast和...
  • 面试题:IPC(跨进程通信

    千次阅读 2019-10-03 11:37:10
    进程通信可能会出现什么问题? Q4:Android中IPC方式有几种? 为何新增Binder来作为主要的IPC方式? Q5:使用Binder进行数据传输的具体过程? Q6:Binder框架中ServiceManager的作用? Q7:Android中有哪些基于...
  • 跨进程通信(IPC)

    2018-09-19 21:39:17
    跨进程通信(IPC)-Inter-Process Communication Android多进程的使用场景 例如: 车联网这类牵涉到系统定制的话,对于多进程的使用应该还是很多的,说的比较简单的例子,一个应用商店App,就需要通过IPC通知Launcher下载...
  • Android跨进程通信:图文详解 Binder机制 原理

    万次阅读 多人点赞 2019-04-27 11:07:25
    如果你接触过 跨进程通信 (IPC),那么你对Binder一定不陌生 虽然 网上有很多介绍 Binder的文章,可是存在一些问题:浅显的讨论Binder机制 或 一味讲解 Binder源码、逻辑不清楚,最终导致的是读者们还是无法形成一...
  • 在不同应用程序之间交互数据(跨进程通讯),在Android SDK中提供了4种用于跨进程通讯的方式。这4种方式正好对应于android系统中4种应用程序组件:Activity、Content Provider、Broadcast和Service: Activity可以...
  • Qt 之进程通信(QProcess)

    万次阅读 2018-05-30 10:35:13
    简述QProcess可以在应用程序内部与其它进程通信,或启动其它应用程序。与在终端机之类的命令输入窗口上使用名称和参数是一样的,可以使用QProcess提供的函数start()启动进程。可以注册QStringList处理进程后的参数。...
  • 进程通信方式有六种,如下 msg_queue (消息队列) pipeline for single duplex (单工管道) pipeline for half duplex (半双工管道) name pipeline (命名管道) share memory (共享内存) semaphore (信号量) ...
  • 进程通信(IPC机制)精炼详解

    万次阅读 2018-04-20 15:38:43
    一、前期基础知识储备IPC定义:IPC是intent-Process Communication的缩写,含义为进程间通信或者跨进程通信,是指两个进程之间进行数据交换的过程。IPC不是Android所独有的,任何一个操作系统都需要有相应的IPC机制...
  • Qt 之进程通信(IPC)

    万次阅读 2018-05-30 10:35:53
    简述进程通信,就是在不同进程之间传播或交换信息。那么不同进程之间存在着什么双方都可以访问的介质呢?进程的用户空间是互相独立的,一般而言是不能互相访问的,唯一的例外是共享内存区。但是,系统空间却是...
  • Qt 之进程通信(共享内存)

    万次阅读 多人点赞 2018-05-30 10:35:21
    简述上一节中,我们分享下如何利用Windows消息机制来进行不同进程间的通信。但是有很多局限性,比如:不能平台,而且必须两个进程同时存在才可以,要么进程A发了消息谁接收呢?下面我们来分享另外一种平台的进行...
  • 内存映射 在 Linux操作系统中非常重要,因为其涉及到高效的跨进程通信 &amp; 文件操作 今天,我将详细讲解操作系统中核心概念:内存映射 目录 1. 定义 关联 进程中的1个虚拟内存区域 &amp; 1个磁盘上的...
  • 进程间的通信方式有很多种, 上次我们说了最傻瓜的“共享文件”的方法。
  • RPC(Remote Procedure Call)即远程过程调用,它是一种通过网络从远程计算机程序上请求服务,在不需要了解底层网络技术的协议下,即可获取计算机进程中的数据。RPC使得开发包括网络分布式多程序在内的应用程序更加...
  • 理解几种常见的进程通信方式

    千次阅读 2017-01-15 22:35:56
    什么是进程通信广义上讲,进程通信(Inter-Process Communication, IPC)是指运行在不同进程(不论是否在同一台机器)中的若干线程间的数据交换。从上面的定义可以得出两点: 参与通信进程即可以运行在同一台机器...
  • Android进程通信的几种方式

    千次阅读 2019-02-21 01:21:42
    定义多进程 Android应用中使用多进程只有一个办法(用NDK的fork来做除外),就是在AndroidManifest.xml中声明组件时,用android:process属性来指定。 不知定process属性,则默认运行在主进程中,主进程名字为包名...
  • MAC OSX 进程通信

    万次阅读 2014-11-18 20:29:10
    Mac OS下的IPC方式种类很多,大约有下面几种。  1. Mach API  2. CFMessagePort  3. Distributed Objects (DO) NSDistributedNotificationCenter 4. Apple events  ...5. UNIX domain sockets  ...
1 2 3 4 5 ... 20
收藏数 93,598
精华内容 37,439
关键字:

跨进程通信