[Android] Binder (1) Introduction of Binder and examples of using Binder in AIDL

Binder introduction

Binder in Android is an inter-process communication mechanism that allows different processes to call methods and transfer data to each other. Binder is mainly used to implement communication between system services and applications, and to implement IPC (Inter-Process Communication, inter-process communication).

The core of Binder is the Binder driver, which is responsible for managing the communication between different processes. Each process can create its own Binder object as a service provider, or obtain Binder objects provided by other processes as a client. These Binder objects must be driven by Binder for cross-process communication.

From 机制the perspective: Binder is an inter-process communication mechanism
From 驱动the perspective: Binder is a virtual physical device driver
From 应用层the perspective: Binder is a Java class that can initiate communication

In Android development, we can define our own Binder interface through AIDL (Android Interface Definition Language), and implement the corresponding service provider and client. The code generated by AIDL can be used for IPC communication between different processes.


Comparison of Binder and other process communication schemes

Comparison between Binder and traditional IPC
Binder Shared memory Socket
performance need to copy once no need to copy need to copy twice
features Based on C/S architecture, high usability Complicated controls and poor usability Based on the C/S architecture, as a general-purpose interface, its transmission efficiency is low and the overhead is large
safety Assign a UID to each APP, supporting both real-name and anonymous Rely on upper-layer protocol access, the access point is open and unsafe

Binder mechanism composition

Binder (IInterface interface) This class defines the remote service interface for communication between the client and the server
IBinder interface This class is the implementation class of Binder, which provides lightweight inter-process communication capabilities
ServiceManager This class provides a mechanism for registering and finding Binder services
Binder driver The driver is the core of Binder inter-process communication and is used to manage Binder connections, data transmission, threads and other operations

The Binder mechanism provides an efficient and flexible inter-process communication method for Android development, making it easier for applications to share data across processes and call remote services.


The relationship between AIDL and Binder

AIDL (Android Interface Definition Language, Android Interface Definition Language) is a mechanism used to implement inter-process communication (IPC) in the Android system. AIDL can help developers implement remote method calls between different applications or between different processes, so as to realize cross-process data sharing and interaction.

Binder is the core driver for implementing IPC in the Android system, and it can provide the underlying support for the interfaces defined by AIDL. Binder driver completes the inter-process communication function based on AIDL by managing inter-process connection, data transmission and other operations.

The relationship between AIDL and Binder can be understood as: AIDL provides a language for describing inter-process communication interfaces, while Binder is an internal framework for implementing AIDL interface calls. In an Android application, generally, the interfaces for cross-process access are defined in the AIDL file, and these interfaces are implemented through Binder, so as to realize the communication between applications.


Example of using Binder for inter-process communication

First, we need to create two terminals, namely 服务端and客户端

Server

Create a project named and MyBinderService
insert image description here
then create the AIDL file

Note: aidlThe folder needs to be created by itself, and the folder is mainunder the folder, which is javaat the same level as the folder

insert image description here

When we aidlcreated the aidl file in the folder, we encountered this error:
insert image description here

This prompt means that you need to set buildFeatures.aidl to true in the build.gradle file to use AIDL technology
insert image description here

 buildFeatures {
    
    
    aidl = true
 }

aidlAt this point we see that the folder above has also changed color.

In the server application, we need to define an AIDL interface to provide the client with a method of data acquisition.
insert image description here
Then we need to implement the interface method and register it in the system, here we use a Service to achieve:
insert image description here
insert image description here
insert image description here

full code

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;
    }
}

Main Page:
insert image description here
Full Code:

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);
            }
        });
    }
}

Notice:

Need to AndroidManifest.xmladd this permission in the file:

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

Otherwise, an error will be reported:

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

MyServiceAt the same time, register the perfect file in this file

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

After configuring at this time, remember to build the project, so that Android Studio will automatically generate AIDL code
insert image description here
Generated code:
insert image description here

client

The steps and methods that need to be configured on the client side are the same as those on the server side, and will not be described here.

Notice:

Do not rewrite the AIDL file on the client side, but copy it from the server side to ensure that both sides are the same.

Server

insert image description here

client

insert image description here

The files on both ends have the same package name and the code inside, so it is best to copy them directly.

The client is named MyBinder, and there is only one file

insert image description here

MainActivity code

insert image description here
insert image description here
Full code:

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;
        }
    };
}
test

First, you need to start 服务端
insert image description here
and then start again 客户端
insert image description here
. After connecting to the server, the server will display
insert image description here
and then call the method on the client getCurrentTimestampto obtain data:
insert image description here
look at the server at this point. So
insert image description here
far, a simple AIDL using Binder cross-process communication is completed.

Guess you like

Origin blog.csdn.net/qq_43358469/article/details/130981992