Service是Android中长期在后台运行的没有界面的组件,使用服务的优势在于:能够提高进程的优先级,系统不容易回收掉进程,即便回收了,内存充足的时候,会把进程重新创建。

1.服务的简单使用示例:

1.1.定义一个服务:

定义一个服务的方式是定义一个类继承自Service:

 public class MyService extends Service {

       @Override

       public IBinder onBind(Intent intent) {

            // TODO Auto-generated method stub

            return null;

       }

 }

注意到onBind()方法是个抽象方法,因而必须重写。

1.2.注册服务:

四大组件之一的Service,在使用之前也必须在清单文件中注册。

<service android:name="cn.csc.service.MyService"></service>

1.3.在MainActivity中启动这个服务:

启动服务的方式很简单,可以如同启动Activity一样,通过Intent对象进行服务的启动,启动服务的方法是startService(Intent intent),下面的代码在MainActivity的onCreate()方法中启动服务:

 protected void onCreate(Bundle savedInstanceState) {

         super.onCreate(savedInstanceState);

         setContentView(R.layout.activity_main);

         Intent intent = new Intent(this, MyService.class);

         startService(intent);

 }

1.4.运行效果:

2.观察服务的生命周期:

2.1修改MyService及MainActivity代码,重写生命周期回调的各个方法,输出标识信息:

MainActivity.java:

 public class MainActivity extends ActionBarActivity {

     @Override

     protected void onCreate(Bundle savedInstanceState) {

         super.onCreate(savedInstanceState);

         setContentView(R.layout.activity_main);

         Log.i("MainActivity","onCreate()");

         Intent intent = new Intent(this, MyService.class);

         startService(intent);

     }

       @Override

       protected void onStop() {

            // TODO Auto-generated method stub

            super.onStop();

            Log.i("MainActivity","onStop()");

       }

       @Override

       protected void onDestroy() {

            // TODO Auto-generated method stub

            super.onDestroy();

            Log.i("MainActivity","onDestroy()");

       }

       @Override

       protected void onPause() {

            // TODO Auto-generated method stub

            super.onPause();

            Log.i("MainActivity","onPause()");

       }

       @Override

       protected void onResume() {

            // TODO Auto-generated method stub

            super.onResume();

            Log.i("MainActivity","onResume()");

       }

       @Override

       protected void onStart() {

            // TODO Auto-generated method stub

            super.onStart();

            Log.i("MainActivity","onStart()");

       }

 }

MyService.java:

 public class MyService extends Service {

       @Override

       public IBinder onBind(Intent intent) {

            // TODO Auto-generated method stub

            Log.i("MyService","onBind()");

            return null;

       }

       @Override

       public void onCreate() {

            // TODO Auto-generated method stub

            super.onCreate();

            Log.i("MyService","onCreate()");

       }

       @Override

       public int onStartCommand(Intent intent, int flags, int startId) {

            // TODO Auto-generated method stub

            Log.i("MyService","onStartCommand()");

            return super.onStartCommand(intent, flags, startId);

       }

       @Override

       public void onDestroy() {

            // TODO Auto-generated method stub

            super.onDestroy();

            Log.i("MyService","onDestroy()");

       }

       @Override

       public boolean onUnbind(Intent intent) {

            // TODO Auto-generated method stub

            Log.i("MyService","onUnbind()");

            return super.onUnbind(intent);

       }

 }

2.2部署安装应用:

运行结果:

2.3退出当前应用:

查看运行中的进程:

服务仍然在运行。

点击Stop之后:

服务才停止运行。

总结

采用startService()方式开启服务后,先后调用了服务的onCrate()和onStartCommand()方法,Activity被销毁之后,服务仍然继续运行,只有当手动停止掉服务时,才会调用onDestory()方法。

可见,start方式开启服务时, 一旦服务开启跟调用者(开启者)就没有任何关系了。

开启者退出后,服务仍然在后台长期的运行,开启者与服务没有任何关联,因而不能调用服务里面的方法。

2.4在MainActivity中调用bindService()绑定服务:

 protected void onCreate(Bundle savedInstanceState) {

         super.onCreate(savedInstanceState);

         setContentView(R.layout.activity_main);

         Log.i("MainActivity","onCreate()");

         Intent intent = new Intent(this, MyService.class);

         bindService(intent, new MyConn(), BIND_AUTO_CREATE);

 }

查看运行结果:

退出应用:

总结

采用绑定的方式开启服务,会先后调用:onCreate()、onBind(),Activity销毁后,Service紧跟着调用onunbind()、onDestory()也被销毁。

这种方式的服务跟随应用的结束而结束,不会长期驻留在后台,但是,这种方式下,Activity与Service产生了关联,因而可以调用Service提供的方法。那么在Activity中如何调用Service中的方法呢?

3.Activity调用本地服务方法:

主要步骤

1)在本地服务中添加需要被Activity调用的方法

2)定义一个接口,约定Activity通过该接口的实例调用本地服务的方法,该接口的实例由本地服务的onBind()方法传递给Activity

3) 在服务的内部创建一个内部类实现约定的接口,并在onBind()方法中返回该内部类的实例,由于onBind()方法返回的是IBinder类型的实例,所以该内部类还需要继承一个Ibinder接口的实现类,一般继承Binder类

4)在activity 绑定服务:bindService();

5)在服务成功绑定的时候 会执行一个方法 onServiceConnected 传递过来一个 IBinder对象

5)将传回的IBinder对象强制类型转化成约定接口的实例,从而调用接口里面的方法。

具体编码步骤:

1)修改MyService代码,添加一个供Activity调用的方法:

 public void serviceMethod(){

            Toast.makeText(getApplicationContext(), "本地服务方法被调用", Toast.LENGTH_SHORT).show();

 }

2)定义一个双方约定的接口,用于调用前面添加的serviceMethod()方法:

 public interface IMiddlePerson {

       public void callServiceMethod();

 }

3)在MyService中定义一个内部类继承自Binder并实现上面的约定接口:

 private class MiddlePerson extends Binder implements IMiddlePerson{

            @Override

            public void callServiceMethod() {

                  // TODO Auto-generated method stub

                  serviceMethod();

            }

 }

4)修改MyService的onBind()方法,返回上面定义的内部类的实例:

 public IBinder onBind(Intent intent) {

            // TODO Auto-generated method stub

            Log.i("MyService","onBind()");

            return new MiddlePerson();

 }

5)在MainActivity中添加一个存放约定接口的引用的字段:

private IMiddlePerson imp;

6)修改MainActivity的布局文件,添加一个按钮:

 <Button

         android:layout_width="wrap_content"

         android:layout_height="wrap_content"

         android:onClick="call"

         android:layout_gravity="center_horizontal"

         android:text="@string/call_native_service" />

在MainActivity中添加public void call(View view)方法,用于按钮的点击回调:

 public void call(View view){

           imp.callServiceMethod();

 }

7)修改MyConn的onServiceConnected方法,将IBinder类型的参数赋值给imp:

 public void onServiceConnected(ComponentName name, IBinder service) {

                  // TODO Auto-generated method stub

                  Log.i("MainActivity","服务绑定了");

                  imp = (IMiddlePerson) service;

 }

8)查看运行结果:

注: 如果又想服务能长期在后台运行,又想能够调用服务中的方法,则应如下顺序处理:

1)start方式开启服务(保证服务长期后台运行)

2)bind方式绑定服务(保证调用服务的方法)

在需要停止服务时,则需要按如下顺序:

3)unbind解除绑定服务

4)stopService停止服务。

这里,就不在测试了。

4.Activity调用远程服务的方法:

这里简单区分下本地服务和远程服务:

远程服务:调用者和服务在不同的工程代码里面。

本地服务:调用者和服务在同一个工程代码里面。

如果像调用同一个工程中的本地服务方法一样,绑定一个远程服务,直接会报错。这是因为绑定远程服务的方法与绑定本地服务的方法有所不同:

Android定义了aidl:android interface definition language  安卓接口定义语言来实现远程服务的绑定。

与绑定本地服务的主要不同在于:

约定的接口的定义不能带有任何访问修饰符,而且后缀名要改为.aidl,之后会自动生成一个名为Stub的内部类,服务中定义的内部类继承该内部类即可。

具体编码步骤:

4.1定义能远程绑定的服务:

1)定义IMiddlePeson.aidl:

 package cn.csc.service;

 interface IMiddlePerson {

     void callServiceMethod();

 }

将在gen目录下自动生成:

打开自动生成的IMiddlePerson.java:

可以看到自动生成了Stub内部抽象类

2)在服务中添加要被远程调用的方法:

 public void serviceMethod(){

            Log.i("MyService","远程服务方法被调用了。。。");

 }

3)在服务中定义内部类继承IMiddlePerson.Stub:

 private class MiddlePerson extends IMiddlePerson.Stub{

            @Override

            public void callServiceMethod() {

                  // TODO Auto-generated method stub

                  serviceMethod();

            }

 }

4)由于要被远程调用,所以不能使用显示意图了,需要在清单文件中注册服务时添加<intent-filter>生命能响应的动作:

 <service android:name="cn.csc.service.MyService">

             <intent-filter >

                 <action android:name="cn.csc.service.MyService"/>

             </intent-filter>

 </service>

至此,一个可以被远程绑定的服务就完成了,先把它部署到模拟器上。

4.2在另一个项目中绑定该远程服务:

1)将约定的接口IMiddlePerson.aidl文件连同所在包一同复制到该项目的src目录中:

可以看到,同样自动生成了IMiddlePerson.java文件

2)定义存放接口引用的字段:

private IMiddlePerson imp;

3)使用隐式意图绑定远程服务:

 Intent intent = new Intent();

 intent.setAction("cn.csc.service.MyService");

 bindService(intent, new MyConn(), BIND_AUTO_CREATE);

 4)修改MyConn()中的onServiceConnected()方法:

 public void onServiceConnected(ComponentName name, IBinder service) {

                  // TODO Auto-generated method stub

                  Log.i("MainActivity","服务绑定了");

                  imp = IMiddlePerson.Stub.asInterface(service);

 }

调用远程服务的应用端也搞定了,然后部署,查看运行结果:

以上,就是今天学到的关于Service的一点知识。

android菜鸟学习笔记28----Android中的Service生命周期及本地和远程服务绑定的实现的更多相关文章

  1. android菜鸟学习笔记30----Android使用百度地图API(一)准备工作及在应用中显示地图

    1.准备工作: 百度地图API是免费开放的,但是需要申请API Key: 1)先注册一个百度开发者帐号 2)进入百度开放服务平台http://developer.baidu.com/ 3)进入LBS云 ...

  2. android菜鸟学习笔记29----Android应用向用户发送提示信息的方式总结

    常见的向用户发送提示信息的方式有3种,分别为: 1)发送Toast信息 2)弹出对话框 3)发送通知 总结如下: 方式1:发送Toast信息: 这种方式最简单,在之前的学习中多次使用过.Toast是在 ...

  3. android菜鸟学习笔记27----Fragment的简单使用

    1.Fragment的生命周期: 简单在新建一个MyFragment继承自Fragment,重写各个生命周期回调方法,各个方法中直接输出标识相关函数被调用的信息. 重写MainActivity的各个生 ...

  4. android菜鸟学习笔记24----与服务器端交互(一)使用HttpURLConnection和HttpClient请求服务端数据

    主要是基于HTTP协议与服务端进行交互. 涉及到的类和接口有:URL.HttpURLConnection.HttpClient等 URL: 使用一个String类型的url构造一个URL对象,如: U ...

  5. android菜鸟学习笔记21----ContentProvider(一)ContentProvider的简单使用

    ContentProvider是Android四大组件之一,它用来封装数据,并通过ContentResolver接口将数据提供给其他应用.只有当需要在多个应用之间共享数据时才会用到ContentPro ...

  6. android菜鸟学习笔记8----Activity(一)

    Activity是android应用程序中重要的组件之一,常听到的android四大组件是Activity.Service.BroadcastReceiver和ContentProvider.它间接继 ...

  7. android菜鸟学习笔记7----android布局(二)

    3.FrameLayout:帧布局 如同Flash或者photoshop中图层的概念,在上面的图层遮盖下面的图层,没被遮到的地方仍然显示出来. 右击res/layout,然后在弹出的菜单中选择new, ...

  8. android菜鸟学习笔记2----关于adb

    adb : android debug bridge android调试桥 路径:adt-bundle目录/sdk/platform-tools/adb.exe 常见的adb命令: adb devic ...

  9. android菜鸟学习笔记31----Android使用百度地图API(二)获取地理位置及地图控制器的简单使用

    1.获取当前地理位置: Android中提供了一个LocationManager的类,用于管理地理位置.不能通过构造函数获取该类的实例,而是通过Context的getSystemService(): ...

随机推荐

  1. Intellij IDEA + Tomcat 出现 HTTP status 404错误的解决办法

    最近要做POC,接了个老项目改,使用war exploded部署到本机的Tomcat(8.5版) 通过Intellij IDEA启动Tomcat的时候发现系统的登录页面出现HTTP-status-40 ...

  2. ohasd failed to start: Inappropriate ioctl for device

    今天同事在安装GI的时候出现故障.让我帮忙看一下. 以下记录例如以下: 问题现象: 在安装gi的时候运行root.sh报例如以下错误: Finished running generic part of ...

  3. Tomcat 服务器只能存有一个正在运行的项目

    即使新建了一个new project (在同一个工作空间),启动Tomcat 还是会出现先前(工程名)一样的问题/异常. [原因]: 在底下Server 那里——Tomcat 7.X 底下会有很多工程 ...

  4. linux socket读数据错误解释

    EINTR 表示某种阻塞的操作,被接收到的信号中断,造成的一种错误返回值. EAGAIN   从字面上来看,是提示再试一次.这个错误经常出现在当应用程序进行一些非阻塞(non-blocking)操作( ...

  5. Centos下安装JDK、Maven和Git

    原文地址:https://github.com/eacdy/spring-cloud-book/blob/master/3%20%E4%BD%BF%E7%94%A8Docker%E6%9E%84%E5 ...

  6. 安装SDK后打开安卓project后有例如以下错误:发现了以元素 &#39;d:skin&#39; 开头的无效内容。此处不应含有子元素。

    Error: Error parsing D:\Program Files\SDK\android-sdk-windows\system-images\android-22\android-wear\ ...

  7. SpringCloud系列十一:自定义Feign

    1. 回顾 上文我们讲解了如何为服务消费者配置Feign. 在Spring Cloud中,Feign的默认配置类是FeignClientsConfiguration,该类定义了Feign默认使用的编码 ...

  8. Atitit.atijson 类库的新特性设计与实现 v3 q31

    Atitit.atijson 类库的新特性设计与实现 v3 q31 1. V1版本---集成了多引擎1 2. V2版本新特性 --bsh脚本化2 3. V3版本新特性---循环引用解决使用fastjs ...

  9. js中级系列三:前端性能优化

    原文链接:http://www.cnblogs.com/xxcanghai/p/5205998.html 链接:http://www.zhihu.com/question/21658448/answe ...

  10. php 、asp、 java、 c#、 delphi之间的语言对照

    PHP是一种跨平台的server端的嵌入式脚本语言.它大量地借用C,Java和Perl语言的语法, 并耦合PHP自己的特性,使WEB开发人员能够高速地写出动态产生页面. 它支持眼下绝大多数数据库. 另 ...