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 followspackage 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