AIDL服务学习笔记 - Android Studio


Android Studio - AIDL服务学习笔记

一、为什么要有AIDL?

无论学什么东西,最先得弄明白为什么要有这个东西,不要说存在即是合理,存在肯定合理,但是你还是没有明白。对于AIDL有一些人的浅显概念就是,AIDL可以跨进程访问其他应用程序,和其他应用程序通讯,那我告诉你,很多技术都可以访问,如广播(应用A在AndroidManifest.xml 中注册指定Action的广播)应用B发送指定Action的广播,A就能收到信息,这样也能看成不同应用之间完成了通讯(但是这种通讯是单向的);还如 ContentProvider,通过URI接口暴露数据给其他应用访问;但是这种都算不上是应用之间的通讯。可能最让人迷惑的是Android推出来了 Messager,它就是完成应用之间的通讯的。那么为什么还要有AIDL呢,官方文档介绍AIDL中有这么一句话:
Note: Using AIDL is necessary only if you allow clients from different applications to access your service for IPC and want to handle multithreading in your service. If you do not need to perform concurrent IPC across different applications, you should create your interface by implementing a Binder or, if you want to perform IPC, but do not need to handle multithreading, implement your interface using a Messenger. Regardless, be sure that you understand Bound Services before implementing an AIDL.
第一句最重要,“只有当你允许来自不同的客户端访问你的服务并且需要处理多线程问题时你才必须使用AIDL”,其他情况下你都可以选择其他方法,如使用Messager,也能跨进程通讯。可见AIDL是处理多线程、多客户端并发访问的。而Messager是单线程处理。还是官方文档说的明白,一句话就可以理解为什么要有AIDL。那么是不是这样的写个AIDL试试。


备注:1、为什么要有AIDL?引用自“彻底明白Android中AIDL及其使用


二、如何使用AIDL?

AIDL(Android Interface Definition Language)是一种接口定义语言,编译器通过***.aidl文件的描述信息生成符合通信协议的Java代码,我们无需自己去写这段繁杂的代码,只需要在需要的时候调用即可,通过这种方式我们就可以完成进程间的通信工作。

接下来使用一个模拟下载数据的实例来说明AIDL的基本使用:

一、创建服务端Module步骤如下:

    1、首先在AS创建一个服务端的Module: service_aidl,并在此Module里面创建一个AIDL文件(默认文件名即可),如下图所示:

         创建AIDL   创建AIDL

    2 、在IMyAidlInterface.aidl文件里定义需要使用的方法:

package com.example.service_aidl;


interface IMyAidlInterface {
    //系统默认创建
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
    //得到下载进度值
    int getProgressValue();
}

    3、在AS里面可能需要同步一下代码或者Clean Projecty一次,编译器才会自动生成对应的IMyAidlInterface.java接口文件:

同步、清除

    4、定义一个Service的子类,将接口暴露给客户端:
    Service子类重写你所需要的方法就行了,不需要重写所有的方法。此处需要特别注意的是onBind方法返回的是一个IMyAidlInterface.Stub的实现类对象,跟踪文件可以知道它是继承了Binder的一个子类。
我在此处定义了一个pro成员变量用于模拟下载进度。
package com.example.aidlservice;


import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;

import com.example.service_aidl.IMyAidlInterface;


public class AidlService extends Service{

//创建一个变量用于模拟下载进度
private int pro;
//创建IMyAidlInterface.Stub的实现类对象,其继承了Binder
private IMyAidlInterface.Stub AidlBinder = new IMyAidlInterface.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString)
throws RemoteException {

}

@Override
public int getProgressValue() throws RemoteException {
return AidlService.this.pro;
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d("MyLog","AidlService...onBind");
return AidlBinder;
}

@Override
public boolean onUnbind(Intent intent) {
Log.d("MyLog","AidlService...onUnbind");
return super.onUnbind(intent);
}

@Override
public void onCreate() {
Log.d("MyLog","AidlService...onCreate");
super.onCreate();
new Thread(){
@Override
public void run() {
super.run();
for( ; ;){
AidlService.this.pro++;
Log.d("MyLog","AidlService.this.pro"+ AidlService.this.pro);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(AidlService.this.pro >= 100){
break;
}
}
}
}.start();
}

@Override
public void onDestroy() {
Log.d("MyLog","AidlService...onDestroy");
super.onDestroy();
}
}
    5、在AndroidManifest.xml里面配置Service
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.service_aidl">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
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="com.example.aidlservice.AidlService">
<intent-filter>
<action android:name="com.example.aidlservice.AidlService"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>
</application>

</manifest>
Activity和Activity的布局文件默认即可,至此我们的服务端Module就写好了,接下来我们完成客户端的Module:client_aidl。

二、创建客户端Module步骤如下:
 1、首先在AS创建一个客户端的Module: client_aidl,并在此Module里面创建一个AIDL文件,此处需要特别注意AIDL的文件名和包名以及***.aidl里面内容都必须和服务端一致,换句话说也就是两端的AIDL部分代码必须保持一致,如下图所示:
        此处将创建的两个Module截图作为对比和参考:
客户端: 客户端                           服务端: 服务端

***.aidl

    2、同样需要在AS里面可能需要同步一下代码或者Clean Projecty一次,编译器才会自动生成对应的IMyAidlInterface.java接口文件:
   3、在客户端绑定Service,这里与本地绑定Service不同的是这里的ServiceConnection并不能直接获取到服务端onBind所返回的对象,它只能返回onBind所返回的对象的代理。所以此处需要通过下面的方法来获取代理对象:
IMyAidlInterface stub = IMyAidlInterface.Stub.asInterface(service);
   此客户端有一个作为下载点击的Button,一个TextView(默认隐藏)和一个ProgressBar来显示进度(默认隐藏),下面是Activity代码和布局文件代码:
package com.example.client_aidl;

import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.AsyncTask;
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.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.example.service_aidl.IMyAidlInterface;

public class MainActivity extends AppCompatActivity {

//ProgressBar组件
ProgressBar progressBar;
//TextView组件
TextView textView;
//IMyAidlInterface对象
IMyAidlInterface stub = null;
//服务绑定成功标志
boolean bindFlag;
//下载数据标记
boolean downloadFlag;
//创建ServiceConnection对象
private ServiceConnection conn = new ServiceConnection() {
//服务绑定成功后调用
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//从第二个参数取出服务端返回的对象代理
MainActivity.this.stub = IMyAidlInterface.Stub.asInterface(service);
bindFlag = true;
Log.i("MyLog", "stub...: 绑定服务成功");
doDownloadData();
}

//服务非正常断开由系统调用 普通断开不会调用
@Override
public void onServiceDisconnected(ComponentName name) {

}
};

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

//得到所有组件
private void getALLUserView() {
progressBar = (ProgressBar) this.findViewById(R.id.progressBar);
textView = (TextView) this.findViewById(R.id.downloadText);
}

//下载按钮点击事件
public void downloadButton(View view) {
if (!bindFlag && !downloadFlag) {
//绑定服务
doBindService();
//下载数据
//doDownloadData();
downloadFlag = true;
}
}

//绑定服务
private void doBindService() {
//创建意图,并隐式绑定服务
Intent intent = new Intent();
//service_aidl 服务所在Activity包路径 5.0后需指定
intent.setPackage("com.example.service_aidl");
intent.setAction("com.example.aidlservice.AidlService");
this.bindService(intent, this.conn, Service.BIND_AUTO_CREATE);
}

//下载数据
private void doDownloadData() {
Log.i("MyLog", "stub...: doDownloadData");
if (stub != null) {
Log.i("MyLog", "stub...: " + stub.toString());
new MyAsyncTask().execute(MainActivity.this.stub);
}

}

//解绑服务
private void doUnBindService() {
this.unbindService(this.conn);
bindFlag = false;
}

@Override
protected void onDestroy() {
super.onDestroy();
//解绑服务
doUnBindService();
}

//创建AsyncTask对象
public class MyAsyncTask extends AsyncTask<IMyAidlInterface, Integer, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
//设置显示
progressBar.setVisibility(View.VISIBLE);
textView.setVisibility(View.VISIBLE);
}

//接收服务端下载数据
@Override
protected String doInBackground(IMyAidlInterface... params) {
int pro = 0;
for (; ; ) {
try {
Thread.sleep(500);
//得到进度值
if (params[0] != null) {
pro = params[0].getProgressValue();
this.publishProgress(pro);
}
if (pro == 100) {
//解绑服务
doUnBindService();
downloadFlag = false;
break;
}

} catch (RemoteException | InterruptedException e) {
e.printStackTrace();
}
}
return "下载成功!";
}

@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
int tmp = values[0];
progressBar.setProgress(tmp);
textView.setText("下载进度: " + tmp + "%");
}

@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show();
}

@Override
protected void onCancelled() {
super.onCancelled();
}
}
}
 
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.client_aidl.MainActivity">

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ff0"
android:onClick="downloadButton"
android:text="@string/downloadButton"
android:textSize="18sp"/>

<TextView
android:id="@+id/downloadText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
android:visibility="invisible"/>

<ProgressBar
android:id="@+id/progressBar"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:max="100"
android:progress="0"
android:visibility="invisible"/>
</LinearLayout>

最后先将服务端安装到虚拟机,在将客户端安装到虚拟机。在客户端点击下载得到下面是执行效果:
  效果1  效果2  效果3

从代码可以看出,使用AIDL线程间通信只是在绑定Service的回调部分有点差别,其他都和本地绑定基本差不多,代码注释比较清楚,就不再赘述了。

新手学习笔记,不足之处望指出,有什么疑问欢迎大家一起讨论


  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: Android Studio中的AIDLAndroid接口定义语言的缩写,它是一种用于定义Android应用程序中的进程间通信(IPC)接口的语言。使用AIDL,您可以定义客户端和服务之间的接口,以便它们可以相互通信和交换数据。在Android应用程序中,AIDL通常用于实现跨进程通信,例如在应用程序中使用服务来执行后台任务。 ### 回答2: Android Studio AIDLAndroid Interface Definition Language)是一种用于在Android应用程序中进行进程间通信(IPC)的技术。它允许不同应用程序或同一应用程序中的不同进程之间进行数据和指令的传输和共享。AIDL基于Binder机制实现,是许多Android系统服务和框架中广泛使用的IPC技术。 在Android Studio中使用AIDL,首先需要创建一个AIDL接口,该接口定义了可用于在不同进程之间进行通信的方法。一旦创建了该接口,它可以在应用程序中使用,与其他进程交换数据和指令。AIDLAndroid系统自动创建和管理,不需要手动实现Binder机制。 使用AIDL的主要优点是实现非常方便,而且可以跨多个进程使用。它使得应用程序能够高效地共享数据和指令,并允许不同进程之间进行通信,从而扩展了Android应用程序的功能和交互性。 一些开发人员可能认为AIDL学习和使用有一定的难度,但是一旦了解了AIDL的基本原理和使用方法,就能够轻松实现IPC功能,并创建更高效的Android应用程序。总之,通过使用AIDLAndroid应用程序开发人员可以实现更好的应用程序设计和创新,并提高应用程序的性能和用户体验。 ### 回答3: Android Studio AIDLAndroid Interface Definition Language)是一种跨进程通信的机制,用于在不同的Android组件之间进行通信。 AIDL类似于SOAP(Simple Object Access Protocol),RPC(Remote Procedure Call)或CORBA(Common Object Request Broker Architecture),它是一种高级的RPC机制,允许不同的应用程序使用相同的接口来进行通信。 AIDL的主要作用是允许一个应用程序通过一个中间层向另外的一个应用程序发送请求,并且读取响应信息。它是Android操作系统提供的默认RPC机制,由于基于Binder实现,因此具备更高的性能和更好的稳定性。 AIDL可以让你定义一组接口,用来描述应用组件之间的通信方法,包括输入和输出参数。AIDL文件定义完毕后,你可以使用Android Studio自动生成AIDL接口的Java类,以便你可以跨进程访问该接口。 使用AIDL的好处是,可以将系统拆分成独立的组件,这些组件可以在不同的进程之间进行通信,从而实现了更好的资源利用和更加灵活的架构设计。 总之,Android Studio AIDL是一种强大的跨进程通信机制,有助于提高应用程序的性能和稳定性,从而让我们能够更好地设计和开发更高效的Android应用程序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值