[Android] Binder (1) Introducción a Binder y ejemplos de uso de Binder en AIDL

Introducción a la carpeta

Binder en Android es un mecanismo de comunicación entre procesos que permite que diferentes procesos llamen a métodos y transfieran datos entre sí. Binder se utiliza principalmente para implementar la comunicación entre servicios y aplicaciones del sistema, y ​​​​para implementar IPC (comunicación entre procesos, comunicación entre procesos).

El núcleo de Binder es el controlador Binder, que es responsable de gestionar la comunicación entre diferentes procesos. Cada proceso puede crear su propio objeto Binder como proveedor de servicios y también puede obtener objetos Binder proporcionados por otros procesos como clientes. Estos objetos de Binder deben ser controlados por Binder para la comunicación entre procesos.

Desde 机制la perspectiva: Binder es un mecanismo de comunicación entre procesos
Desde 驱动la perspectiva: Binder es un controlador de dispositivo físico virtual
Desde 应用层la perspectiva: Binder es una clase Java que puede iniciar la comunicación

En el desarrollo de Android, podemos definir nuestra propia interfaz Binder a través de AIDL (lenguaje de definición de interfaz de Android) e implementar el proveedor de servicios y el cliente correspondientes. El código generado por AIDL se puede utilizar para la comunicación IPC entre diferentes procesos.


Comparación de Binder y otros esquemas de comunicación de procesos

Comparación entre Binder y IPC tradicional
Aglutinante Memoria compartida Enchufe
actuación necesito copiar una vez no es necesario copiar necesito copiar dos veces
características Basado en arquitectura C/S, alta usabilidad Controles complicados y mala usabilidad. Basado en la arquitectura C/S, como interfaz de uso general, su eficiencia de transmisión es baja y la sobrecarga es grande.
seguridad Asigne un UID a cada aplicación, admitiendo tanto nombre real como anónimo Confíe en el acceso al protocolo de capa superior, el punto de acceso es abierto e inseguro

Composición del mecanismo aglutinante.

Carpeta (interfaz IInterface) Esta clase define la interfaz de servicio remoto para la comunicación entre el cliente y el servidor.
Interfaz IBinder Esta clase es la clase de implementación de Binder, que proporciona capacidades livianas de comunicación entre procesos.
Supervisor Esta clase proporciona un mecanismo para registrar y encontrar servicios de Binder.
conductor de carpeta El controlador es el núcleo de la comunicación entre procesos de Binder y se utiliza para administrar conexiones de Binder, transmisión de datos, subprocesos y otras operaciones.

El mecanismo Binder proporciona un método de comunicación entre procesos eficiente y flexible para el desarrollo de Android, lo que facilita que las aplicaciones compartan datos entre procesos y llamen a servicios remotos.


La relación entre AIDL y Binder

AIDL (lenguaje de definición de interfaz de Android, lenguaje de definición de interfaz de Android) es un mecanismo utilizado para implementar la comunicación entre procesos (IPC) en el sistema Android. AIDL puede ayudar a los desarrolladores a implementar llamadas a métodos remotos entre diferentes aplicaciones o entre diferentes procesos, para lograr el intercambio y la interacción de datos entre procesos.

Binder es el controlador principal para implementar IPC en el sistema Android y puede proporcionar soporte subyacente para las interfaces definidas por AIDL. El controlador Binder completa la función de comunicación entre procesos basada en AIDL al administrar la conexión entre procesos, la transmisión de datos y otras operaciones.

La relación entre AIDL y Binder puede entenderse como: AIDL proporciona un lenguaje para describir interfaces de comunicación entre procesos, mientras que Binder es un marco interno para implementar llamadas de interfaz AIDL. En una aplicación de Android, generalmente, las interfaces para el acceso entre procesos se definen en el archivo AIDL y estas interfaces se implementan a través de Binder para realizar la comunicación entre aplicaciones.


Ejemplo de uso de Binder para comunicación entre procesos

Primero, necesitamos crear dos terminales, a saber 服务端y客户端

Servidor

Cree un proyecto llamado y MyBinderService
inserte la descripción de la imagen aquí
luego cree el archivo AIDL

Nota: aidlLa carpeta debe crearse sola y la carpeta está maindebajo de la carpeta, que está javaal mismo nivel que la carpeta.

inserte la descripción de la imagen aquí

Cuando aidlcreamos el archivo Aidl en la carpeta, encontramos este error:
inserte la descripción de la imagen aquí

Este mensaje significa que debe configurar buildFeatures.aidl en verdadero en el archivo build.gradle para usar la tecnología AIDL.
inserte la descripción de la imagen aquí

 buildFeatures {
    
    
    aidl = true
 }

aidlEn este punto vemos que la carpeta de arriba también ha cambiado de color.

En la aplicación del servidor, necesitamos definir una interfaz AIDL para proporcionar al cliente un método de adquisición de datos.
inserte la descripción de la imagen aquí
Luego necesitamos implementar el método de interfaz y registrarlo en el sistema. Aquí usamos un Servicio para lograr:
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

código completo

public class MyService extends Service {
    
    

    private static final int NOTIFICATION_ID = 1001; // 前台通知 ID

    private final IBinder mBinder = new MyBinder();

    @Override
    public IBinder onBind(Intent intent) {
    
    
        Log.e("Binder响应:", "已经绑定到Binder上面了");
        return mBinder;
    }

    static class MyBinder extends IMyService.Stub {
    
    
        @Override
        public long getCurrentTimestamp() throws RemoteException {
    
    
            long time = System.currentTimeMillis();
            Log.e("Binder数据:", "服务端的时间戳:" + time);
            return time;
        }
    }

    @Override
    public void onCreate() {
    
    
        super.onCreate();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    
    
            NotificationManager manager = getSystemService(NotificationManager.class);
            NotificationChannel channel = new NotificationChannel(
                    "channel_id",
                    "前台通知渠道名称",
                    NotificationManager.IMPORTANCE_DEFAULT
            );
            manager.createNotificationChannel(channel);
        }

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "channel_id")
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setContentTitle("Binder服务端")
                .setContentText("测试Binder的前台Service");

        startForeground(NOTIFICATION_ID, builder.build());
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    
    
        new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                Log.e("Binder的服务", "在Service做耗时任务的话,请使用子线程,因为Service是在主线程运行的");
                Log.e("Binder的服务", "此时的线程:" + Thread.currentThread().getName());
            }
        }).start();
        return START_STICKY;
    }
}

Página principal:
inserte la descripción de la imagen aquí
Código completo:

public class MainActivity extends AppCompatActivity {
    
    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView tvStartService = findViewById(R.id.tv_startService);
        TextView tvStopService = findViewById(R.id.tv_stopService);
        tvStartService.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View view) {
    
    
                Intent intent = new Intent(MainActivity.this, MyService.class);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    
    
                    startForegroundService(intent);
                } else {
    
    
                    startService(intent);
                }
            }
        });
        tvStopService.setOnClickListener(new View.OnClickListener() {
    
    

            @Override
            public void onClick(View view) {
    
    
                Intent intent = new Intent(MainActivity.this, MyService.class);
                stopService(intent);
            }
        });
    }
}

Aviso:

Es necesario AndroidManifest.xmlagregar este permiso en el archivo:

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

De lo contrario, se informará un error:

Permission Denial: startForeground from pid=16363, uid=10134 requires android.permission.FOREGROUND_SERVICE

MyServiceAl mismo tiempo, registre el archivo perfecto en este archivo.

<service
     android:name=".MyService"
     android:enabled="true"
     android:exported="true">
     <intent-filter>
           <action android:name="com.shsany.mybinderservice"/>
     </intent-filter>
</service>

Después de la configuración en este momento, recuerde compilar el proyecto, para que Android Studio genere automáticamente el
inserte la descripción de la imagen aquí
código AIDL Código generado:
inserte la descripción de la imagen aquí

cliente

Los pasos y métodos que deben configurarse en el lado del cliente son los mismos que en el lado del servidor y no se describirán aquí.

Aviso:

No reescriba el archivo AIDL en el lado del cliente, cópielo desde el lado del servidor para asegurarse de que ambos lados sean iguales.

Servidor

inserte la descripción de la imagen aquí

cliente

inserte la descripción de la imagen aquí

Los archivos en ambos extremos tienen el mismo nombre de paquete y el mismo código dentro, por lo que es mejor copiarlos directamente.

El cliente tiene nombre MyBindery solo hay un archivo.

inserte la descripción de la imagen aquí

Código de actividad principal

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
Código completo:

public class MainActivity extends AppCompatActivity {
    
    
    private IMyService mMyService;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView tvGetData = findViewById(R.id.tv_getBinderData);

        Intent intent = new Intent();
        intent.setAction("com.shsany.mybinderservice");
        intent.setPackage("com.shsany.mybinderservice");
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

        tvGetData.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View view) {
    
    
                try {
    
    
                    // 在使用服务端方法时,先判断服务是否可用
                    if (mMyService != null) {
    
    
                        long currentTime = mMyService.getCurrentTimestamp();
                        Log.e("Binder数据:", "从服务端接收到的时间戳:" + currentTime);
                    } else {
    
    
                        Log.e("Binder数据:", "无法连接到服务端");
                    }
                } catch (Exception e) {
    
    
                    Log.e("Binder错误:", e.getMessage());
                }
            }
        });
    }

    private final ServiceConnection mConnection = new ServiceConnection() {
    
    
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
    
    
            //远程Service绑定
            Log.e("Binder数据:", "已经连接到服务端");
            mMyService = IMyService.Stub.asInterface(iBinder);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
    
    
            //Service被意外销毁
            Log.e("Binder数据:", "服务端被意外销毁");
            mMyService = null;
        }
    };
}
prueba

Primero debe comenzar 服务端
inserte la descripción de la imagen aquí
y luego comenzar nuevamente 客户端
inserte la descripción de la imagen aquí
. Después de conectarse al servidor, el servidor mostrará
inserte la descripción de la imagen aquí
y luego llamará al método en el cliente getCurrentTimestamppara obtener datos:
inserte la descripción de la imagen aquí
mire el servidor en este punto. Hasta
inserte la descripción de la imagen aquí
ahora, un AIDL simple usando Binder cross -Se completa la comunicación del proceso.

Supongo que te gusta

Origin blog.csdn.net/qq_43358469/article/details/130981992
Recomendado
Clasificación