The most detailed steps in history to create Android AIDL remote services

Project introduction

  • Creation time: October 4, 2019 16:30:09
  • Functions: Android remote service production and test run, AIDL service.
  • Introduction to development environment: Android API = 29, Android 10, and Android Studio

Make complaints

More than N articles were searched online, either for a long time or for different operations of IDE development. In this paper, the most detailed steps to achieve the simplest AIDL remote service production and invocation.

Implementation steps

  • Summary

    An empty project was created in Android Studio (actually not used later, but in order to match the source code or to say below), the module rsserver was created. Because Android Studio and IDEA a virtuous row, it can only be called the module - the English name is module. This module is used to make a service that can be invoked in the activity of this module. It can be used by other app s or modules. Then a client module rsclient is created, where rs means remote service. Then the final structure is as follows:

    The next step is to make the service in the server module and test it before making the client module. Let's start.

  • Make AIDL interface file and create an AIDL file through right-click menu on the root node of the server module

    Name it IProcessInfo, where as long as you define a method without implementation, the whole code is as follows (after creating, there will be a default method, delete it, and then add a method of our own)

    // IProcessInfo.aidl
    package com.ccsoft.rsserver;
    
    // Declare any non-default types here with import statements
    
    interface IProcessInfo {
        int getProcessId();
    }

    After saving, AS will automatically create the interface file with the same name, which will be used to create the service later.

  • Method of Implementing Definitions in AIDL Files
    Create a package service under the project package com.ccsoft.rsserver and then create a service IProcessInfoImpl under it, which is inherited from IProcessInfo.Stub. The code is as follows

    package com.ccsoft.rsserver.service;
    
    import android.os.RemoteException;
    
    import com.ccsoft.rsserver.IProcessInfo;
    
    public class IProcessInfoImpl extends IProcessInfo.Stub {
        @Override
        public int getProcessId() throws RemoteException {
            return android.os.Process.myPid();
        }
    }
    

    Calling this method prints the process ID, resulting in the following structure

  • Create a service to return an instance of the class that implements the interface. The code is as follows:

    package com.ccsoft.rsserver.service;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.util.Log;
    
    import androidx.annotation.Nullable;
    
    public class MyRemoteService extends Service {
        private static final String TAG = "chanchaw";
        IProcessInfoImpl mProcessInfo = new IProcessInfoImpl();
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            Log.e(TAG, "MyRemoteService thread id = " + Thread.currentThread().getId());
            return mProcessInfo;
        }
    }

    The final implementation structure is as follows

  • Next, an Activity is created for the server to test whether the service is available. First, the layout file activity_main is created. The whole code is as follows:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Binding local services"
        android:onClick="bindLocalService" />
    </LinearLayout>

    The final structure is shown below.

  • Create an Activity to display the layout and test the service, named MainActivity, with the full code as follows:

    package com.ccsoft.rsserver;
    
    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 androidx.annotation.Nullable;
    
    import com.ccsoft.rsserver.service.MyRemoteService;
    
    public class MainActivity extends Activity {
        // Used to filter and quickly find debugging information when printing logs
        private static final String TAG = "chanchaw";
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // Associated with res/layout/activity_main.xml, the controls defined therein are displayed
            setContentView(R.layout.activity_main);
        }
    
        // Create an object instance of ServiceConnection type, which will be used later when binding services
        ServiceConnection myServiceConnection = new ServiceConnection() {
    
            /**
             * This method is called when the service binding is successful
             * @param name
       */
      @Override
      public void onServiceConnected(ComponentName name, IBinder service) {

          Log.i(TAG, "MyRemoteService onServiceConnected");
          // Retrieve data through aidl
          IProcessInfo processInfo = IProcessInfo.Stub.asInterface(service);
          try {
              Log.i(TAG, "MyRemoteService process id = " + processInfo.getProcessId());
          } catch (RemoteException e) {
              e.printStackTrace();
          }
      }

      @Override
      public void onServiceDisconnected(ComponentName name) {
          Log.i(TAG, "MyRemoteService onServiceDisconnected");
      }
  };

  public void bindLocalService(View v){
      Intent intent = new Intent(this, MyRemoteService.class);
      bindService(intent, myServiceConnection, Context.BIND_AUTO_CREATE);

  }

  @Override
  protected void onDestroy() {
      super.onDestroy();
      unbindService(myServiceConnection);
  }

}

The final structure is as follows
![](https://user-images.githubusercontent.com/29369287/66197772-ac01e400-e6cd-11e9-84c5-815d5764feec.png)

- Register `Activity` and services in the module manifest file `Android Manifest.xml'. The code is as follows:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

  package="com.ccsoft.rsserver">

  <application
      android:allowBackup="true"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:roundIcon="@mipmap/ic_launcher_round"
      android:supportsRtl="true"
      android:theme="@style/AppTheme" >

      <activity android:name=".MainActivity" android:label="MainActivity">
          <intent-filter>
              <action android:name="android.intent.action.MAIN" />
              <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
      </activity>

      <service android:name=".service.MyRemoteService" android:process=":remote">
          <intent-filter>
              <action android:name="com.jxx.server.service.bind" />
              <category android:name="android.intent.category.DEFAULT" />
          </intent-filter>
      </service>

  </application>

</manifest>

- Testing the service on the server side, 70% of the work will be completed if it is successful. The effect is as follows.
![](https://user-images.githubusercontent.com/29369287/66197771-ab694d80-e6cd-11e9-98f6-e614ba7ec6b6.png)
- Create the client module, and then copy `AIDL'in the server module with the files below to the client module, as shown below.
![](https://user-images.githubusercontent.com/29369287/66197770-ab694d80-e6cd-11e9-94a8-a1d001c2ff1c.png)
- After copying, remember to use `ctrl + F9 ` to build the client module, so that the interface file can be generated, as shown below.
![](https://user-images.githubusercontent.com/29369287/66197768-ab694d80-e6cd-11e9-9880-fa361007d38e.png)

- The layout file of `activity''is created in the client module. The whole code is as follows:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

  android:orientation="vertical" android:layout_width="match_parent"
  android:layout_height="match_parent">

  <TextView
      android:id="@+id/rsclient_textview"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="rsclient_textview" />

  <Button
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Binding remote services"
      android:onClick="bindRemoteService" />

</LinearLayout>

The structure formed is as follows
![](https://user-images.githubusercontent.com/29369287/66197766-aad0b700-e6cd-11e9-85aa-70bec1af872b.png)

- Create `Activity', all code as follows

package com.ccsoft.rsclient;

import android.app.Activity;
import android.content.ComponentName;
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.TextView;

import androidx.annotation.Nullable;

import com.ccsoft.rsserver.IProcessInfo;

public class MainActivity extends Activity {

  private static final String TAG = "chanchaw";

  TextView text = null;
  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      text = findViewById(R.id.rsclient_textview);
  }

  // Binding remote services
  public void bindRemoteService(View v){
      Intent intent = new Intent();
      intent.setAction("com.jxx.server.service.bind");//action of Service
      intent.setPackage("com.ccsoft.rsserver");//Package Name of App A
      bindService(intent, mServerServiceConnection, BIND_AUTO_CREATE);
  }


  ServiceConnection mServerServiceConnection = new ServiceConnection() {
      @Override
      public void onServiceConnected(ComponentName name, IBinder service) {

          Log.i(TAG, "MyRemoteService onServiceConnected");
          // Retrieve data through aidl
          IProcessInfo processInfo = IProcessInfo.Stub.asInterface(service);
          try {
              Log.i(TAG, "MyRemoteService process id = " + processInfo.getProcessId());
              text.setText("Binding success!");
          } catch (RemoteException e) {
              e.printStackTrace();
          }
      }

      @Override
      public void onServiceDisconnected(ComponentName name) {
          Log.i(TAG, "MyRemoteService onServiceDisconnected");
      }
  };

}

The final structure is as follows
![](https://user-images.githubusercontent.com/29369287/66197765-aad0b700-e6cd-11e9-938e-e22917399fab.png)

- Register `Activity` in the manifest file. The code is as follows

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

  package="com.ccsoft.rsclient">

  <application
      android:allowBackup="true"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:roundIcon="@mipmap/ic_launcher_round"
      android:supportsRtl="true"
      android:theme="@style/AppTheme" >

      <activity android:name=".MainActivity" android:label="MainActivity">
          <intent-filter>
              <action android:name="android.intent.action.MAIN" />
              <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
      </activity>
  </application>

</manifest>

There is no need to register remote services, because they are called remotely.

- Test and invoke remote service in client module
![](https://user-images.githubusercontent.com/29369287/66197763-aad0b700-e6cd-11e9-9880-4a4d1a5c2c61.png)

#### Concluding remarks

Keywords: Android xml encoding

Added by bytes on Wed, 09 Oct 2019 12:29:32 +0300