进程间通讯demo

255 阅读11分钟

以下是每种Android进程通信方式的具体使用示例,帮助你更好地理解它们的实际应用场景:

1.Intent

示例:从一个Activity跳转到另一个Activity并传递数据

// 在Activity A中
Intent intent = new Intent(ActivityA.this, ActivityB.class);
intent.putExtra("key", "Hello from Activity A");
startActivity(intent);

// 在Activity B中接收数据
Intent intent = getIntent();
String data = intent.getStringExtra("key");
Log.d("ActivityB", "Received data: " + data);

2.SharedPreference

示例:在不同进程间共享简单的配置信息

// 写入数据
SharedPreferences sharedPreferences = getSharedPreferences("my_prefs", Context.MODE_MULTI_PROCESS);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("username", "Kimi");
editor.apply();

// 读取数据
SharedPreferences sharedPreferences = getSharedPreferences("my_prefs", Context.MODE_MULTI_PROCESS);
String username = sharedPreferences.getString("username", "default");
Log.d("SharedPreference", "Username: " + username);

3.Binder

示例:通过Service实现进程间通信 服务端(Service)

public class MyService extends Service {
    private final IBinder binder = new MyBinder();

    public class MyBinder extends Binder {
        MyService getService() {
            return MyService.this;
        }
    }

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

    public void doSomething() {
        Log.d("MyService", "Doing something...");
    }
}

客户端(Activity)

private MyService myService;
private boolean isBound = false;

private ServiceConnection connection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName className, IBinder service) {
        MyService.MyBinder binder = (MyService.MyBinder) service;
        myService = binder.getService();
        isBound = true;
        myService.doSomething();//不跨端进程间rpc远程调用
    }

    @Override
    public void onServiceDisconnected(ComponentName arg0) {
        isBound = false;
    }
};

@Override
protected void onStart() {
    super.onStart();
    Intent intent = new Intent(this, MyService.class);
    bindService(intent, connection, Context.BIND_AUTO_CREATE);
}

@Override
protected void onStop() {
    super.onStop();
    if (isBound) {
        unbindService(connection);
        isBound = false;
    }
}

4.AIDL

示例:通过AIDL实现跨进程调用 定义AIDL接口

// IMyService.aidl
interface IMyService {
    void doSomething();
}

服务端(Service)

public class MyService extends Service {
    private final IMyService.Stub binder = new IMyService.Stub() {
        @Override
        public void doSomething() {
            Log.d("MyService", "Doing something...");
        }
    };

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

客户端(Activity)

private IMyService myService;

private ServiceConnection connection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName className, IBinder service) {
        myService = IMyService.Stub.asInterface(service);
        try {
            myService.doSomething();//不跨端进程间rpc调用
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName className) {
        myService = null;
    }
};

@Override
protected void onStart() {
    super.onStart();
    Intent intent = new Intent();
    intent.setComponent(new ComponentName("com.example.serviceapp", "com.example.serviceapp.MyService"));
    bindService(intent, connection, Context.BIND_AUTO_CREATE);
}

5.Messenger

示例:通过Messenger实现简单的单向通信 服务端(Service)

public class MyService extends Service {
    private final Messenger messenger = new Messenger(new IncomingHandler());

    private static class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    Log.d("MyService", "Received message: " + msg.getData().getString("key"));
                    break;
            }
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return messenger.getBinder();
    }
}

客户端(Activity)

private Messenger serviceMessenger;

private ServiceConnection connection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName className, IBinder service) {
        serviceMessenger = new Messenger(service);
        Message msg = Message.obtain(null, 1);
        Bundle data = new Bundle();
        data.putString("key", "Hello from Activity");
        msg.setData(data);
        try {
            serviceMessenger.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName className) {
        serviceMessenger = null;
    }
};

@Override
protected void onStart() {
    super.onStart();
    Intent intent = new Intent(this, MyService.class);
    bindService(intent, connection, Context.BIND_AUTO_CREATE);
}

6.Socket

示例:通过Socket实现客户端与服务器之间的通信 服务器端

ServerSocket serverSocket = new ServerSocket(8080);
Socket clientSocket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
    System.out.println("Received: " + inputLine);
}

客户端

Socket socket = new Socket("localhost", 8080);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println("Hello from client");

7.ContentProvider

示例:通过ContentProvider共享数据 定义ContentProvider

public class MyContentProvider extends ContentProvider {
    private static final String AUTHORITY = "com.example.myprovider";
    private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    static {
        uriMatcher.addURI(AUTHORITY, "items", 1);
    }

    @Override
    public boolean onCreate() {
        return true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        switch (uriMatcher.match(uri)) {
            case 1:
                // 返回查询结果
                return null;
        }
        return null;
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        return null;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }
}

客户端查询数据

Uri uri = Uri.parse("content://com.example.myprovider/items");
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
while (cursor.moveToNext()) {
    // 处理查询结果
}
cursor.close();

8.管道(Pipe)

管道是一种特殊的文件,用于进程间通信。它分为匿名管道和命名管道:

• 匿名管道:只能用于具有亲缘关系的进程(如父子进程)之间的通信,且通信是单向的。

• 命名管道:也称为FIFO(First In First Out),允许不相关的进程进行通信,通信是双向的。

使用示例:匿名管道

// 父进程代码
try {
    // 创建管道
    FileDescriptor pipeFd = ParcelFileDescriptor.createPipe();
    ParcelFileDescriptor readSide = ParcelFileDescriptor.dup(pipeFd, ParcelFileDescriptor.MODE_READ);
    ParcelFileDescriptor writeSide = ParcelFileDescriptor.dup(pipeFd, ParcelFileDescriptor.MODE_WRITE);

    // 子进程代码
    ProcessBuilder processBuilder = new ProcessBuilder("child_process");
    processBuilder.redirectInput(readSide.getFileDescriptor());
    processBuilder.redirectOutput(writeSide.getFileDescriptor());
    Process childProcess = processBuilder.start();

    // 父进程写入数据
    FileOutputStream fos = new FileOutputStream(writeSide.getFileDescriptor());
    fos.write("Hello from parent process".getBytes());
    fos.close();

    // 父进程读取子进程的输出
    FileInputStream fis = new FileInputStream(readSide.getFileDescriptor());
    byte[] buffer = new byte[1024];
    int bytesRead = fis.read(buffer);
    String message = new String(buffer, 0, bytesRead);
    Log.d("ParentProcess", "Received from child: " + message);
    fis.close();
} catch (IOException e) {
    e.printStackTrace();
}

9.文件共享

文件共享是通过文件系统来实现进程间通信。一个进程写入文件,另一个进程读取文件。这种方式简单易用,但不适合高并发场景。

使用示例

// 写入文件
try {
    FileOutputStream fos = new FileOutputStream("shared_file");
    fos.write("Hello from Process A".getBytes());
    fos.close();
} catch (IOException e) {
    e.printStackTrace();
}

// 读取文件
try {
    FileInputStream fis = new FileInputStream("shared_file");
    byte[] data = new byte[fis.available()];
    fis.read(data);
    String content = new String(data);
    Log.d("ProcessB", "Content: " + content);
    fis.close();
} catch (IOException e) {
    e.printStackTrace();
}

区别

• 管道(Pipe)

• 用途:主要用于进程间通信,尤其是父子进程或不相关进程之间的通信。

• 特点:管道是临时的,数据在管道中流动,读取后即被消费,不会永久存储。

• 并发:管道支持单向或双向通信,但需要正确管理读写操作以避免死锁。

• 性能:管道的读写操作相对较快,适合小数据量的快速传输。

• 文件共享

• 用途:用于进程间共享数据,数据存储在文件系统中。

• 特点:数据持久化,即使进程结束,数据仍然存在文件中。

• 并发:需要处理并发问题,如多个进程同时写入文件可能导致数据不一致。

• 性能:文件操作相对较慢,适合大数据量的存储和读取。

希望这些解释和示例能帮助你更好地理解管道和文件共享的区别和使用方法。

这些示例展示了每种通信方式的基本用法,你可以根据实际需求选择合适的通信方式来实现进程间的数据交互。

以下是使用Messenger实现双向通信的完整示例:

服务端(Service)

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;

public class ExampleService extends Service {
    static final int MSG_SAY_HELLO = 1;
    static final int MSG_REGISTER_CLIENT = 2;
    static final int MSG_UNREGISTER_CLIENT = 3;
    static final int MSG_REPLY_TO_CLIENT = 4;

    Messenger mClient = null; // 用于保存客户端的Messenger

    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SAY_HELLO:
                    // 当服务收到来自客户端的问候时,回复客户端
                    sendMessageToClient(MSG_REPLY_TO_CLIENT, "Hello from Service!");
                    break;
                case MSG_REGISTER_CLIENT:
                    // 客户端注册自己的Messenger
                    mClient = msg.replyTo;
                    break;
                case MSG_UNREGISTER_CLIENT:
                    // 客户端取消注册其Messenger
                    mClient = null;
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    final Messenger mMessenger = new Messenger(new IncomingHandler());

    @Override
    public IBinder onBind(Intent intent) {
        return mMessenger.getBinder();
    }

    private void sendMessageToClient(int what, String text) {
        if (mClient != null) {
            try {
                Bundle bundle = new Bundle();
                bundle.putString("reply", text);
                Message msg = Message.obtain(null, what);
                msg.setData(bundle);
                mClient.send(msg);
            } catch (RemoteException e) {
                mClient = null; // 客户端已断开连接
            }
        }
    }
}

客户端(Activity)

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
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.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {
    Messenger mService = null;
    boolean mBound = false;

    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case ExampleService.MSG_REPLY_TO_CLIENT:
                    String reply = msg.getData().getString("reply");
                    Toast.makeText(MainActivity.this, reply, Toast.LENGTH_SHORT).show();
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    final Messenger mMessenger = new Messenger(new IncomingHandler());

    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            mService = new Messenger(service);
            mBound = true;
            try {
                // 注册客户端的Messenger
                Message msg = Message.obtain(null, ExampleService.MSG_REGISTER_CLIENT);
                msg.replyTo = mMessenger;
                mService.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        public void onServiceDisconnected(ComponentName className) {
            mService = null;
            mBound = false;
        }
    };

    public void sayHello(View v) {
        if (!mBound) return;
        try {
            Message msg = Message.obtain(null, ExampleService.MSG_SAY_HELLO, 0, 0);
            mService.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button = findViewById(R.id.say_hello_button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sayHello(v);
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        bindService(new Intent(this, ExampleService.class), mConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mBound) {
            // 取消注册客户端的Messenger
            try {
                Message msg = Message.obtain(null, ExampleService.MSG_UNREGISTER_CLIENT);
                mService.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            unbindService(mConnection);
            mBound = false;
        }
    }
}

工作原理

• 客户端注册:客户端通过MSG_REGISTER_CLIENT消息将自己的Messenger传递给服务端。

• 服务端回复:服务端接收到客户端消息后,通过客户端的Messenger发送回复。

• 客户端接收:客户端通过自己的Handler接收服务端的回复。

通过这种方式,服务端和客户端可以互相发送消息,实现双向通信。

以下是使用 AIDL 实现双向通信的完整示例,同时结合linkToDeath机制来处理进程崩溃或断开恢复。

服务端(AIDL服务)

• 定义 AIDL 接口 创建IMyAidlInterface.aidl文件:

   package vac.test.aidlservice;

   interface IMyAidlInterface {
       void addPerson(in Person person);
       List<Person> getPersonList();
   }

• 实现 AIDL 接口 在服务端的AidlService中实现 AIDL 接口:

   package vac.test.aidlservice;

   import android.app.Service;
   import android.content.Intent;
   import android.os.Binder;
   import android.os.IBinder;
   import android.os.RemoteException;
   import android.util.Log;

   import java.util.ArrayList;
   import java.util.List;

   public class AidlService extends Service {
       private final IMyAidlInterface.Stub binder = new IMyAidlInterface.Stub() {
           private final List<Person> mPersons = new ArrayList<>();

           @Override
           public void addPerson(Person person) throws RemoteException {
               mPersons.add(person);
           }

           @Override
           public List<Person> getPersonList() throws RemoteException {
               return mPersons;
           }
       };

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

• 服务端监听客户端死亡 在服务端的AidlService中添加对客户端死亡的监听:

   package vac.test.aidlservice;

   import android.os.Binder;
   import android.os.IBinder;
   import android.os.RemoteException;
   import android.util.Log;

   public class AidlService extends Service {
       private final IMyAidlInterface.Stub binder = new IMyAidlInterface.Stub() {
           private final List<Person> mPersons = new ArrayList<>();
           private IBinder.DeathRecipient deathRecipient;

           @Override
           public void addPerson(Person person) throws RemoteException {
               mPersons.add(person);
           }

           @Override
           public List<Person> getPersonList() throws RemoteException {
               return mPersons;
           }

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

           @Override
           public void onRebind(Intent intent) {
               super.onRebind(intent);
               // 客户端重新绑定时的处理逻辑
           }

           @Override
           public boolean onUnbind(Intent intent) {
               // 客户端断开连接时的处理逻辑
               return true;
           }

           @Override
           public void linkToDeath(IBinder.DeathRecipient recipient, int flags) throws RemoteException {
               super.linkToDeath(recipient, flags);
               deathRecipient = recipient;
           }

           @Override
           public void unlinkToDeath(IBinder.DeathRecipient recipient, int flags) throws RemoteException {
               super.unlinkToDeath(recipient, flags);
               if (deathRecipient == recipient) {
                   deathRecipient = null;
               }
           }
       };

       private final IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
           @Override
           public void binderDied() {
               Log.d("AidlService", "客户端死亡");
               // 客户端死亡后的处理逻辑
           }
       };
   }

客户端(调用服务)

• 绑定服务 在客户端的MainActivity中绑定服务并调用 AIDL 接口:

   package vac.test.aidlclient;

   import android.app.Activity;
   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.util.Log;
   import android.view.View;
   import android.widget.Button;
   import android.widget.TextView;

   import vac.test.aidlservice.IMyAidlInterface;
   import vac.test.aidlservice.Person;

   public class MainActivity extends Activity {
       private IMyAidlInterface mService;
       private boolean mBound = false;

       private ServiceConnection mConnection = new ServiceConnection() {
           @Override
           public void onServiceConnected(ComponentName className, IBinder service) {
               mService = IMyAidlInterface.Stub.asInterface(service);
               mBound = true;
               try {
                   // 获取数据并显示
                   List<Person> persons = mService.getPersonList();
                   if (persons != null) {
                       TextView textView = findViewById(R.id.textView);
                       StringBuilder sb = new StringBuilder();
                       for (Person person : persons) {
                           sb.append(person.getName()).append(": ").append(person.getAge()).append("\n");
                       }
                       textView.setText(sb.toString());
                   }
               } catch (RemoteException e) {
                   e.printStackTrace();
               }
           }

           @Override
           public void onServiceDisconnected(ComponentName className) {
               mService = null;
               mBound = false;
           }
       };

       private final IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
           @Override
           public void binderDied() {
               Log.d("MainActivity", "服务端死亡");
               // 服务端死亡后的处理逻辑
               if (mService != null) {
                   try {
                       mService.asBinder().unlinkToDeath(this);
                   } catch (RemoteException e) {
                       e.printStackTrace();
                   }
                   mService = null;
               }
           }
       };

       @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);

           Button button = findViewById(R.id.button);
           button.setOnClickListener(new View.OnClickListener() {
               @Override
               public void onClick(View v) {
                   if (mBound) {
                       try {
                           // 添加数据
                           Person person = new Person("Kimi", 25);
                           mService.addPerson(person);
                           List<Person> persons = mService.getPersonList();
                           if (persons != null) {
                               TextView textView = findViewById(R.id.textView);
                               StringBuilder sb = new StringBuilder();
                               for (Person p : persons) {
                                   sb.append(p.getName()).append(": ").append(p.getAge()).append("\n");
                               }
                               textView.setText(sb.toString());
                           }
                       } catch (RemoteException e) {
                           e.printStackTrace();
                       }
                   }
               }
           });
       }

       @Override
       protected void onStart() {
           super.onStart();
           Intent intent = new Intent();
           intent.setClassName("vac.test.aidlservice", "vac.test.aidlservice.AidlService");
           bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
       }

       @Override
       protected void onStop() {
           super.onStop();
           if (mBound) {
               unbindService(mConnection);
               mBound = false;
           }
       }
   }

• 客户端监听服务端死亡 在客户端的MainActivity中添加对服务端死亡的监听:

   @Override
   public void onServiceConnected(ComponentName className, IBinder service) {
       mService = IMyAidlInterface.Stub.asInterface(service);
       mBound = true;
       try {
           mService.asBinder().linkToDeath(deathRecipient, 0);
       } catch (RemoteException e) {
           e.printStackTrace();
       }
       try {
           // 获取数据并显示
           List<Person> persons = mService.getPersonList();
           if (persons != null) {
               TextView textView = findViewById(R.id.textView);
               StringBuilder sb = new StringBuilder();
               for (Person person : persons) {
                   sb.append(person.getName()).append(": ").append(person.getAge()).append("\n");
               }
               textView.setText(sb.toString());
           }
       } catch (RemoteException e) {
           e.printStackTrace();
       }
   }

工作原理

• 双向通信

• 客户端通过绑定服务获取服务端的IBinder,然后通过IMyAidlInterface.Stub.asInterfaceIBinder转换为服务端的 AIDL 接口代理对象。

• 客户端可以通过代理对象调用服务端的方法,如添加数据和获取数据列表。

• 服务端实现 AIDL 接口,处理客户端的请求,并返回结果。

• 死亡监听

• 客户端通过linkToDeath方法监听服务端的死亡事件。如果服务端进程崩溃或断开连接,binderDied方法会被调用。

• 服务端也可以通过linkToDeath方法监听客户端的死亡事件。如果客户端进程崩溃或断开连接,binderDied方法会被调用。

• 在binderDied方法中,可以进行相应的清理操作,如断开与对方的连接。

通过以上实现,可以使用 AIDL 实现双向通信,并结合linkToDeath机制来处理进程崩溃或断开恢复的情况。

在 Android 中,使用 AIDL 和共享内存(尤其是匿名共享内存 Ashmem)可以实现高效的跨进程双向通信,特别适用于需要传递大量数据的场景。以下是实现这一功能的详细步骤和代码示例:

1.定义 AIDL 接口 定义一个 AIDL 接口,用于传递共享内存的文件描述符(ParcelFileDescriptor)。

// ISharedMemoryAidlInterface.aidl
package com.example.sharedmemory;

import android.os.ParcelFileDescriptor;

interface ISharedMemoryAidlInterface {
    ParcelFileDescriptor createSharedMemory(int size);
    void writeDataToSharedMemory(ParcelFileDescriptor pfd, byte[] data);
    byte[] readDataFromSharedMemory(ParcelFileDescriptor pfd);
}

2.实现服务端 服务端负责创建共享内存,并通过 AIDL 接口将共享内存的文件描述符传递给客户端。

package com.example.sharedmemory;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.util.Log;

import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class SharedMemoryService extends Service {
    private final ISharedMemoryAidlInterface.Stub binder = new ISharedMemoryAidlInterface.Stub() {
        @Override
        public ParcelFileDescriptor createSharedMemory(int size) throws RemoteException {
            try {
                // 创建匿名共享内存
                FileDescriptor fd = ashmemCreate(size);
                return ParcelFileDescriptor.dup(fd);
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }

        @Override
        public void writeDataToSharedMemory(ParcelFileDescriptor pfd, byte[] data) throws RemoteException {
            try (FileOutputStream fos = new FileOutputStream(pfd.getFileDescriptor())) {
                fos.write(data);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public byte[] readDataFromSharedMemory(ParcelFileDescriptor pfd) throws RemoteException {
            try (FileInputStream fis = new FileInputStream(pfd.getFileDescriptor())) {
                byte[] data = new byte[fis.available()];
                fis.read(data);
                return data;
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
    };

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

    private native FileDescriptor ashmemCreate(int size) throws IOException;

    static {
        System.loadLibrary("ashmem");
    }
}

3.实现客户端 客户端通过绑定服务获取共享内存的文件描述符,并进行读写操作。

package com.example.sharedmemory;

import android.app.Activity;
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.util.Log;

import java.io.IOException;

public class MainActivity extends Activity {
    private ISharedMemoryAidlInterface mService;
    private boolean mBound = false;

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            mService = ISharedMemoryAidlInterface.Stub.asInterface(service);
            mBound = true;
            try {
                // 创建共享内存
                ParcelFileDescriptor pfd = mService.createSharedMemory(1024);
                if (pfd != null) {
                    // 写入数据
                    byte[] data = "Hello from client".getBytes();
                    mService.writeDataToSharedMemory(pfd, data);

                    // 读取数据
                    byte[] readData = mService.readDataFromSharedMemory(pfd);
                    Log.d("MainActivity", "Read from shared memory: " + new String(readData));
                }
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName className) {
            mService = null;
            mBound = false;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.example.sharedmemory", "com.example.sharedmemory.SharedMemoryService"));
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }
}

4.使用 Ashmem 创建共享内存 在服务端中,使用 JNI 调用 Ashmem 创建共享内存。

// ashmem.c
#include <jni.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

JNIEXPORT jobject JNICALL
Java_com_example_sharedmemory_SharedMemoryService_ashmemCreate(JNIEnv *env, jobject thiz, jint size) {
    int fd = ashmem_create_region("shared_memory", size);
    if (fd < 0) {
        return NULL;
    }
    return (*env)->NewDirectByteBuffer(env, mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0), size);
}

5.同步机制 由于共享内存本身不提供同步机制,需要额外使用同步机制(如信号量)来确保数据的一致性。

总结 通过 AIDL 和匿名共享内存(Ashmem),可以实现高效的跨进程双向通信,特别适用于需要传递大量数据的场景。服务端创建共享内存并通过 AIDL 接口将文件描述符传递给客户端,客户端通过文件描述符进行读写操作。