Android studio 中创建AIDL Service
1、概述
AIDL在android系统中的作用
AIDL,Android Interface definition language的缩写,它是一种android内部进程通信接口的描写叙述语言,通过它我们能够定义进程间的通信接口。近期看了下AIDL在Android系统中的使用方法,在网上看到非常多初学的朋友不太明确AIDL的实际作用,android提供了非常多进程间通信的组件,像action、broadcast、contentprovide都能够实现进程间的通信,为什么还要用AIDL这个东西呢?我在android源代码中实现了一个自己写的AIDL样例。用以简单解释下AIDL的作用。
有开发过蓝牙或者WIFI应用的朋友肯定都知道,要去操作它必须先获得一个管理类,比方WIFI的管理类是WifiManager,通过getSystemService(Context.WIFI_SERVICE)就能够得到wifi的管理权限,这个提供了非常多的方法能够让用户去操作它,比方打开wifi能够调用setWifiEnabled(true)方法。
那这个Manager究竟做了什么工作呢?是如何实现打开wifi的呢?事实上这个Manager仅仅是一个管理类,真正干活的另有其人,是一个叫WifiService的系统服务。
在Android系统中有非常多的Manager。wifi的管理类叫WifiManager。蓝牙的管理类叫BluetoothManager,可是,仅仅要有xxxManager.java。就会有Ixxx.aidl,而且有xxxService.java。这个aidl类就是实现Manager和Service通信的桥梁。
Binder驱动,Binderclient、服务端这三者之间的关系:
binder通信的四个角色应该是client组件。server组件,serviceManager和binder驱动。client组件和server组件进行通信,要通过ServiceManager查询server组件的引用。server向ServiceManager注冊一个binder尸体,client通过ServiceManager获得binder实体的一个引用,这样client和server就能够通信了
2、Android studio 中AIDL的使用
在eclipse里面操作时aidl文件个java文件都放在一个包下, client直接将该包拷贝到自己的文件夹下,然后能够另外建另外一个包放其它代码。
但在android studio以下这样是不能够的,须要在src单独建一个AIDL文件夹,将aidl文件放在里面。java文件在另外的包下,这样就导致服务端项目与client项目的包名必须同样。在as中project相当于es的workspace,moudle相当于es的project,在eclipse里面是两个project在通信,so
我推測在as中是两个mould在通信。因此建了一个project(里面自带一个app module),让app moulde作为client然后又另外加了一个服务端moudle 叫aidlserver。
在aidlserver的project视图以下的src以下右键new 选择AIDL ,AIDL Folder ,然后将自己的aidl文件放入当中。
在Android Studio下创建AIDL Serivce。
建立ADIL Service的步骤比建立普通Service要多一些,主要有:
1、创建AIDL文件,在这里面定义远程接口。
2、生成Java接口文件。
3、建立一个Service的子类,而且记得在AndroidManifest.xml文件里配置。
在client调用ADIL Servie:
1、拷贝server端的AIDL文件,并生成Java接口文件。
2、用BindService来调用Service,与调用普通Serivce相类似,仅仅是获取IBinder的方式有点不一样。
以下是一个简单的样例
一、建立服务端AIDL文件
在项目名称上右键>NEW>AIDL>AIDL File,这样就创建了一个ADIL文件,命名为AIDLServerService.aidl
package com.test.huangxingli.aidlserver;
import com.test.huangxingli.aidlserver.Girl;
// Declare any non-default types here with import statements interface AIDLServerService { String sayHello();
Girl getGirl();
}
再创建Girl.aidl
package com.test.huangxingli.aidlserver;
parcelable Girl;
建好这两个文件后再编写Girl.java .注意要先写Girl.aidl然后再写Girl.java
刚開始时 我先写的Girl.java 然后再写Girl.aidl时提示不能创建重名的文件。
Girl.java例如以下:
package com.test.huangxingli.aidlserver; import android.os.Parcel;
import android.os.Parcelable; /**
* Created by huangxingli on 2015/3/27.
*/
public class Girl implements Parcelable{ String name;
int age; public Girl() { } public String getName() { return name;
} public int getAge() {
return age;
} public void setName(String name) {
this.name = name;
} public void setAge(int age) {
this.age = age;
} @Override
public int describeContents() {
return 0;
} @Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age); } public static final Creator<Girl> CREATOR=new Creator<Girl>() {
@Override
public Girl createFromParcel(Parcel source) {
Girl girl=new Girl();
girl.setName(source.readString());
girl.setAge(source.readInt());
return girl;
} @Override
public Girl[] newArray(int size) {
return new Girl[size];
}
};
}
然后菜单中选择Build>Rebulid Project,这样就生成了java接口文件,地址在项目目录/app/build/generated/aidl里面
如图
接着写Service类MAIDLServerService,例如以下:
package com.test.huangxingli.aidlserver; import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException; public class MAIDLServerService extends Service { public MAIDLServerService() {
} AIDLServerService.Stub binder=new AIDLServerService.Stub() { @Override
public String sayHello() throws RemoteException {
return "hello, i am from AIDLServerService";
} @Override
public Girl getGirl() throws RemoteException {
Girl girl=new Girl();
girl.setAge(25);
girl.setName("lily");
return girl;
}
}; @Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return binder;
} }
然后在AndroidManifest.xml中里面将该服务器端的Service注冊一下:例如以下
<? xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.huangxingli.aidlserver" > <application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" > <service
android:name="com.test.huangxingli.aidlserver.MAIDLServerService"
android:process=":remote"
>
<intent-filter>
<action android:name="com.test.huangxingli.aidlserver.MAIDLServerService"></action>
</intent-filter>
</service>
</application> </manifest>
server端结构如图
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
二、建立clientAIDL文件
首先要拷贝AIDL文件,这里要保证文件的内容一模一样,包含包的名称,比方本样例中服务器端AIDL文件所在包的名称是com.test.huangxingli.aidlserver,怎样做到这一点,先新建一个项目,然后在:项目目录/app/src/main目录下建立一个aidl目录。与java目录同级,在Android
Studio中就能够看到这个文件夹。在这个文件夹上右键New>Package。建立一个com.test.huangxingli.aidlserver的包,再将aidl文件拷进去。这样才干保证生成的java接口文件全然一样。否则会提示找不到接口。參照下图操作
Intent must be explitict
fromerr=sm6neVzq">怎样解决Android 5.0中出现的警告:Service Intent must be expli
Intent mIntent = new Intent();
mIntent.setAction("com.test.huangxingli.aidlserver.MAIDLServerService");
Intent eintent = new Intent(createExplicitFromImplicitIntent(MainActivity.this, mIntent));
bindService(eintent,connection,BIND_AUTO_CREATE); MainActivity.this.startService(eintent);
应在 startService之前
package com.test.huangxingli.aidlserver; import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView; import java.util.List; public class MainActivity extends ActionBarActivity { TextView textView;
Button button;
AIDLServerService aidlServerService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button= (Button) findViewById(R.id.button);
textView= (TextView) findViewById(R.id.textView);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) { // Intent intent=new Intent();
// intent.setAction("com.test.huangxingli.aidlserver.MAIDLServerService");//你定义的service的action
// intent.setPackage(getPackageName());
//
// bindService(intent,connection,BIND_AUTO_CREATE); Intent mIntent = new Intent();
mIntent.setAction("com.test.huangxingli.aidlserver.MAIDLServerService");
Intent eintent = new Intent(createExplicitFromImplicitIntent(MainActivity.this, mIntent));
bindService(eintent,connection,BIND_AUTO_CREATE); MainActivity.this.startService(eintent); }
}); } /***
* Android L (lollipop, API 21) introduced a new problem when trying to invoke implicit intent,
* "java.lang.IllegalArgumentException: Service Intent must be explicit"
*
* If you are using an implicit intent, and know only 1 target would answer this intent,
* This method will help you turn the implicit intent into the explicit form.
*
* Inspired from SO answer: http://stackoverflow.com/a/26318757/1446466
* @param context
* @param implicitIntent - The original implicit intent
* @return Explicit Intent created from the implicit original intent
*/
public static Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) {
// Retrieve all services that can match the given intent
PackageManager pm = context.getPackageManager();
List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0); // Make sure only one match was found
if (resolveInfo == null || resolveInfo.size() != 1) {
return null;
} // Get component info and create ComponentName
ResolveInfo serviceInfo = resolveInfo.get(0);
String packageName = serviceInfo.serviceInfo.packageName;
String className = serviceInfo.serviceInfo.name;
ComponentName component = new ComponentName(packageName, className); // Create a new intent. Use the old one for extras and such reuse
Intent explicitIntent = new Intent(implicitIntent); // Set the component to be explicit
explicitIntent.setComponent(component); return explicitIntent;
} ServiceConnection connection=new ServiceConnection() { String content;
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
aidlServerService=AIDLServerService.Stub.asInterface(service);
try {
content=aidlServerService.sayHello()+"\n";
Girl girl=aidlServerService.getGirl();
content +="my name is "+girl.getName(); textView.setText(content); } catch (RemoteException e) {
e.printStackTrace();
} } @Override
public void onServiceDisconnected(ComponentName name) {
aidlServerService=null;
}
}; }
好了,就到这里就能够执行程序了
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
代码先安装server端的代码。然后再安装client端的。。。
參考文献:
http://blog.csdn.net/huangxingli/article/details/44674751
http://blog.csdn.net/lmj623565791/article/details/38461079
http://blog.csdn.net/shenzhonglaoxu/article/details/42737195
http://www.2cto.com/kf/201501/370478.html
Android studio 中创建AIDL Service的更多相关文章
- Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用
在上一篇文章Android IPC机制(二)用Messenger进行进程间通信中我们介绍了使用Messenger来进行进程间通信的方法.可是我们能发现Messenger是以串行的方式来处理client ...
- Android Studio中创建Kotlin For Android项目
Kotlin俗称Android中的Swift,它是Jetbrains公司开发的基于JVM的一门语言,JetBrains公司可能大家并不熟悉,不过相信IntelliJ IDE大家一定知道,Android ...
- Android实验一(在Android Studio中创建项目和模拟器)
北京电子科技学院(BESTI) 实 验 报 告 课程:移动平台开发 班级:1592 姓名:苏泽楠 学号:20159207 成绩: 指导教师 ...
- 在Android Studio中创建项目和模拟器
北京电子科技学院 实 验 报 告 课程:移动平台应用开发实践 班级:201592 姓名:杨凤 学号:20159213 成绩:___________ 指导老师:娄嘉 ...
- Android Studio中实现AIDL
AIDL 先来两个传送门: http://www.cnblogs.com/yydcdut/p/3961545.html Android面试,与Service交互方式 http://www.cnblog ...
- 在Android Studio中创建(或添加)第一个Hello World应用程序
下面我们将使用Android Studio创建第一个简单的Hello World应用程序. 1.打开Android Studio,加载画面如下图所示: 2.选择”Start a new Andro ...
- Android Studio中创建java项目
1.创建普通的android工程 2.创建一个module 3.module类型选择java library 4.填写libary和class的名字 5.生成的工程如图所示 6.然后点击Run --- ...
- 如何在Android Studio中创建jniLib和asset文件夹 2
1.创建asset文件夹 如图进行操作 2.创建jniLib文件夹 —打开app下面的gradle文件(不是project的gradle) —在gradle文件的Android标签里面添加 sourc ...
- OpenCV - Android Studio 中集成Opencv环境(不包含opencv_contrib部分)
OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,支持的运行环境也是非常的多,这篇文章主要讲的是Android环境集成OpenCV(IDE是Android Studio,我想Eclip ...
随机推荐
- WinCE 下编程须要IP地址控件咋办?
默认控件栏里面没有IP Address Control. 可是 WinCE 系统内的网络属性中是有这种控件的,想知道怎么调用IP Address Control的吗? 先通过远程工具 Remote S ...
- 解决input框中加入disabled="disabled"之后,改变字体的颜色(默认的是灰色)
在input框中加入disabled="disabled"之后,字体默认的就变成灰色了 解决方案 input[disabled]{color:#fff;opacity:1} dis ...
- [UIView setShowsFPS:]: unrecognized selector sent to instance XXX
今天在做sprite Kit game时遇到一个问题. 新建一个项目运行时发现就加了这几句代码无法运行.后来一查原来是storyboard uiview要改一下.改成SKview In your st ...
- 牛客网-《剑指offer》-替换空格
题目:http://www.nowcoder.com/practice/4060ac7e3e404ad1a894ef3e17650423 C++ class Solution { public: vo ...
- Android 之 沉浸式状态栏及顶部状态栏背景色设置
现在很多应用都引用了沉浸式状态栏,如QQ,效果下图: 效果很酷炫,其实设置也很简单.但是,需要注意的是,这种效果只能在API19以及以上版本中才能够做到. 方法一: 首先,如果想让界面Activity ...
- JAVA动态编译辅助类
一.场景 平时我们学学用到在JVM运行时,动态编译.java的源代码情况,比如作为灵活的配置文件.这时候就要用到动态编译,参考下列. 二.类内容 1.引入依赖: <!-- https://mvn ...
- C#随机数字生成的一种方法
1.参考: public class RandomLongGenerater { public static long New(int bit) { ) { throw new Exception(& ...
- Kettle命令行使用说明
Kettle命令行使用说明 1.Pan——转换执行器 用来执行转换.参数与Kitchen类似,如下. 1- -version显示版本信息 2- -file=filename运行xml文件 3- -pa ...
- 算法笔记_204:第四届蓝桥杯软件类决赛真题(Java语言C组)
目录 1 好好学习 2 埃及分数 3 金蝉素数 4 横向打印二叉树 5 危险系数 6 公式求值 前言:以下代码仅供参考,若有错误欢迎指正哦~ 1 好好学习 汤姆跟爷爷来中国旅游.一天,他帮助中国的 ...
- nuxt框架学习
1.static和assets文件夹区别 相同点:都可以存放静态文件 不同:assets下的文件 webpack会处理:static文件夹下的文件不会处理. 2.middleware middlewa ...