Android-远程Service

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

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

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

<service android:name=".AIDLService"
        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代码

package mangues.com.aidl;
interface IPerson {
  String greet(String someone);
}

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

public class AIDLService extends Service {
  private static final String TAG = "AIDLService";

  IPerson.Stub stub = new IPerson.Stub() {
      @Override
      public String greet(String someone) throws RemoteException {
          Log.i(TAG, "greet() called");
          return "hello, " + someone;
      }
  };

  @Override
  public void onCreate() {
      super.onCreate();
      Log.i(TAG, "onCreate() called");
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
      Log.i(TAG, "onBind() onStartCommand");
      return super.onStartCommand(intent, flags, startId);

  }

  @Override
  public IBinder onBind(Intent intent) {
      Log.i(TAG, "onBind() called");
      return stub;
  }

  @Override
  public boolean onUnbind(Intent intent) {
      Log.i(TAG, "onUnbind() called");
      return true;
  }

  @Override
  public void onDestroy() {
      super.onDestroy();
      Log.i(TAG, "onDestroy() called");
  }
}

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

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

@Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      Intent startIntent = new Intent(this, AIDLService.class);
      startService(startIntent);
  }

在AndroidManifest.xml注册

<service android:name=".AIDLService"
               android:process=":remote">
          <intent-filter>
              <action android:name="android.intent.action.AIDLService" />
              <category android:name="android.intent.category.DEFAULT" />
          </intent-filter>
      </service>

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

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

public class MainActivity extends AppCompatActivity {
    private IPerson person;
    private ServiceConnection conn = new ServiceConnection() {
       @Override
      public void onServiceConnected(ComponentName name, IBinder service) {
          Log.i("ServiceConnection", "onServiceConnected() called");
          person = IPerson.Stub.asInterface(service);
          String retVal = null;
          try {
              retVal = person.greet("scott");
          } catch (RemoteException e) {
              e.printStackTrace();
          }
          Toast.makeText(MainActivity.this, retVal, Toast.LENGTH_SHORT).show();
      }

      @Override
      public void onServiceDisconnected(ComponentName name) {
          //This is called when the connection with the service has been unexpectedly disconnected,
          //that is, its process crashed. Because it is running in our same process, we should never see this happen.
          Log.i("ServiceConnection", "onServiceDisconnected() called");
      }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      Intent mIntent = new Intent();
      mIntent.setAction("android.intent.action.AIDLService");
      Intent eintent = new Intent(getExplicitIntent(this,mIntent));
      bindService(eintent, conn, Context.BIND_AUTO_CREATE);
  }
  public static Intent getExplicitIntent(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;
  }
}

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

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

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

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

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

时间: 2024-10-13 02:30:25

Android-远程Service的相关文章

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

在Android中,Service是运行在主线程中的,如果在Service中处理一些耗时的操作,就会导致程序出现ANR. 但如果将本地的Service转换成一个远程的Service,就不会出现这样的问题了. 转换成远程Service非常简单,只需要在注册Service的时候将他的android:process的属性制定成 :remote就可以了. 重新运行项目,你会发现,不会出现ANR了. 为什么将MyService转换成远程Service后就不会导致程序ANR了呢?这是由于,使用了远程Serv

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

当一个Service在androidManifest中被声明为 process=":remote", 或者是还有一个应用程序中的Service时,即为远程Service, 远程的意思是和当前程序不在同一个进程中执行. Activity和远程Service的跨进程通信(IPC)通过Binder机制,使用AIDL服务实现. 一.  定义远程服务端 1.新建一个project,project文件夹例如以下 2. 文件内容 aidl传递复杂对象时,须要该对象实现Parcelable或Seria

Android通过Service调用远程接口—AIDL-进程间通信

在Andorid平台中,各个组件运行在自己的进程中,他们之间是不能相互访问的,但是在程序之间是不可避免的要传递一些对象,在进程之间相互通信.为了实现进程之间的相互通信,Andorid采用了一种轻量级的实现方式RPC(Remote Procedure Call 远程进程调用)来完成进程之间的通信,并且Android通过接口定义语言(Andorid Interface Definition Language ,AIDL)来生成两个进程之间相互访问的代码,例如,你在Activity里的代码需要访问Se

Android Web Service学习总结(一)

最近学习android平台调用webWebService,学习了一篇不错的博客(http://blog.csdn.net/lyq8479/article/details/6428288),可惜是2011年时的方法,而不适合现在android4.0之后的android版本,所以通过一番学习和研究,总结如下. web Service简介 通俗的理解:通过使用WebService,我们能够像调用本地方法一样去调用远程服务器上的方法.我们并不需要关心远程的那个方法是Java写的,还是PHP或C#写的:我

android的service

package com.service.service; import com.example.service.R; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.B

016_03浅谈远程Service和AIDL

 如果需要访问不同进程间service中的数据或者方法,需要使用AIDL(android interface description language)工具,可以通过如下方法: public boolean bindService(Intent intent, ServiceConnection conn, int flags) :         public void unbindService(ServiceConnection conn); intent是跳转到service的inten

Android服务Service总结

转自 http://blog.csdn.net/liuhe688/article/details/6874378 富貴必從勤苦得,男兒須讀五車書.唐.杜甫<柏學士茅屋> 作为程序员的我们,须知富贵是要通过勤苦努力才能得到的,要想在行业内有所建树,就必须刻苦学习和钻研. 今天我们来讲一下Android中Service的相关内容. Service在Android中和Activity是属于同一级别上的组件,我们可以将他们认为是两个好哥们,Activity仪表不凡,迷倒万千少女,经常做一些公众人物角色

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

android SDK提供了Service,用于类似*nix守护进程或者windows的服务. Service有两种类型: 本地服务(Local Service):用于应用程序内部 远程服务(Remote Sercie):用于android系统内部的应用程序之间 前者用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程序比如Activity所属线程,而是单开线程后台执行,这样用户体验比较好. 后者可被其他应用程序复用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的

Android服务(Service)研究

Service是android四大组件之一,没有用户界面,一直在后台运行. 为什么使用Service启动新线程执行耗时任务,而不直接在Activity中启动一个子线程处理? 1.Activity会被用户退出,Activity所在的进程就变成了空进程(没有任何活动组件的进程),系统需要内存可能会优先终止该进程: 2.如果宿主进程被终止,那么该进程内所有的子线程也会被终止,这样可能导致子线程无法执行完成: 3.其实两种方式都是可以处理耗时任务的,使用场景不同而已. 一.通过Start方式启动Serv

Android中Service 全解析

在学习Android四大模块的时候在service的学习是必须要掌握的,而且个人感觉相当重要!很多场合都有需要的! 首先我们看看Service的种类 按运行地点分类 以上面三种方式启动的服务其生命周期也有区别,将在随后给出. 2.Service 与 Thread 的区别 很多时候,你可能会问,为什么要用 Service,而不用 Thread 呢,因为用 Thread 是很方便的,比起 Service 也方便多了,下面我详细的来解释一下. 1). Thread:Thread 是程序执行的最小单元,