Android Studio下使用AIDL创建和使用远程service
2016-07-05 18:34
429 查看
各位读者朋友们大家好,好久没来更新博客了,今天心血来潮来写一篇关于如何在AS下结合AIDL创建和使用远程service。在此之前我先跟大家解释下什么是远程service?以及为什么要使用远程service?相信不管对于安卓新手还是老手而言,对于service并不感到陌生,所以这里就不跟讨论其基础概念和一些知识点了。所谓的远程service意思其实就是提供一个独立于某个app进程而创建的服务,这个服务可以提供给多个app共同使用,当然了,这些app必须拥有访问这个远程service的某种协议或者说接口,而这正是我们今天博文的另一个重点,就是AIDL,所谓的AIDL其实就是安卓接口定义语言,在本篇当中,它将用于提供一个我们访问远程service的一个接口。如果我的表述不是很清楚或者你完全听不懂,那么没关系,我们通过代码和截图一步步帮你搞懂我在本篇所要表达的内容,相信你能明白,因为本篇的内容很简单。
一、"服务端"项目
按照国际惯例,我们先来打开Android Studio并创建一个项目,项目名称随你定,这里我就不演示了。然后在项目中创建一个service。下面我会贴出这个service的截图和代码:
可以发现,这个自定义的service类中并没有什么特别的东西,都是些重写的方法,当我们调用bindService方法时,就会调用onBind方法了,我们后面会通过logcat来跟踪。我们往下继续。。。。
接下来,我们为了让这个service变为远程的service,需要在AndroidManifest.xml文件中注册并加一个:reomote标识,具体代码如下:
然后,我们来开始本篇的重点,我们那就是使用AIDL来实现我们远程service的使用,我们首先在AS下来创建一个AIDL文件,右键app,然后new一个aidl文件,如下图:
然后输入文件名,点击finish完成创建。请注意这里的AIDL文件所在的路径(包名)要跟项目的包名保持一致。
下面我把我创建出来的AIDL文件代码也贴出来,其实很简单,因为我只写了一个sayHelloWorld方法而已:
然后点击Bulid->Make project生成我们的java文件。
这时你会发现我们已经可以调用这个接口并实现它的方法了。接下请注意,我们为了让其他app能够找到我们共享的远程service,需要在服务中加入intent-filter标识,并指定我们的AIDL文件路径。也就是说AndroidManifest.xml文件中的注册代码部分将变为如下:
最后,我们完善下MyService这个类,实现sayHelloWorld方法,并在onBind方法中返回实现了这个方法的binder:
二、“客户端”项目
接下来,我们就可以来新建一个项目了,在这个项目中我们将访问我们上面“服务端”项目的MyService,也就是实现远程service的访问。
同样的,项目名由你来定,然后我们接下来要做的就是把我们编译生成的那个AIDL java文件拷贝到我们的这个新项目中,如何找到这个文件呢?其实不难,在“服务端”项目中,我们切换到package模式下就能找到。
接着将我们的IMyAidlService文件拷贝到我们的新项目即“客户端”项目中,注意这里文件的存放路径要跟“服务端”项目的存放路径一致,也就是“客户端”IMyAidlService的包名要跟服务端存放的包名相同,如下图:
好了,接下来我们“客户端”项目中新建一个Activity,在MainActivity中,我们将演示远程访问“服务端”项目的service,下面直接贴出这个MainActivity的代码:
好了,接下来我们运行一下我们这个新建的“客户端”项目。
点击一下绑定按钮,按钮布局我没给出,自己拖一个,我们主要在logcat中看下运行效果图。
看看上图,你会发现不仅打印出了Hello World,而且还调用了onBind方法,也就是说已经访问到了我们那个远程service了。哈哈,是不是很神奇。那么我们本篇的内容到此为止也就结束了,有错误或遗漏之处还请广大读者指出,谢谢大家的阅读!咱们下期见!
一、"服务端"项目
按照国际惯例,我们先来打开Android Studio并创建一个项目,项目名称随你定,这里我就不演示了。然后在项目中创建一个service。下面我会贴出这个service的截图和代码:
public class MyService extends Service { @Override public void onCreate() { super.onCreate(); Log.i("mylog", "onCreate"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("mylog","onStartCommand"); return super.onStartCommand(intent, flags, startId); } @Nullable @Override public IBinder onBind(Intent intent) { Log.i("mylog","onTestBind"); return null; } @Override public boolean onUnbind(Intent intent) { Log.i("mylog","unBind"); return super.onUnbind(intent); } @Override public void onDestroy() { Log.i("mylog","onDestroy"); super.onDestroy(); }
可以发现,这个自定义的service类中并没有什么特别的东西,都是些重写的方法,当我们调用bindService方法时,就会调用onBind方法了,我们后面会通过logcat来跟踪。我们往下继续。。。。
接下来,我们为了让这个service变为远程的service,需要在AndroidManifest.xml文件中注册并加一个:reomote标识,具体代码如下:
<service android:name=".service.MyService" android:process=":remote"> </service>
然后,我们来开始本篇的重点,我们那就是使用AIDL来实现我们远程service的使用,我们首先在AS下来创建一个AIDL文件,右键app,然后new一个aidl文件,如下图:
然后输入文件名,点击finish完成创建。请注意这里的AIDL文件所在的路径(包名)要跟项目的包名保持一致。
下面我把我创建出来的AIDL文件代码也贴出来,其实很简单,因为我只写了一个sayHelloWorld方法而已:
// IMyAidlService.aidl package com.example.marktrace003.test; // Declare any non-default types here with import statements interface IMyAidlService { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); void sayHelloWorld(); }
然后点击Bulid->Make project生成我们的java文件。
这时你会发现我们已经可以调用这个接口并实现它的方法了。接下请注意,我们为了让其他app能够找到我们共享的远程service,需要在服务中加入intent-filter标识,并指定我们的AIDL文件路径。也就是说AndroidManifest.xml文件中的注册代码部分将变为如下:
<service android:name=".service.MyService" android:process=":remote"> <intent-filter> <action android:name="com.example.marktrace003.test.IMyAidlService"/> </intent-filter> </service>
最后,我们完善下MyService这个类,实现sayHelloWorld方法,并在onBind方法中返回实现了这个方法的binder:
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.marktrace003.test.IMyAidlService; /** * Created by Marktrace003 on 2016/7/4. */ public class MyService extends Service { @Override public void onCreate() { super.onCreate(); Log.i("mylog", "onCreate"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("mylog","onStartCommand"); return super.onStartCommand(intent, flags, startId); } @Nullable @Override public IBinder onBind(Intent intent) { Log.i("mylog","onTestBind"); return binder; } IMyAidlService.Stub binder = new IMyAidlService.Stub() { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } @Override public void sayHelloWorld() throws RemoteException { Log.i("mylog","Hello World"); } }; @Override public boolean onUnbind(Intent intent) { Log.i("mylog","unBind"); return super.onUnbind(intent); } @Override public void onDestroy() { Log.i("mylog","onDestroy"); super.onDestroy(); } }
二、“客户端”项目
接下来,我们就可以来新建一个项目了,在这个项目中我们将访问我们上面“服务端”项目的MyService,也就是实现远程service的访问。
同样的,项目名由你来定,然后我们接下来要做的就是把我们编译生成的那个AIDL java文件拷贝到我们的这个新项目中,如何找到这个文件呢?其实不难,在“服务端”项目中,我们切换到package模式下就能找到。
接着将我们的IMyAidlService文件拷贝到我们的新项目即“客户端”项目中,注意这里文件的存放路径要跟“服务端”项目的存放路径一致,也就是“客户端”IMyAidlService的包名要跟服务端存放的包名相同,如下图:
好了,接下来我们“客户端”项目中新建一个Activity,在MainActivity中,我们将演示远程访问“服务端”项目的service,下面直接贴出这个MainActivity的代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private Button bind_btn; private IMyAidlService iMyAidlService; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { iMyAidlService = IMyAidlService.Stub.asInterface(iBinder); try { iMyAidlService.sayHelloWorld(); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName componentName) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bind_btn = (Button)findViewById(R.id.bind_btn); bind_btn.setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()){ case R.id.bind_btn: Intent intent = new Intent("com.example.marktrace003.test.IMyAidlService"); intent.setPackage("com.example.marktrace003.test"); //Android5.0之后需要指定共享Service所在应用的应用包名,否则会抛异常 bindService(intent,connection,BIND_AUTO_CREATE); break; } } }说明一下,由于我们已经导入了AIDL文件,所以我们直接可以使用这个接口,然后我们一开始定义ServiceConnection,当bindService时,我们传入这个connection,触发onServiceConnected方法,然后调用sayHelloWorld方法。请注意,我们这里的Intent所传入的这个action正是我们在前面“服务端”项目中的AndroidManifest.xml文件中注册service时加入的那个action,也正是因为这样我们才能顺利的找到这个远程的service。那么这里还有一点需要说明的是,Google认为隐式调用这种调用方式不安全,由于Android5.0中已经禁用Intent隐式调用,所以采用隐式调用会抛出异常,那么为了保证我们的程序不会抛出异常,需要在这里指定一下包名,而包名自然就是我们“服务端”项目的那个包名了。
好了,接下来我们运行一下我们这个新建的“客户端”项目。
点击一下绑定按钮,按钮布局我没给出,自己拖一个,我们主要在logcat中看下运行效果图。
看看上图,你会发现不仅打印出了Hello World,而且还调用了onBind方法,也就是说已经访问到了我们那个远程service了。哈哈,是不是很神奇。那么我们本篇的内容到此为止也就结束了,有错误或遗漏之处还请广大读者指出,谢谢大家的阅读!咱们下期见!
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories