⑴ 如何对系统调用了aidl文件进行避免混淆
建立AIDL服务要比建立普通的服务复杂一些,具体步骤如下:
(1)在Eclipse android工程的java包目录中建立一个扩展名为aidl的文件。该文件的语法类似于Java代码,但会稍有不同。详细介绍见实例52的内容。
(2)如果aidl文件的内容是正确的,ADT会自动生成一个Java接口文件(*.java)。
(3)建立一个服务类(Service的子类)。
(4)实现由aidl文件生成的Java接口。
(5)在AndroidManifest.xml文件中配置AIDL服务,尤其要注意的是,<action>标签中android:name的属性值就是客户端要引用该服务的ID,也就是Intent类的参数值。
建立AIDL服务
本例中将建立一个简单的AIDL服务。这个AIDL服务只有一个getValue方法,该方法返回一个String类型的值。在安装完服务后,会在客户端调用这个getValue方法,并将返回值在TextView组件中输出。建立这个AIDL服务的步骤如下:
(1)建立一个aidl文件。在Java包目录中建立一个IMyService.aidl文件。IMyService.aidl文件的位置如图
IMyService.aidl文件的内容如下:
Java代码:
package eoe.demo;
interface IMyService {
String getValue();
}
IMyService.aidl文件的内容与Java代码非常相似,但要注意,不能加修饰符(例如,public、private)、AIDL服务不支持的数据类型(例如,InputStream、OutputStream)等内容。
(2)如果IMyService.aidl文件中的内容输入正确,ADT会自动生成一个IMyService.java文件。读者一般并不需要关心这个文件的具体内容,也不需要维护这个文件。关于该文件的具体内容,读者可以查看本节提供的源代码。
(3)编写一个MyService类。MyService是Service的子类,在MyService类中定义了一个内嵌类(MyServiceImpl),该类是IMyService.Stub的子类。MyService类的代码如下:
Java代码:
package eoe.demo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class MyService extends Service {
public class MyServiceImpl extends IMyService.Stub {
@Override
public String getValue() throws RemoteException {
return "Android/OPhone开发讲义";
}
}
@Override
public IBinder onBind(Intent intent) {
return new MyServiceImpl();
}
}
在编写上面代码时要注意如下两点:
IMyService.Stub是根据IMyService.aidl文件自动生成的,一般并不需要管这个类的内容,只需要编写一个继承于IMyService.Stub类的子类(MyServiceImpl类)即可。
onBind方法必须返回MyServiceImpl类的对象实例,否则客户端无法获得服务对象。
(4)在AndroidManifest.xml文件中配置MyService类,代码如下:
Java代码:
<service android:name=".MyService" >
<intent-filter>
<action android:name="net.blogjava.mobile.aidl.IMyService" />
</intent-filter>
</service>
下面来编写客户端的调用代码。首先新建一个Eclipse Android工程(ch08_aidlclient),并将自动生成的IMyService.java文件连同包目录一起复制到ch08_aidlclient工程的src目录中,如图所示。
调用AIDL服务首先要绑定服务,然后才能获得服务对象,代码如下:
Java代码:
package net.blogjava.mobile;
import net.blogjava.mobile.aidl.IMyService;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle; import android.os.IBinder;
import android.view.View; import android.view.View.OnClickListener;
import android.widget.Button; import android.widget.TextView;
public class Main extends Activity implements OnClickListener {
private IMyService myService = null;
private Button btnInvokeAIDLService;
private Button btnBindAIDLService;
private TextView textView;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 获得服务对象
myService = IMyService.Stub.asInterface(service);
btnInvokeAIDLService.setEnabled(true);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btnBindAIDLService:
// 绑定AIDL服务
bindService(new Intent("net.blogjava.mobile.aidl.IMyService"), serviceConnection, Context.BIND_AUTO_CREATE);
break;
case R.id.btnInvokeAIDLService:
try {
textView.setText(myService.getValue());
// 调用服务端的getValue方法
} catch (Exception e) {
}
break;
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnInvokeAIDLService = (Button) findViewById(R.id.btnInvokeAIDLService);
btnBindAIDLService = (Button) findViewById(R.id.btnBindAIDLService); btnInvokeAIDLService.setEnabled(false);
textView = (TextView) findViewById(R.id.textview);
btnInvokeAIDLService.setOnClickListener(this);
btnBindAIDLService.setOnClickListener(this);
}。
⑵ android framework aidl生成文件在哪
建立AIDL服务要比建立普通的服务复杂一些,具体步骤如下:
(1)在Eclipse Android工程的Java包目录中建立一个扩展名为aidl的文件。该文件的语法类似于Java代码,但会稍有不同。详细介绍见实例52的内容。
(2)如果aidl文件的内容是正确的,ADT会自动生成一个Java接口文件(*.java)。
(3)建立一个服务类(Service的子类)。
(4)实现由aidl文件生成的Java接口。
(5)在AndroidManifest.xml文件中配置AIDL服务,尤其要注意的是,<action>标签中android:name的属性值就是客户端要引用该服务的ID,也就是Intent类的参数值。
⑶ 迁移一个eclipse工程到AndroidStudio有哪些坑
首先,我们来看一下把一个eclipse工程迁移到AndroidStudio有几种方法:
方法1:直接导入一个eclipse工程;
方法2:在eclipse中利用ADT为工程生成一个Gradle文件,AndroidStudio导入这个gradle工程;
方法3:在AndroidStudio中新建一个工程,把eclipse工程的代码、资源一点点拷过来;
1
采用哪种方法
先说结论:我采用了方法3,如果你对方法1和方法2的效果不感兴趣,可以跳过这一部分。
方法1的好处是简单,AndroidStudio的早期版本只能用方法2,现在的新版可以支持方法1,直接导入一个eclipse工程,我开始时也是试这种方法的,确实简单,导进来不需要做任何设置居然就能运行,那么问题是什么呢?问题是编译运行一次那叫一个慢呀,比eclipse还慢N倍,而且异常消耗电脑资源,我们Macbook Pro配置不算低,买来一年多风扇从来没响过,以至于我以为电脑根本没有风扇,这下是听到风扇响了,响声那叫一个大,说明这种构建项目的方式极其耗内存耗CPU,并且由于没有gradle文件,Gradle的所有特性全部用不上,我都怀疑这种编译方式用的就是ant,根本没用到gradle。
综上所述,方法1既没有eclipse快,也没有AndroidStudio的好处,看来这种方法不可取。
再来看方法2,方法2是Google官方推荐的方式,操作步骤是:先在eclipse中的工程上点鼠标右键,在弹出的菜单中选择Export...,然后在弹出的窗口中选择Android标签下的Generate Gradle build files,如下图所示:
然后按提示操作就可以在工程目录下生成一个build.gradle文件,之后我们就可以用AndroidStudio导入这个build.gradle文件了,导入的过程中会连同这个工程一齐导入,之后,就会看到导入后的工程了,如图所示:
看到了吧,整个工程还是保持eclipse中的目录结构。
右边是eclipse自动生成的build.gradle文件的内容,跟代码无关。并且只有一个build.gradle文件,没有分全局的gradle和模块的gradle,使用了很旧的Gradle版本,并且使用已经不建议的android插件,之所以工程目录没有使用AndroidStudio默认格式,而可以保持eclipse目录结构,都是因为gradle文件中的那一部分sourceSets下的配置,sourceSets的配置可以允许我们改变工程的目录组织结构,而不需要必须使用AndroidStudio的默认结构,而且build.gradle构建一直不成功。。。也是醉了。
由于存在这么多的疑问,我担心会给将来留坑,并且目录结构都不是AndroidStudio默认,我决定:放弃这种方法,采用方法3:新建一个AndroidStudio工程,把代码和资源一点一点拷过去,使用“纯粹”的AndroidStudio开发方式。
2
采用方法3把工程迁移到AndroidStudio
这种方法的过程也没什么好讲的,就是把java代码和资源文件复制粘贴到新工程的目录下就OK了,先来看一下效果,下图是我迁移完的效果:
怎么样,是不是清爽了许多,目录结构完全是AndroidStudio的格式,首先一个注意的问题就是公司以前的项目是没有用到v7包的,所以在build.gradle中注释掉这个maven引用,以免引起不必要的麻烦。
还有一点就是以前项目中是有jni代码的,但是我们的jni代码目录组织结构比较复杂,不是标准的jni目录,AndroidStudio又不是靠mk文件来配置C代码,所以还没搞定,暂时只是把so包拿过来用,C代码的编译还是在eclipse下进行,将来搞定了我再回来给大家补充。下面把我的修改过程一一讲述一下:
1、注释掉build.gradle中v7包的引用。
这个上面已经说过了,因为项目中以前没用到v7包;
2、迁移AIDL文件。
如果你的项目中没有用到AIDL,那你可以跳过这部分。在eclipse中,aidl文件是跟java文件放在同一个包下的,但是AndroidStudio要求aidl文件默认放在模块下的src/main/aidl文件夹下,并且包名要与以前在java包下的包名、路径相同。
比如以前aidl文件在com.example.mycode包下边,那么你也要在aidl文件夹下建这样一个同名的包,把aidl文件移过去,如果没有aidl文件夹,那就点右键新建一个,效果如下图所示:
--aidl目录没有就新建一个--
--aidl文件的位置摆放--
如果aidl文件摆放不正确,java中引用service的类就会报错,aidl文件默认是放在这里的,当然也可以通过配置build.gradle文件来使它们跟java代码混在一起,但是不建议这样做,我们尽量按照 AndroidStudio的默认配置来做;
3、修改AndroidManifest.xml文件
我在进行完以上步骤后尝试同步gradle配置,结果报了
Execution failed for task ':app:processDebugManifest'.
> Manifest merger failed with multiple errors, see logs
这个错误,如下图所示
--报Manifest merger failed错误--
merger是合并的意思嘛,开始觉得很奇怪,我们工程又没有Library引用,跟谁合并呢,后来想起来build.gradle中引用了v7包,但是把v7包的引用注释掉还是不行,有网友说在manifest中使用tools:replace标签,可能这种方式只适用于Library模块引起的merger冲突,我的很显然不是这种情况;还有网友说在build.gradle的android标签下加入aaptOptions.cruncherEnabled false和aaptOptions.useNewCruncher false,开始时管了点用,后来多试几次又不行,看来也不是这个问题。
后来用了一个笨办法,一点一点注释AndroidManifest.xml中的内容,看看注释掉哪一块可以不报错,结果发现是下图中所示的原因:
--intent-filter标签是一个空标签--
上图中,我的service下配置了intent-filter标签,按理说intent-filter标签下还应该有action子标签,比如像下图这样的标准写法:
--网络定位SDK的写法是标准写法--
所以,我们要做的就是注释掉AndroidManifest.xml中service标签下的空的intent-filter标签,至少我用这种方法处理后就不再报错了,看来AndroidStudio完全是一套新的api,跟以前的开发方式都不一样了;
此外,由于版本号等配置在build.gradle文件中已经有了,所以我们在AndroidManifest.xml文件中要删掉重复的配置;
4、图片资源引用问题
经过以上几步修改后,项目终于可以编译运行了,但是悲剧也发生了,一打开app立马闪退,报的错误是:
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.xxxxx.xx/com.xxxxx.xx.xxxxx.MainActivity}:
android.view.InflateException: Binary XML file line #2: Error
inflating class android.widget.RelativeLayout
报错的地方就在Activity的onCreate方法中的setConentView方法处,什么原因呢?
原因是我们在build.gradle中buildToolsVersion配置的版本过低,我一直在用19.1.0,在这个版本下,要求所有图片必须放在mipmap目录下才能在布局文件中引用,否则就会引起上述Activity闪退,当我把buildToolsVersion的版本改成23.0.2之后就可以引入放在drawable目录下的图片了,如下图所示:
--buildToolsVersion建议用较新版本--
还有的同学说这个错误是因为图片资源不符合规范,有些本来是jpg图片,只是把扩展名改成了png就拿来用,其实这个问题会导致build同步失败,根本就不可能让应用跑起来,关于这个问题,建议批量修改图片资源,把所有的图片都改成png格式,网上有很多修改图片的工具,但是mac操作系统下有一个现成的方法,不需要安装任何第三方软件就可以批量改图片格式,具体操作方法如下:
5、图片资源不规范导致同步gradle失败的解决方法(Mac操作系统)
(1)进入图片目录,按command+A选中所有图片,然后右键菜单选择打开方式->选择“预览”这个应用程序,这个程序是Mac操作系统自带的,如下图所
示:
--用预览打开图片--
(2)打开“预览”之后,点左上角的“显示”,勾选“缩略图”,就可以在预览窗口左侧看到所有图片的缩略图了,如下图所示:
--勾选“缩略图”--
(3)在缩略图区域的空白处点鼠标右键,勾选排序菜单中的“种类”,按种类排序,如下图所示:
--所有图片按种类排序--
然后你就可以看到下图所示的情景:
--假的png图片被找了出来--
(4)将jpg图片重新导出为png图片,方法是在图片上点鼠标右键(如果有多张图片想批量导出的话按住command键点鼠标进行多选,或者直接按command+A全选所有图片),选择“导出为...”, 在弹出的对话框中选择PNG类型,如下图所示
--将图片导出为PNG格式--
这样就可以将不符合规范的图片规范化了。
这里之所以用Mac来讲是因为Windows下图片转换的工具有很多,一抓一大把,但是Mac中这类工具却相对较少,为了让大家少走弯路,分享一下Mac的图片转换方法,其实我也是在网络上找的,忘记哪个网站了,感谢那位朋友的无私分享。
6、jar包和so包应该放在哪?
在eclipse中,so包和jar都是放在lib目录下的,那么在AndroidStudio中是不是这样呢?当然不是的。
(1)首先看jar应该放在哪?jar包应该放在模块下的libs目录下,如图所示:
--jar包的位置--
然后就可以了,因为在新建工程的时候,系统已经在build.gradle中自动为我们配置了jar包的位置,如图所示:
--build.gradle中关于jar包位置的默认配置--
所以我们不需要再配了,直接把jar包拷在libs目录下就可以用;
(2)言归正转,so包应该放在哪呢?AndroidStudio默认的so存放位置是模块下的src/main/jniLibs目录,如图所示:
--so包应该放在jniLibs目录下--
如图所示,so包不能像在eclipse中那样跟jar包放在一起(默认情况下),如果没有jniLibs目录就自己建一个。
其实无论是aidl文件的存放位置,还是so包的存放位置,都是可以通过build.gradle文件修改的,这个不是今天的重点,大家有兴趣可以自行搜索相关资料,我们尽量遵循AndroidStudio的默认方式,以便让别人看到我们的项目时不至于一头雾水。
7、最后就是jni源码的存放位置以及如何配置了。
⑷ 为什么 aidl 总是出现null
建立AIDL服务要比建立普通的服务复杂一些,具体步骤如下:
(1)在Eclipse Android工程的Java包目录中建立一个扩展名为aidl的文件。该文件的语法类似于Java代码,但会稍有不同。详细介绍见实例52的内容。
(2)如果aidl文件的内容是正确的,ADT会自动生成一个Java接口文件(*.java)。
(3)建立一个服务类(Service的子类)。
(4)实现由aidl文件生成的Java接口。
(5)在AndroidManifest.xml文件中配置AIDL服务,尤其要注意的是,<action>标签中android:name的属性值就是客户端要引用该服务的ID,也就是Intent类的参数值。
建立AIDL服务
本例中将建立一个简单的AIDL服务。这个AIDL服务只有一个getValue方法,该方法返回一个String类型的值。在安装完服务后,会在客户端调用这个getValue方法,并将返回值在TextView组件中输出。建立这个AIDL服务的步骤如下:
(1)建立一个aidl文件。在Java包目录中建立一个IMyService.aidl文件。IMyService.aidl文件的位置如图
IMyService.aidl文件的内容如下:
Java代码:
package eoe.demo;
interface IMyService {
String getValue();
}
IMyService.aidl文件的内容与Java代码非常相似,但要注意,不能加修饰符(例如,public、private)、AIDL服务不支持的数据类型(例如,InputStream、OutputStream)等内容。
(2)如果IMyService.aidl文件中的内容输入正确,ADT会自动生成一个IMyService.java文件。读者一般并不需要关心这个文件的具体内容,也不需要维护这个文件。关于该文件的具体内容,读者可以查看本节提供的源代码。
(3)编写一个MyService类。MyService是Service的子类,在MyService类中定义了一个内嵌类(MyServiceImpl),该类是IMyService.Stub的子类。MyService类的代码如下:
Java代码:
package eoe.demo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class MyService extends Service {
public class MyServiceImpl extends IMyService.Stub {
@Override
public String getValue() throws RemoteException {
return "Android/OPhone开发讲义";
}
}
@Override
public IBinder onBind(Intent intent) {
return new MyServiceImpl();
}
}
在编写上面代码时要注意如下两点:
IMyService.Stub是根据IMyService.aidl文件自动生成的,一般并不需要管这个类的内容,只需要编写一个继承于IMyService.Stub类的子类(MyServiceImpl类)即可。
onBind方法必须返回MyServiceImpl类的对象实例,否则客户端无法获得服务对象。
(4)在AndroidManifest.xml文件中配置MyService类,代码如下:
Java代码:
<service android:name=".MyService" >
<intent-filter>
<action android:name="net.blogjava.mobile.aidl.IMyService" />
</intent-filter>
</service>
下面来编写客户端的调用代码。首先新建一个Eclipse Android工程(ch08_aidlclient),并将自动生成的IMyService.java文件连同包目录一起复制到ch08_aidlclient工程的src目录中,如图所示。
调用AIDL服务首先要绑定服务,然后才能获得服务对象,代码如下:
Java代码:
package net.blogjava.mobile;
import net.blogjava.mobile.aidl.IMyService;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle; import android.os.IBinder;
import android.view.View; import android.view.View.OnClickListener;
import android.widget.Button; import android.widget.TextView;
public class Main extends Activity implements OnClickListener {
private IMyService myService = null;
private Button btnInvokeAIDLService;
private Button btnBindAIDLService;
private TextView textView;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 获得服务对象
myService = IMyService.Stub.asInterface(service);
btnInvokeAIDLService.setEnabled(true);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btnBindAIDLService:
// 绑定AIDL服务
bindService(new Intent("net.blogjava.mobile.aidl.IMyService"), serviceConnection, Context.BIND_AUTO_CREATE);
break;
case R.id.btnInvokeAIDLService:
try {
textView.setText(myService.getValue());
// 调用服务端的getValue方法
} catch (Exception e) {
}
break;
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnInvokeAIDLService = (Button) findViewById(R.id.btnInvokeAIDLService);
btnBindAIDLService = (Button) findViewById(R.id.btnBindAIDLService); btnInvokeAIDLService.setEnabled(false);
textView = (TextView) findViewById(R.id.textview);
btnInvokeAIDLService.setOnClickListener(this);
btnBindAIDLService.setOnClickListener(this);
}
}
转载仅供参考,版权属于原作者。祝你愉快,满意请采纳哦
⑸ 怎么将android加入eclipse
具体来说,有两种方式。
第一种:在你创建android project 的时候在选择
Create project from existing source 按后选
Browse 在你的电脑里面找到要引入的代码。
第二种:可以建立一个Applocation name
Package name
Create Activity
还有 android版本相同的项目
建立以后,点右键选择Import 再选File System
找到要引入的项目,把里面的东西都引入进来就可以了。
学习android的源码,比如Browser(浏览器)、Mms(彩信/短信)、Phone(电话)、Contacts(联系人)在eclipse里可能会有错误,原因可能有下边几个:
1、使用到了未包括在SDK中(公开发布)的API,有两种情况:
a 被 @hide 标注了的类:这 些类是被隐藏起来的,这些类大多都在com.android.internal包下面;
b 一些未包括在SDK中的、Google私有的Api,它们大多都在com.google.android包下面
2、使用了一些由framework层声明的aidl接口访问系统服务,然而这些aidl在编译时才会转换成.java源码,因此在SDK环境下编译这些应用时无法访问到它们。
解决方法是:
(请注意:out目录 是在完整源码编译环境下(Linux下),执行一次完整编译后的输出目录)
1、找到那些被隐藏起来的类、它们在以下两个位置:
A、out argetcommonobjJAVA_LIBRARIESframework_intermediates/ classes.jar ;
B、out argetcommonobjJAVA_LIBRARIESandroid-common_intermediates classes.jar ;
将找到的.jar文件,在Eclipse中作为User Library 添加到 Project 的Librarys依赖中,并将该库的顺序置于Android SDK Library之上。
在 out argetcommonobjJAVA_LIBRARIES 目录下,还有很多其它具体应用相关的jar包,.... ;
2、找到那些缺失的、编译时才生成的,.java源文件,它们通常在以下位置:
A、 out argetcommonobjJAVA_LIBRARIESXXX _intermediatessrc 目录下,XXX是相关模块的名称;
将找到的src目录,在Eclipse下,以Link Source的方式,连接到Project 中作为源码的一部分。
⑹ android 如何让两个apk相互通信
A.apk,B.apk都是我写的.现在我想在B.apk里实现获得A.apk的某控件ID,并向其发送一个按键事件.如何实现,谢谢!也就是用B控制A.
这两个apk 是在两个进程里的,(或许可以配置成一个进程。不过如何直接操作这个没有试过。)
所以一般的有两种方法:
1、RPC
2、通过 BroadcastRecever 或 Service
第二种方法比较简单一些。
比如B 控制 A的话,
A定义Service ,比如com.my.ServerA .自定义actionFilter “com.my.serverA.action"
B中调用Intent it = newIntent("com.my.serverA.action");
it.putExtra(....);// 传递你的自定义控制指令。
B.startService(it);
在A中ServerA的 onStartService(Intent it) 。解析这个控制指令,做相应操作就可以了。
用BroadcastRecever 的道理一样。
Aidl,android平台的IPC方式之一,基于系统的Ibinder机制。
网上大多数例子都是在一个apk下来测试调用service,现在我在两个project下面来调用。
一个是server project,一个是client project
首先我们建立的是server project,这里面要实现aidl文件和一个service,activity只是用来启动service的,当然,你也可以通过发广播的形式来启动service。
首先看IAidlService.aidl文件:
Java代码
package com.ds.server;
interface IAidlService {
int getType();
}
这样在eclipse里面自动编译的时候会在gen下面生成IAidlService.java文件(灯下我们的client project要用)。
然后新建一个service,这个service里面has a IAidlService的stub对象,service具体代码如下:
Java代码
package com.ds.server;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class AidlService extends Service {
private IAidlService.Stub mBinder = new IAidlService.Stub() {
@Override
public int getType() throws RemoteException {
// TODO Auto-generated method stub
return 5;
}
};
private void Log(String str) {
Log.d("AidlService", "------ " + str + "------");
}
@Override
public void onCreate() {
Log("service create");
}
@Override
public void onStart(Intent intent, int startId) {
Log("service start id=" + startId);
}
@Override
public IBinder onBind(Intent t) {
Log("service on bind");
return mBinder;
}
@Override
public void onDestroy() {
Log("service on destroy");
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
Log("service on unbind");
return super.onUnbind(intent);
}
public void onRebind(Intent intent) {
Log("service on rebind");
super.onRebind(intent);
}
}
这里一定要实现onBind方法,并返回一个IAidlService.Stub对象。
再去AndroidManifest.xml注册这个service:
Xml代码
<service
android:name=".AidlService"
android:enabled="true"
android:process=":remote" >
<intent-filter>
<action android:name="com.ds.server.IAidlService" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
android:enabled="true"
android:process=":remote"这两个标签可有可无。
只要注册了这个service就行。
好了,到此,服务端已经完成。
-------------------华丽的分割线-----------------------------------------
下面我们开始client project。
client project比较简单,需要注意的地方是,首先需要把server project中gen文件夹中aidl生成的那个IAidlService.java类以及包都拷贝到我们的client project中。
(注意:client project的包名为com.ds.client;另外一个包名com.ds.server以及这个server包下面的IAidlService.java类都是从server project的gen文件夹拷贝过来的,至于gen文件夹的其他文件就不需要拷贝过来。)。
好了,这样的话,client project只要从activity去远程调用service就好了,实现代码如下:
Java代码
package com.ds.client;
import com.ds.server.IAidlService;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class AidlClientActivity extends Activity {
IAidlService iservice;
private ServiceConnection connection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
// 从远程service中获得AIDL实例化对象
iservice = IAidlService.Stub.asInterface(service);
Log.i("Client","Bind Success:" + iservice);
}
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
iservice = null;
Log.i("Client","onServiceDisconnected");
}
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final TextView tv = (TextView) findViewById(R.id.tv);
Button bt = (Button) findViewById(R.id.bt);
bt.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent service = new Intent(IAidlService.class.getName());
bindService(service, connection, BIND_AUTO_CREATE);
if (iservice != null) {
try {
tv.setText("" + iservice.getType());
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
});
}
}
注意几点:
1,import com.ds.server.IAidlService;使用的是我们拷贝过来的IAidlService.java类
2,需要一个ServiceConnection对象
3,通过Intent service = new Intent(IAidlService.class.getName());
bindService(service, connection, BIND_AUTO_CREATE);来bind service。这样就可以调用aidl中定义的接口来获取service中的值了。
唉,由于在使用中没有注意拷贝server project中gen文件夹下面的包和IAidlService.java,老是出现Unable to start service Intent这样的错误。搞了好久。
附件是源码。注意使用的时候,先要运行server project,启动服务,然后再运行client project。