ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Android AIDL 学习 (服务端)

2021-11-18 17:03:51  阅读:180  来源: 互联网

标签:return String AIDL Book import Android public 服务端 name


在学习 AIDL的过程中看不过不少的书籍,在网上也找了不少的资料,总算能够实现AIDL的调用,在这里把自己的理解与实现写出来方便一后备忘查找。

主要是自己的底子太差,别人都写的太高大尚很多看不明白。用自己看明白的方式记录下。

话不多说回归正题。

AIDL是什么

AIDL是一个缩写,全称是Android Interface Definition Language,也就是Android接口定义语言。

它就是可以定义一个接口,提供给其他的app调用。

为什么会需要AIDL语音接口

每一个app的运行在虚拟机中都有自己独立的进程,虚拟机为每个app进行划分独立的内存运行空间,app就在这个空间里运行无法越界。

那有自己的独立空间是挺好,程序运行起来互相不影响,但有些时候自己想要获取的数据,自己没法完成只有别的app才能够提供,但自己由跑不出去虚拟机给划分的空间,那怎么办?这时AIDL就来了,app之间只要根据统一的规则,双双规定好接口就能够通过AIDL进行传输数据。

A (客户端)说想从B (服务器端)进行登录的验证,B服务端返回成功还是失败,能够从B端获取一个对象。

我们就以这个小需求为列,看看AIDL需要怎么实现。

首先我们来看服务端,服务端提供服务,那我就是老大,一切规则由我定,你们都是小弟必须按照我的规则来。

我们来看看服务端如何实现。

环境:android stuido 3.6.2

新建一个项目BService

在app上点击右键->新建->AIDL->AIDL文件

 给我们新建的aidl文件起个名字IMyBookManager。

 创建一个Book.java的类,Book的类必须与IMyBookManager的是同一个命名空间。

package com.example.bservice;

public class Book {
    private int price;
    private String name = "";

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Book 这个类,后续我们需要通过AIDL 接口返回给调用者,所以这个类需要进行序列化。

我们让他实现 Parcelable接口。

package com.example.bservice;

import android.os.Parcel;
import android.os.Parcelable;

public class Book implements Parcelable {
    private int price;
    private String name = "";

    public Book(){}

    protected Book(Parcel in) {
        price = in.readInt();
        name = in.readString();
    }

    public static final Creator<Book> CREATOR = new Creator<Book>() {
        @Override
        public Book createFromParcel(Parcel in) {
            return new Book(in);
        }

        @Override
        public Book[] newArray(int size) {
            return new Book[size];
        }
    };

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(price);
        dest.writeString(name);
    }
}

处理完了Book类,我们来处理我们的接口文件  IMyBookManager

IMyBookManager.aidl接口文件中我们实现两个接口,1个是登录login,一个是根据书名返回一个Book的类。

// IMyBookManager.aidl
package com.example.bservice;

// Declare any non-default types here with import statements
//需要采用全部包名的引入。
import com.example.bservice.Book;

//需要说明我们引入的book 是个序列化的类。
parcelable Book;

interface IMyBookManager {
    /**
     * 默认添加的基础类型接口,不用可以删掉
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

    String login(String userName, String pwd);
    
    Book queryByName(String bookName);
}

 处理完了接口文件之后,我们编译一下,按ctrl+f9,或者点击菜单进行编辑。

编译完成这后系统会自动的生成一个实现类,这个是有系统生成的,不需要我们关系,我们需要处理的只是实现个类,继承系统给我们生成的这个类的子类。

好了我们现在添加  MyBookManager 继承  IMyBookManager.Stub类。

package com.example.bservice;

import android.os.RemoteException;

public class MyBookManager extends IMyBookManager.Stub {
    @Override
    public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
        
    }

    @Override
    public String login(String userName, String pwd) throws RemoteException {
        return null;
    }

    @Override
    public Book queryByName(String bookName) throws RemoteException {
        return null;
    }
}

 上面是个框架,下面我们进行简单的具体实现。

package com.example.bservice;

import android.os.RemoteException;

public class MyBookManager extends IMyBookManager.Stub {
    @Override
    public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

    }

    @Override
    public String login(String userName, String pwd) throws RemoteException {
        if(userName.equalsIgnoreCase("abcd") && pwd.equalsIgnoreCase("123")){
            return "success";
        }
        return "error";
    }

    @Override
    public Book queryByName(String bookName) throws RemoteException {
        Book book = new Book();
        book.setName(bookName);
        book.setPrice(100);
        return book;
    }
}

好了这样我们就对接口进行了一个简单的实现。

说了这么多还是没说到底该怎么用,现在我就来说说该怎么用。

想对外提供给其他的app调用我们还需要创建一个服务,通过服务的绑定方法进行对外进行服务。

好了我们添加个服务吧。

我们先添加个报名 service,全路径为 com.example.bservice.service

 生成的代码

package com.example.bservice.service;

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

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

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

 还记得我们刚才添加了个 MyBookManager的实现类吧,他集成了IMyBookManager.Stub的子类,我来看看他是什么样子的

我们发现 Stub 是集成了 Binder 的类,我们再看看Binder类

Binder类实现了IBinder的接口,而我们的Service 真好也有个Bind的方法是返回IBinder这接口。

那我们就可以吧我们的 MyBookManager通过这个接口返回给调用者。

最终我们的 MyService 代码。把我们的接口实现类给返回。

package com.example.bservice.service;

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

import com.example.bservice.MyBookManager;

public class MyService extends Service {
    
    MyBookManager bookManager = new MyBookManager();
    
    public MyService() {
    }

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

接口的实现类完成了,服务也添加了,那我们的服务要想在外边能被调用,我们还差最后一步,需要再AndroidManifest.xml 文件中对齐进行设置。

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

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

        <service
            android:name=".service.MyService"
            android:enabled="true"
            android:exported="true"
            android:process=":remote"
            >
            <intent-filter>
                <action android:name="com.example.bservice.bookService"/>
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service>

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

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

</manifest>

 <action android:name="com.example.bservice.bookService"/> 是我们为我们的服务定义的一个调用名称,这个自己可以任意的起。当然要符合命名规范。

到处我们的服务就能够正常的工作了,可以对外提供接口服务了。

标签:return,String,AIDL,Book,import,Android,public,服务端,name
来源: https://blog.csdn.net/jackning/article/details/121381886

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有