zoukankan      html  css  js  c++  java
  • Android AIDL 使用

    一、概述:

    AIDL是Android中IPC(Inter-Process Communication)方式中的一种,AIDL是Android Interface definition language的缩写。

    其主要作用是用于进程间额通讯。

    在Android系统中,每个进程都运行在一块独立的内存中,在其中完成自己的各项活动,与其他进程都分隔开来。可是有时候我们又有应用间进行互动的需求,比较传递数据或者任务委托等,AIDL就是为了满足这种需求而诞生的。通过AIDL,可以在一个进程中获取另一个进程的数据和调用其暴露出来的方法,从而满足进程间通信的需求。
     
    二、语法:
    1、支持的数据类型:
    • 八种基本数据类型:byte、char、short、int、long、float、double、boolean
    • String,CharSequence
    • 实现了Parcelable接口的数据类型
    • List 类型。List承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象
    • Map类型。Map承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象

    2、

    AIDL文件可以分为两类。一类用来声明实现了Parcelable接口的数据类型,以供其他AIDL文件使用那些非默认支持的数据类型。还有一类是用来定义接口方法,声明要暴露哪些接口给客户端调用,定向Tag就是用来标注这些方法的参数值。

     3、

    定向Tag。定向Tag表示在跨进程通信中数据的流向,用于标注方法的参数值,分为 in、out、inout 三种。其中 in 表示数据只能由客户端流向服务端, out 表示数据只能由服务端流向客户端,而 inout 则表示数据可在服务端与客户端之间双向流通。此外,如果AIDL方法接口的参数值类型是:基本数据类型、String、CharSequence或者其他AIDL文件定义的方法接口,那么这些参数值的定向 Tag 默认是且只能是 in,所以除了这些类型外,其他参数值都需要明确标注使用哪种定向Tag。
     
    4、

    明确导包。在AIDL文件中需要明确标明引用到的数据类型所在的包名,即使两个文件处在同个包名下。

    三、编写代码:

    创建两个工程,一个作为服务端,一个作为客户端,客户端绑定服务端service,然后调用方法向服务端获取书籍列表,向服务端添加书籍。

    1、服务端:

    (1)、创建aidl文件Book.aidl

    创建后便可以在目录里看到aidl文件。

     接下来定义Book类,注意Books类的包名必须与Book.aidl包名一样,但是不可与Book.aidl在同一个目录下。

    Book.class的代码如下,其必须继承Parcelable接口:

    package com.status.aidlproject.com.aidl;
    
    import android.os.Parcel;
    import android.os.Parcelable;
    
    public class Book implements Parcelable {
    
        private String bookName;
    
        public Book(String name) {
            bookName = name;
        }
    
        public String getBookName() {
            return bookName;
        }
    
        public void setBookName(String bookName) {
            this.bookName = bookName;
        }
    
        protected Book(Parcel in) {
            bookName = 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];
            }
        };
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(bookName);
        }
    
        public void readFromParcel(Parcel desc) {
            bookName = desc.readString();
        }
    
        @Override
        public String toString() {
            return "bookName=" + bookName;
        }
    }

    接下来修改Book.aidl文件,将其声明为parcelable类型,并且需要注意的是,原先默认的interface接口需要去掉,否则编译会报错。

    // Book.aidl
    package com.status.aidlproject.com.aidl;
    
    // Declare any non-default types here with import statements
    
    parcelable Book;
    //需要删除
    /*interface Book {
        void default(String s);
    }*/

    接下来便是要定义服务端暴露给客户端的接口了(获取书籍列表,添加书籍)

    在同样的目录定义aidl文件BookManager.aidl

    代码如下:

    // BookManager.aidl
    package com.status.aidlproject.com.aidl;
    
    // Declare any non-default types here with import statements
    import com.status.aidlproject.com.aidl.Book;
    interface BookManager {
        List<Book> getBookList();
    
        void addBook(inout Book book);
    }

    注意要把包手动导进来。

    接下来,make project便可以看到aidl编译成代码文件

     

    这个文件才是我们真正需要用到的。

    (2)、创建Service,供客户端绑定

    package com.status.aidlproject;
    
    import android.app.Service;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.IBinder;
    import android.support.annotation.Nullable;
    import android.util.Log;
    
    import com.status.aidlproject.com.aidl.Book;
    import com.status.aidlproject.com.aidl.BookManager;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class BookService extends Service {
        private final String TAG = BookService.class.getSimpleName();
        private List<Book> list;
    
        @Override
        public void onCreate() {
            super.onCreate();
            list = new ArrayList<>();
            for (int i = 0; i < 5; i++) {
                Book book = new Book("第" + i + "本书");
                list.add(book);
            }
        }
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return bookManager;
        }
    
        private BookManager.Stub bookManager = new BookManager.Stub() {
            @Override
            public List<Book> getBookList() {
                Log.d(TAG, "getBookList");
                return list;
            }
    
            @Override
            public void addBook(Book book) {
                Log.d(TAG, "addBook");
                if (book != null) {
                    list.add(book);
                }
                Log.d(TAG, book.toString());
            }
        };
    
        @Override
        public void unbindService(ServiceConnection conn) {
            super.unbindService(conn);
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
        }
    }

    Manifests文件中可以这样写:

    <service
         android:name=".BookService"
         android:enabled="true"
         android:exported="true"
         android:process=":remote">
            <intent-filter>
               <action android:name="android.intent.action.BookService" />
            </intent-filter>
    </service>

     onBind方法返回的是BookManager.Stub对象,实现里面的两个方法,客户端拿到这个对象后就可以与服务端通讯了。

    2、客户端

    (1)

    将aidl文件与Book.class拷贝到客户端的工程,注意他们的目录需要与服务端的一样,也就是说aidl与Book.class包名要与服务端的一样。

    make project一下便会生成编译后的文件

    (2)、编写代码,与服务端连接:

    package com.status.aidlclient;
    
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.TextView;
    
    import com.status.aidlproject.com.aidl.Book;
    import com.status.aidlproject.com.aidl.BookManager;
    import com.status.aidlproject.com.aidl.IMyConnect;
    
    import java.util.List;
    
    public class MainActivity extends AppCompatActivity {
    
        private final String TAG = MainActivity.class.getSimpleName();private TextView textView3;
        private TextView textView4;
        private TextView textView5;
        private final String ACTION1 = "android.intent.action.ConnectService";
        private final String ACTION2 = "android.intent.action.BookService";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            textView3 = findViewById(R.id.text3);
            textView4 = findViewById(R.id.text4);
            textView5 = findViewById(R.id.text5);
    
            textView3.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(ACTION2);
                    // 注意在 Android 5.0以后,不能通过隐式 Intent 启动 service,必须制定包名
                    intent.setPackage("com.status.aidlproject");
                    bindService(intent, connection2, Context.BIND_AUTO_CREATE);
                }
            });
    
            textView4.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    try {
                        if (manager != null) {
                            List<Book> list = manager.getBookList();
                            Log.d(TAG, "getBookList:" + list);
                        }
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            });
    
            textView5.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Book book = new Book("添加的书");
                    try {
                        if (manager != null) {
                            manager.addBook(book);
                        }
    
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    private BookManager manager;
        ServiceConnection connection2 = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.d(TAG, "onServiceConnected");
                manager = BookManager.Stub.asInterface(service);
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                manager = null;
            }
        };
    }

    textView3用于绑定服务端

    textView4用于获取服务端书籍列表

    textView5用于向服务端添加书籍

     转载请标明出处:https://www.cnblogs.com/tangZH/p/10775848.html 

    更多精彩文章: http://77blogs.com/?p=293

    参考:https://www.jianshu.com/p/29999c1a93cd

  • 相关阅读:
    POJ3320 Jessica's Reading Problem
    POJ3320 Jessica's Reading Problem
    CodeForces 813B The Golden Age
    CodeForces 813B The Golden Age
    An impassioned circulation of affection CodeForces
    An impassioned circulation of affection CodeForces
    Codeforces Round #444 (Div. 2) B. Cubes for Masha
    2013=7=21 进制转换
    2013=7=15
    2013=7=14
  • 原文地址:https://www.cnblogs.com/tangZH/p/10775848.html
Copyright © 2011-2022 走看看