http://blog.csdn.net/guolin_blog/article/details/9797169

http://www.jianshu.com/p/eeb2bd59853f

将一个普通的Service转换成远程Service其实非常简单,只需要在注册Service的时候将它的android:process属性指定成:remote就可以了,代码如下所示:

  1. <service android:name=".AIDLService"
  2. android:process=":remote"></service>

远程service可以让service在另一个进程运行,所以可以执行阻塞进程的操作

远程Service这么好用,干脆以后我们把所有的Service都转换成远程Service吧,还省得再开启线程了。其实不然,远程Service非但不好用,甚至可以称得上是较为难用。一般情况下如果可以不使用远程Service,就尽量不要使用它。

下面就来看一下它的弊端吧,首先将MyService的onCreate()方法中让线程睡眠的代码去除掉,然后重新运行程序,并点击一下Bind Service按钮,你会发现程序崩溃了!为什么点击Start Service按钮程序就不会崩溃,而点击Bind Service按钮就会崩溃呢?这是由于在Bind Service按钮的点击事件里面我们会让MainActivity和MyService建立关联,但是目前MyService已经是一个远程Service了,Activity和Service运行在两个不同的进程当中,这时就不能再使用传统的建立关联的方式,程序也就崩溃了。

那么如何才能让Activity与一个远程Service建立关联呢?这就要使用AIDL来进行跨进程通信了(IPC)。

调用者和Service如果不在一个进程内, 就需要使用android中的远程Service调用机制.
android使用AIDL定义进程间的通信接口. AIDL的语法与java接口类似, 需要注意以下几点:

    1. AIDL文件必须以.aidl作为后缀名.
    2. AIDL接口中用到的数据类型, 除了基本类型, String, List, Map, CharSequence之外, 其他类型都需要导包, 即使两种在同一个包内. List和Map中的元素类型必须是AIDL支持的类型.
    3. 接口名需要和文件名相同.
    4. 方法的参数或返回值是自定义类型时, 该自定义的类型必须实现了Parcelable接口.
    5. 所有非java基本类型参数都需要加上in, out, inout标记, 以表明参数是输入参数, 输出参数, 还是输入输出参数.
    6. 接口和方法前不能使用访问修饰符和static, final等修饰.

AIDL实现
1.首先我建立2个app工程,通过aidl实现一个app调用另一个app的service
目录结构如下:
service提供端app

利用aidl调用service的app

2.在两个app中都建立一个文件 IPerson.aidl注意 包名 要相同
IPerson.aidl只是一个接口文件,用来aidl交互的,建立好之后在Studio中点Build-->Rebuild会自动创建需要的java文件。

IPerson.aidl代码

  1. package mangues.com.aidl;
  2. interface IPerson {
  3. String greet(String someone);
  4. }

3.在aidl_service 中建立AIDLService
这个IPerson.Stub 就是通过IPerson.aidl 自动生成的binder 文件,你实现下,然后在onBind()中 return出去就好了,就和Android Service实现和activity交互一样。
代码:

  1. public class AIDLService extends Service {
  2. private static final String TAG = "AIDLService";
  3.  
  4. IPerson.Stub stub = new IPerson.Stub() {
  5. @Override
  6. public String greet(String someone) throws RemoteException {
  7. Log.i(TAG, "greet() called");
  8. return "hello, " + someone;
  9. }
  10. };
  11.  
  12. @Override
  13. public void onCreate() {
  14. super.onCreate();
  15. Log.i(TAG, "onCreate() called");
  16. }
  17.  
  18. @Override
  19. public int onStartCommand(Intent intent, int flags, int startId) {
  20. Log.i(TAG, "onBind() onStartCommand");
  21. return super.onStartCommand(intent, flags, startId);
  22.  
  23. }
  24.  
  25. @Override
  26. public IBinder onBind(Intent intent) {
  27. Log.i(TAG, "onBind() called");
  28. return stub;
  29. }
  30.  
  31. @Override
  32. public boolean onUnbind(Intent intent) {
  33. Log.i(TAG, "onUnbind() called");
  34. return true;
  35. }
  36.  
  37. @Override
  38. public void onDestroy() {
  39. super.onDestroy();
  40. Log.i(TAG, "onDestroy() called");
  41. }
  42. }

这里为什么可以这样写呢?因为Stub其实就是Binder的子类,所以在onBind()方法中可以直接返回Stub的实现。

4.aidl_service MainActivity 中启动这个service
简单点就不写关闭什么的了;

  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3. super.onCreate(savedInstanceState);
  4. setContentView(R.layout.activity_main);
  5. Intent startIntent = new Intent(this, AIDLService.class);
  6. startService(startIntent);
  7. }

在AndroidManifest.xml注册

  1. <service android:name=".AIDLService"
  2. android:process=":remote">
  3. <intent-filter>
  4. <action android:name="android.intent.action.AIDLService" />
  5. <category android:name="android.intent.category.DEFAULT" />
  6. </intent-filter>
  7. </service>

作用就是把这个service暴露出去,让别的APP可以利用
android.intent.action.AIDLService 字段隐形绑定这个service,获取数据。

5.aidl_client 中绑定aidl_service service 获取数据
代码:

  1. public class MainActivity extends AppCompatActivity {
  2. private IPerson person;
  3. private ServiceConnection conn = new ServiceConnection() {
  4. @Override
  5. public void onServiceConnected(ComponentName name, IBinder service) {
  6. Log.i("ServiceConnection", "onServiceConnected() called");
  7. person = IPerson.Stub.asInterface(service);
  8. String retVal = null;
  9. try {
  10. retVal = person.greet("scott");
  11. } catch (RemoteException e) {
  12. e.printStackTrace();
  13. }
  14. Toast.makeText(MainActivity.this, retVal, Toast.LENGTH_SHORT).show();
  15. }
  16.  
  17. @Override
  18. public void onServiceDisconnected(ComponentName name) {
  19. //This is called when the connection with the service has been unexpectedly disconnected,
  20. //that is, its process crashed. Because it is running in our same process, we should never see this happen.
  21. Log.i("ServiceConnection", "onServiceDisconnected() called");
  22. }
  23. };
  24. @Override
  25. protected void onCreate(Bundle savedInstanceState) {
  26. super.onCreate(savedInstanceState);
  27. setContentView(R.layout.activity_main);
  28. Intent mIntent = new Intent();
  29. mIntent.setAction("android.intent.action.AIDLService");
  30. Intent eintent = new Intent(getExplicitIntent(this,mIntent));
  31. bindService(eintent, conn, Context.BIND_AUTO_CREATE);
  32. }
  33. public static Intent getExplicitIntent(Context context, Intent implicitIntent) {
  34. // Retrieve all services that can match the given intent
  35. PackageManager pm = context.getPackageManager();
  36. List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);
  37. // Make sure only one match was found
  38. if (resolveInfo == null || resolveInfo.size() != 1) {
  39. return null;
  40. }
  41. // Get component info and create ComponentName
  42. ResolveInfo serviceInfo = resolveInfo.get(0);
  43. String packageName = serviceInfo.serviceInfo.packageName;
  44. String className = serviceInfo.serviceInfo.name;
  45. ComponentName component = new ComponentName(packageName, className);
  46. // Create a new intent. Use the old one for extras and such reuse
  47. Intent explicitIntent = new Intent(implicitIntent);
  48. // Set the component to be explicit
  49. explicitIntent.setComponent(component);
  50. return explicitIntent;
  51. }
  52. }

在上一篇文章中我们已经知道,如果想要让Activity与Service之间建立关联,需要调用bindService()方法,并将Intent作为参数传递进去,在Intent里指定好要绑定的Service,示例代码如下:

  1. Intent bindIntent = new Intent(this, MyService.class);
  2. bindService(bindIntent, connection, BIND_AUTO_CREATE);

这里在构建Intent的时候是使用MyService.class来指定要绑定哪一个Service的,但是在另一个应用程序中去绑定Service的时候并没有MyService这个类,这时就必须使用到隐式Intent了

  1. <intent-filter>
  2. <action android:name="com.example.servicetest.MyAIDLService"/>
  3. </intent-filter>

这就说明,MyService可以响应带有com.example.servicetest.MyAIDLService这个action的Intent。

Android-远程Service的更多相关文章

  1. 一个简单的demo学习Android远程Service(AIDL的使用)

    这是milo很早之前写在论坛上的一个帖子,现在整理出来,milo也复习一下一般来说Android 的四大组件都是运行在同一个进程中的,但远程Service运行在不同的进程里.这进程间的通信是使用了An ...

  2. android 远程Service以及AIDL的跨进程通信

    在Android中,Service是运行在主线程中的,如果在Service中处理一些耗时的操作,就会导致程序出现ANR. 但如果将本地的Service转换成一个远程的Service,就不会出现这样的问 ...

  3. Android Activity与远程Service的通信学习总结

    当一个Service在androidManifest中被声明为 process=":remote", 或者是还有一个应用程序中的Service时,即为远程Service, 远程的意 ...

  4. Android服务(Service)研究

    Service是android四大组件之一,没有用户界面,一直在后台运行. 为什么使用Service启动新线程执行耗时任务,而不直接在Activity中启动一个子线程处理? 1.Activity会被用 ...

  5. 【Android 】Service 全面总结

    1.Service的种类 按运行地点分类: 类别 区别  优点 缺点   应用 本地服务(Local) 该服务依附在主进程上,  服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外L ...

  6. 【Android 界面效果34】Android里Service的bindService()和startService()混合使用深入分析

    .先讲讲怎么使用bindService()绑定服务 应用组件(客户端)可以调用bindService()绑定到一个service.Android系统之后调用service的onBind()方法,它返回 ...

  7. Android服务Service总结

    转自 http://blog.csdn.net/liuhe688/article/details/6874378 富貴必從勤苦得,男兒須讀五車書.唐.杜甫<柏學士茅屋> 作为程序员的我们, ...

  8. 本地/远程Service 和Activity 的交方式(转)

    android SDK提供了Service,用于类似*nix守护进程或者windows的服务. Service有两种类型: 本地服务(Local Service):用于应用程序内部 远程服务(Remo ...

  9. android服务Service(上)- IntentService

    Android学习笔记(五一):服务Service(上)- IntentService 对于需要长期运行,例如播放音乐.长期和服务器的连接,即使已不是屏幕当前的activity仍需要运行的情况,采用服 ...

  10. Android:Service

    Android Service: http://www.apkbus.com/android-15649-1-1.html android service 的各种用法(IPC.AIDL): http: ...

随机推荐

  1. Ubuntu修改apt-get源

    1.背景 服务器上安装了最新的Ubuntu Server 17.04,代号为zesty.使用apt-get命令安装软件时,有时候速度比较慢,有时候会失败.因此考虑用国内的镜像源更换下apt-get的默 ...

  2. 一分钟学会git

    首先 克隆 源码地址 git clone git://github.com/jquery/jquery.git 更新 git pull查看状态 git status暂存所有(注意 . 表示全部暂存) ...

  3. [宁波集训]0827Day1

    1.\(CF771D\ Bear\ and\ Company\)(原题,比赛时改为多组数据) 一道毒瘤\(dp\)题,\(dp[i][j][k][0/1]\)表示有\(i\)个\(V\),有\(j\) ...

  4. C#6.0语言规范(六) 转换

    转换能够被视为是一个特定类型的表达式.转换可能会导致给定类型的表达式被视为具有不同的类型,或者它可能导致没有类型的表达式获取类型.转换可以是隐式或显式的,这决定了是否需要显式转换.例如,从类型int到 ...

  5. vue项目经验:图形验证码接口get请求处理

    一般图形验证码处理: 直接把img标签的src指向这个接口,然后在img上绑定点击事件,点击的时候更改src的地址(在原来的接口地址后面加上随机数即可,避免缓存) <img :src=" ...

  6. linux上安装redis4.0.9

    redis安装从3.0的版本到现在4.0的版本,现在装一个4.0的版本供大家学习使用. 先yum安装gcc yum -y install gcc 已加载插件:fastestmirror, langpa ...

  7. 一步步Cobol 400 上手自学入门教程03 - 数据部

    数据部的作用 程序中涉及到的全部数据(输入.输出.中间)都要在此定义,对它们的属性进行说明.主要描述以下属性: 数据类型(数值/字符)和存储形式(长度) 数据项之间的关系(层次和层号) 文件与记录的关 ...

  8. odoo开发基础--模型之基本字段类型

    定义模型的时候,和python的其他框架类似,可以对比Django,同样是一个模型即:一个class对应生成数据库中的一张表, 只是odoo的继承机制比较复杂一点,在日常的开发中,定义模型的时候, 基 ...

  9. Oracle EXPDP/IMPDP示例

    待整理: 参考DAVE博客 http://blog.csdn.net/tianlesoftware/article/details/6260138

  10. 课程一(Neural Networks and Deep Learning),第三周(Shallow neural networks)—— 3.Programming Assignment : Planar data classification with a hidden layer

    Planar data classification with a hidden layer Welcome to the second programming exercise of the dee ...