AIDl实现步骤及客户端与服务端的案例

AIDl

AIDL简介

AIDL(Android 接口定义语言),可以使用它定义客户端与服务端进程间通信(IPC)的编程接口。在Android系统中,每个进程都运行在一块独立的内存中,在其中完成自己的各项活动,与其他进程都分隔开来。可是有时候我们又有应用间进行互动的需求,比较传递数据或者任务委托等,AIDL就是为了满足这种需求而诞生的。通过AIDL,可以在一个进程中获取另一个进程的数据和调用其暴露出来的方法,从而满足进程间通信的需求。

AIDL是用于定义服务端和客户端通信接口的一种描述语言,可以拿来生产IPC代码,从某种意义上说AIDL其实就是一个模板,因为在使用过程中,实际起作用的并不是AIDL文件,而是据此生产的一个Interface的实例代码,AIDL其实是为了避免我们重复写代码而出现的一个模板。

**注意:**只有在需要不同应用的客户端通过 IPC 方式访问服务,并且希望在服务中进行多线程处理时,您才有必要使用 AIDL。如果您无需跨不同应用执行并发 IPC,则应通过实现 Binder来创建接口;或者,如果您想执行 IPC,但需要处理多线程,请使用 Messenger 来实现接口。无论如何,在实现 AIDL 之前,请您务必理解绑定服务。

使用流程

1.创建.aidl文件

在 AIDL 中可以通过可带参数以及返回值的一个或多个方法来声明接口,参数和返回值可以是任意类型,AIDL 中支持的数据类型如下:

java 的 8 种数据类型:byte、short、int、long、float、double、boolean ,char

除此之外支持 String、charSequence、List、Map

自定义数据类型 List 或 Map

首先,在工程的 src 目录下创建 .aidl 文件,具体如下图所示:

在这里插入图片描述

在这里插入图片描述

2.打开IPersonAidlInterface.aidl,在 .aidl 文件中添加具体的业务方法,文件内容如下

// IMyAidlInterface.aidl
package com.hoop.myapp1;

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

interface IMyAidlInterface {
    //具体的业务
    void setAccount(String account);
    void setPassword(String password);
    String getInfo();

    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
}

3.然后,重新 rebuild project , Android SDK 工具会在相应的目录生成对应的与 .aidl 文件同名的 .java

rebuild project

在这里插入图片描述

在这里插入图片描述

4.那么这个业务要体现在什么地方呢,从上面可知 Stub 是一个抽象类,那么它所提供的具体业务必

然需要一个具体的实现类来完成,下面实现这个具体的业务类,具体如下:

 public class IPaidl extends IMyAidlInterface.Stub{

        private String account;
        private String password;

        @Override
        public void setAccount(String account) throws RemoteException {
            this.account=account;
        }

        @Override
        public void setPassword(String password) throws RemoteException {
            this.password=password;
        }

        @Override
        public String getInfo() throws RemoteException {
            return "password"+password+"password"+password
+        }

        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }
    }

5.向客户端公开接口

创建一个 Service 以便对外提供具体的业务,具体如下:

 public MyService() {

    }
    @Override
    public IBinder onBind(Intent intent) {
        //返回的是new 上面的实现类
        return new IPaidl();
    }

当外部调用 bindService() 方法绑定服务时,就会调用 onBind() 方法返回 IBinder 对象,这个 IBinder对象也是具体的业务对象,如这里的 onBind() 方法返回的也是具体的业务对象,两者是统一的。此外,创建的 Service 要在 AndroidManifest.xml 文件中声明,具体如下:

<service 
	android:name=".PersonService" 
	android:enabled="true" 
	android:exported="true" 
	android:process=":remote">
</service>

其中使用 process 关键字表示为该服务开启一个独立的进程,remote 可任意,表示进程名称,":"将会

在主进程(进程名为包名)添加新名称作为新进程的名称,如 com.hopu.study 将会变成

com.hopu.study:remote。如果是在两个app上 android:process=":remote可省略

4.客户端远程调用

通过上面几步完成了服务的搭建,并将服务运行在独立进程中,下面主要就是客户端的具体调用

public class MainActivity extends AppCompatActivity {
    private Button btn_start_service, btn_stop_service, btn_call_remote; 
    private static final String TAG = "MainActivity";
    private IPersonAidlInterface iPersonAidlInterface;
    @Override 
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_start_service = findViewById(R.id.btn_start_service);
        btn_stop_service = findViewById(R.id.btn_stop_service);
        btn_call_remote = findViewById(R.id.btn_call_remote);
        btn_start_service.setOnClickListener(new View.OnClickListener() { 					@Override 
            public void onClick(View v) {
				 bindServiceClick(v);
            }
            });
        btn_stop_service.setOnClickListener(new View.OnClickListener() {
            @Override 、
                public void onClick(View v) {
                    callRemoteClick(v);
            }
       }) ;
   }
    public void bindService Cick(View view) {
        Log . i (TAG , "绑定服务 . . . ") ;
        Intent intent = new Intent (this , PersonSe rvice . class) ;
        // 绑定服务时自动创建服务
 
        bindService (intent , conn , Context . BIND_AUTO_CREATE) ;
   }
    public void unbindSe rviceCl i ck(View view) {
        Log . i (TAG , "解绑服务 . . . ") ;
        unbindService (conn) ;
   }
    public void call RemoteClick(View view) {
        Log . i (TAG , "远程调用具体服务 . . . ") ;
        try {
            iPersonAidl Interface . setName ("Tom") ;
            iPersonAidl Interface . setAge (10) ;
            String info = iPersonAidl Interface . getInfo () ;
            System . out . println ("这是远程调用的服务信息: "+info) ;
       } catch (RemoteExcepti on e) {
            e . printStackTrace () ;
       }
   }
    private Servi ceConnection conn = new Service Connection () {
        @Override
 
        public void onService Connected (ComponentName name , IBinde rservice) {
            // 根据实际情况返回 IBinder 的本地对象或其代理对象
 
            iPersonAidl Interface = 
 
IPersonAidl Interface . Stub . asInterface (service) ;
            System . out . println ("具体的业务对象: "+iPersonAi dlInterface) ;
       }
        @Override
 
        public void onService Disconnected (ComponentName name) {
            // Service 意外中断时调用

案例

App1(服务端)

IMyAidllnteace.aidl
// IMyAidlInterface.aidl
package com.hoop.myapp1;

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

interface IMyAidlInterface {

    void setAccount(String account);
    void setPassword(String password);
    String getInfo();

    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
}
MainActivity
package com.hoop.myapp1;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


    }
}
MyService
package com.hoop.myapp1;

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

public class MyService extends Service {
    //无参构建方法
    public MyService() {

    }
    @Override
    public IBinder onBind(Intent intent) {
        return new IPaidl();
    }
    public class IPaidl extends IMyAidlInterface.Stub{

        private String account;
        private String password;

        @Override
        public void setAccount(String account) throws RemoteException {
            this.account=account;
        }

        @Override
        public void setPassword(String password) throws RemoteException {
            this.password=password;
        }

        @Override
        public String getInfo() throws RemoteException {
            //使用数组模拟数组的账号密码
            String[] accounts={"123","456"};
            String[] passwords={"123","456"};
            //对账号密码进行判断
            for (int i = 0; i < accounts.length; i++) {
                if (account.equals(accounts[i])){
                    if (password.equals(passwords[i])){
                        //进行跳转
                        Intent intent = new Intent();
                        intent.setClass(MyService.this,MainActivity.class);
                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        startActivity(intent);
                        return "登录成功";
                    }else {
                        return "登录失败";
                    }
                }
            }
            return "没有找到账号";
        }

        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }
    }
}

App2(服务端)

需要点对点的将服务端的 IMyAidllnteace.aidl 文件复制到App2(服务端)文件下 同时还要在文件清单上添加 下面这行代码

<queries>
    <package android:name="com.hoop.myapp1"/>  //com.hoop.myapp1表示服务端的包名
</queries>

MainActivity

package com.hoop.myapp2;

import androidx.appcompat.app.AppCompatActivity;

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.Button;
import android.widget.Toast;

import com.google.android.material.textfield.TextInputEditText;
import com.hoop.myapp1.IMyAidlInterface;

public class MainActivity extends AppCompatActivity {


    private TextInputEditText ti_zh,ti_mm;
    private Button button;
    private IMyAidlInterface iMyAidlInterface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ti_zh=findViewById(R.id.ti_zh);
        ti_mm=findViewById(R.id.ti_mm);
        button=findViewById(R.id.textButton);

        //绑定
        Log.i("客户端","绑定线程...");
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.hoop.myapp1","com.hoop.myapp1.MyService"));
        bindService(intent,serviceConnection,BIND_AUTO_CREATE);

        //登录按钮点击事件
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String zh = ti_zh.getText().toString();
                String mm = ti_mm.getText().toString();
                try {
                    iMyAidlInterface.setAccount(zh);
                    iMyAidlInterface.setPassword(mm);

                    String info=iMyAidlInterface.getInfo();
                        Toast.makeText(MainActivity.this, ""+info, Toast.LENGTH_SHORT).show();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }


//                //解绑
//                Log.i("客户端","解绑线程...");
//                unbindService(serviceConnection);
            }
        });
    }

    ServiceConnection serviceConnection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            iMyAidlInterface=IMyAidlInterface.Stub.asInterface(iBinder);
            Log.i("serviceConnection",""+iMyAidlInterface);
        }
        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };
}

XML文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:gravity="center"
    android:layout_margin="18dp"
    tools:context=".MainActivity">

    <com.google.android.material.textfield.TextInputLayout

        android:layout_width="match_parent"
        android:gravity="center"
        android:layout_height="wrap_content"
        android:hint="请输入账号">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/ti_zh"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            />
    </com.google.android.material.textfield.TextInputLayout>

    <com.google.android.material.textfield.TextInputLayout
        android:layout_marginTop="15dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入密码"
        app:endIconMode="password_toggle">
    <com.google.android.material.textfield.TextInputEditText
        android:id="@+id/ti_mm"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textPassword"
    />
        <Button
            android:layout_marginTop="20dp"
            android:id="@+id/textButton"
            android:gravity="center"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="登录"
            style="@style/Widget.MaterialComponents.Button.TextButton"
            />


</com.google.android.material.textfield.TextInputLayout>

</LinearLayout>
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值