VirgilG72's Blog.

Android Service AIDL Demo

字数统计: 1.4k阅读时长: 6 min
2019/01/23 Share

Android Service AIDL Demo Run

接上面的CVTE电话面试,这是Android部分问题之一:activity调用service&&进程间的通信

Activity调用Service分为两种方式,一种是本地服务,一种是远程服务。本地服务的启动方式有两种,见Android官方文档介绍如下:

本例中使用的是绑定方式。

而我们往往采用的是远程服务——AIDL(Android Interface Definition Language),Android接口自定义语言,它可以用于让某个Service与多个应用程序组件之间进行跨进程通信,从而可以实现多个应用程序共享同一个Service的功能。实际上实现跨进程之间通信的有很多,
比如广播,Content Provider,但是AIDL的优势在于速度快(系统底层直接是共享内存),性能稳,效率高,一般进程间通信就用它。

既然是跨进程,那必须的有两个应用,一个是service端,一个是client端,然后实现客户端从服务端获取数据。那么我们创建一个服务端,项目结构如图所示:

我们首先右键创建一个aidl文件夹,然后在该文件夹下右键新建一个aidl文件,如图:

代码如下:

1
2
3
4
5
6
7
8
9
// IService.aidl
package com.example.a61979.alipayservice;

// Declare any non-default types here with import statements

interface IService {
int callSafepay(String username, String password, float money, long timestamp);

}

接着写AliService的代码,注意IService.Stub是bulid完后生成的aidl.java文件。MyBinder继承IService.Stub接口后,实现callsafepay方法,然后调用safepay方法,这是仿支付宝支付接口的方法。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package com.example.a61979.alipayservice;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

public class AliService extends Service {
public AliService() {
}

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

@Override
public void onCreate() {
System.out.println("支付宝服务被创建了");
super.onCreate();
}

@Override
public void onDestroy() {
System.out.println("支付宝服务被销毁了");
super.onDestroy();
}

private class MyBinder extends IService.Stub {
@Override
public int callSafepay(String username, String password, float money, long timestamp) throws RemoteException {
return safepay(username, password,money, timestamp);
}


}

/**
* 安全支付的服务方法
* @param username
* 用户名
* @param password
* 密码
* @param money
* 钱
* @param timestamp
* 时间戳
* @return
*/
public int safepay(String username, String password, float money, long timestamp){
System.out.println("加密的username");
System.out.println("加密的password");
System.out.println("提交数据到支付宝的服务器");
if(money>5000){
return 505;
}
if("zhangsan".equals(username)&&"123".equals(password))
{
return 200;

}
else
{
return 300;
}
}
}

然后,开始写客户端代码,新建一个Android Studio项目,以实现两个进程间的通信。客户端代码结构如下:

然后,我们回到Service端,把整个aidl文件夹的内容原封不动的复制到AlipayClient下,接着,我们开始写MainActivity的内容。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.example.a61979.alipayclient;

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.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import com.example.a61979.alipayservice.IService;

public class MainActivity extends AppCompatActivity {

private Button bt_connect;
private Button bt_disconnect;
private ServiceConnection conn=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
try {
Mybinder = IService.Stub.asInterface(iBinder);
Mybinder.callSafepay("VirgilG72","123456",300,123456789);
} catch (RemoteException e) {
e.printStackTrace();
}
}

@Override
public void onServiceDisconnected(ComponentName componentName) {
Mybinder=null;
Log.e("1","无法连接服务");
}
};
private IService Mybinder;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt_connect = (Button) findViewById(R.id.button);
bt_disconnect = (Button) findViewById(R.id.button2);
bt_connect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setAction("com.example.a61979.alipayservice.AliService");
intent.setPackage("com.example.a61979.alipayservice");

bindService(intent,conn,BIND_AUTO_CREATE);
}
});
bt_disconnect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
unbindService(conn);
Log.e("1","成功解绑服务");
}
});
}



}

这段代码关键点在这三点

  1. Mybinder = IService.Stub.asInterface(iBinder); //asInterface是根据调用是否是同一个进程而返回不同的实例对象
  2. intent.setAction(“com.example.a61979.alipayservice.AliService”);
    intent.setPackage(“com.example.a61979.alipayservice”);这两行代码从何而来?这就需要我们回到服务端的AndroidManifest文件下去设置相应的action和包名,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.a61979.alipayservice">

    <application
    android:name=".AlipayApplication"
    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">
    <intent-filter>
    <action android:name="android.intent.action.MAIN"/>

    <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
    </activity>

    <service
    android:name=".AliService"
    >
    <intent-filter>
    <action android:name="com.example.a61979.alipayservice.AliService"></action>
    </intent-filter>

    </service>
    </application>

    </manifest>
  3. bindService(intent,conn,BIND_AUTO_CREATE);
    unbindService(conn);
    这两行代码,我设置了两个点击事件去触发,activity_main如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.a61979.alipayclient.MainActivity">

<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="绑定服务"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.528"
app:layout_constraintStart_toEndOf="@+id/button2"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.125"/>

<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="88dp"
android:layout_marginTop="64dp"
android:text="解绑服务"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>

</android.support.constraint.ConstraintLayout>

最后,附上成功运行的图片:

ui:

点击“绑定服务”后,日志消息如下:

点击“解绑服务”后,日志消息如下:

附上Github源代码:
客户端:https://github.com/VirgilG72/AlipayClient
服务端:https://github.com/VirgilG72/AlipayService

CATALOG
  1. 1. Android Service AIDL Demo Run