• Android进程间的通信之AIDL


    Android服务被设计用来执行很多操作,比如说,可以执行运行时间长的耗时操作,比较耗时的网络操作,甚至是在一个单独进程中的永不会结束的操作。实现这些操作之一是通过Android接口定义语言(AIDL)来完成的。AIDL被设计用来执行进程间通信,另一种实现方式见博文Android进程间的通信之Messenger。本文我们将学习如何创建AIDL文件实现Android进程间通信。在正式学习之前,我们先澄清一些“事实”。

    关于Android Service

    1、Android服务不是后台任务,它们默认只运行在你的app的主线程中
    2、Android服务可以通过设置来运行在不同进程中
    3、如果Android服务在不同进程中启动,你将不能使用通常的IBinder接口与其通信

    AIDL:Android Interface Definition Language

    为了在Android应用中实现进程间通信,我们需要在远端进程中定义一系列可被当前进程访问的方法。通过AIDL我们可以定义这样的一系列方法。AIDL就好像Java中的其它接口一样可以在其中定义一些抽象方法。我们首先需要创建一个以.aidl为后缀的文件并在里面定义所需的抽象方法。

    AIDL的一个主要特征是,通过使用AIDL,我们可以在两个不同的应用中进行通信(其实Messenger也可以实现同样的操作,两者区别请见博文Android进程间的通信之Messenger);当然,如果你的应用不需要跟另外一个应用进行通信,那就尽量避免使用AIDL机制吧。aidl文件中定义的抽象方法中,只有一些原始数据类型以及一些基本数据类型如String,lists,maps等可以作为这些方法的参数,如果你想使用一个自定义类作为参数,那么你的自定义类必须实现Parcelable接口,并且该类要被导入AIDL文件中,这一点应该在单独的课程中进行讲解。本文只学习简单的AIDL用法。

    AIDL实现思路

    AIDL通过定义服务端暴露的接口,以提供给客户端来调用,AIDL使服务端可以并行处理(因此你可能需要考虑多线程并发访问的线程安全性问题)。通过编写aidl文件来设计想要暴露的接口,编译后会自动生成相应的Java文件,服务端将接口的具体实现写入Stub中,通过IBinder对象传递给客户端,客户端bindService时,通过asInterface方法将IBinder还原成接口,供客户端调用其中的方法。

    简单示例

    AndroidManifest.xml

    复制代码
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".BoundService" android:process=":custom_process"/>
    </application>
    复制代码

    IBoundService.aidl

    package yf.exam.service.aidl;
    interface IBoundService{
        int getResult(int a, int b);
    }

    BoundService.java

    复制代码
    public class BoundService extends Service {
        private IBoundService.Stub mBinder = new IBoundService.Stub() {
            @Override
            public int getResult(int a, int b) throws RemoteException {
                return a+b;
            }
        };
        @Override
        public IBinder onBind(Intent intent) {
            return mBinder;
        }
    }
    复制代码

    MainActivity.java

    复制代码
    public class MainActivity extends Activity {
        private Button btn = null;
        private IBoundService mIBoundService;
        private boolean mServiceConnected = false;
        private ServiceConnection conn = new ServiceConnection() {
            @Override
            public void onServiceDisconnected(ComponentName name) {
                mServiceConnected = false;
            }
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                mIBoundService = IBoundService.Stub.asInterface(service);
                mServiceConnected = true;
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            btn = (Button) findViewById(R.id.button1);
            Intent intent = new Intent(this, BoundService.class);
            bindService(intent, conn, Context.BIND_AUTO_CREATE);
            btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mServiceConnected) {
                        try {
                            int result = mIBoundService.getResult(2, 4);
                            Toast.makeText(MainActivity.this, "result=" + result,
                                    Toast.LENGTH_SHORT).show();
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            if (mServiceConnected) {
                unbindService(conn);
                mServiceConnected = false;
            }
        }
    }
    复制代码
  • 相关阅读:
    关于在unity中动态获取字符串后在InputField上进行判断的BUG
    关于在将暴风SDK倒入unity中运行程序出现报错问题
    关于用暴风SDK在unity中加入VR效果和利用暴风手柄进行操作
    IDEA 接口无法跳转到实现类
    springboot项目中获取pom中的属性
    mybatisplus异常: 栏位索引超过许可范围:2,栏位数:1。
    七日杀windows服务器搭建
    SQL子查询报错syntax error at end of input
    关于在将excel数据导入到pgsql数据库的时候中文变成问号的处理方式
    字符串补位操作
  • 原文地址:https://www.cnblogs.com/huilixieqi/p/6497092.html
Copyright © 2020-2023  润新知