Android四大组件之 Service

开发者福利!热门AI工具限时免费用 购周边即赠Coding Plan Lite,Claude Code、Cursor等20+工具畅享,效率翻倍! 阅读详情

一    Service简介

        Service是运行在后台的,没有界面的,用来处理耗时比较长的。Service不是一个单独的进程,不是一个单独的线程。

        Service有两种类型:

  1. 本地服务(Local Service):用于应用程序内部
  2. 远程服务(Remote Sercie):用于android系统内部的应用程序之间
       

      前者用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程序比如Activity所属线程,而是单开线程后台执行,这样用户体验比较好。

      后者可被其他应用程序复用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的即可。

     

二  Service的生命周期

      Service有startService()和bindService()两种启动Service方法,每种方法Service的生命周期是不一样的。

     1 通过startService()
       Service会经历 onCreate --> onStartCommand()
       stopService的时候直接onDestroy

       如果是 调用者 直接退出而没有调用stopService的话,Service会一直在后台运行。
       下次调用者再起来仍然可以stopService。

    2 通过bindService()  
       Service只会运行onCreate()-->onBind()

      这个时候 调用者和Service绑定在一起
       unbindService的时候  onUnbind()-->onDestroyed()
      调用者退出了,Srevice就会调用onUnbind()-->onDestroyed()
      所谓绑定在一起就共存亡了。 


注意:Service的onCreate的方法只会被调用一次,
就是你无论多少次的startService又 bindService,Service只被创建一次。
如果先是bind了,那么start的时候就直接运行Service的onStart方法,
如果先是start,那么bind的时候就直接运行onBind方法。如果你先bind上了,就stop不掉了,
只能先UnbindService, 再StopService,所以是先start还是先bind行为是有区别的。

Android中的服务和windows中的服务是类似的东西,服务一般没有用户操作界面,它运行于系统中不容易被用户发觉,可以使用它开发如监控之类的程序。

服务不能自己运行,需要通过调用Context.startService()或Context.bindService()方法启动服务。
这两个方法都可以启动Service,但是它们的使用场合有所不同。使用startService()方法启用服务,调用者与服务之间没有关连,
即使调用者退出了,服务仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。

如果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,
接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,
但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。

如果打算采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,
接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,
接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,
多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。
如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()-->onDestroy()方法.   



三    代码实例

编写不需和Activity交互的本地服务示例

本地服务编写比较简单。首先,要创建一个Service类,该类继承android的Service类。这里写了一个计数服务的类,每秒钟为计数器加一。在服务类的内部,还创建了一个线程,用于实现后台执行上述业务逻辑。

 

 

package com.easymorse;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class CountService extends Service {

   
private  boolean threadDisable;

   
privateint count;

    @Override
   
public IBinder onBind(Intent intent) {
       
returnnull;
    }

    @Override
   
public void onCreate() {
       
super.onCreate();
       
new Thread(new Runnable() {

            @Override
           
publicvoid run() {
               
while (!threadDisable) {
                   
try {
                        Thread.sleep(
1000);
                    }
catch (InterruptedException e) {
                    }
                    count
++;
                    Log.v(
"CountService","Count is " + count);
                }
            }
        }).start();
    }

    @Override
   
public void onDestroy() {
       
super.onDestroy();
       
this.threadDisable= true;
        Log.v(
"CountService","on destroy");
    }

   
public int getCount() {
       
return count;
    }

}

 需要将该服务注册到配置文件AndroidManifest.xml中,否则无法找到:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package
="com.easymorse" android:versionCode="1" android:versionName="1.0">
   
<applicationandroid:icon="@drawable/icon" android:label="@string/app_name">
       
<activityandroid:name=".LocalServiceDemoActivity"
            android:label
="@string/app_name">
           
<intent-filter>
               
<actionandroid:name="android.intent.action.MAIN"/>
               
<categoryandroid:name="android.intent.category.LAUNCHER"/>
           
</intent-filter>
       
</activity>
       
<serviceandroid:name="CountService"/>
   
</application>
   
<uses-sdkandroid:minSdkVersion="3"/>
</manifest/>

 

 

在Activity中启动和关闭本地服务。

package com.easymorse;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;

public class LocalServiceDemoActivityextends Activity {
   
/** Called when the activity is first created.*/
    @Override
   
public void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

       
this.startService(new Intent(this, CountService.class));
    }

    @Override
   
protectedvoid onDestroy() {
       
super.onDestroy();
       
this.stopService(new Intent(this, CountService.class));
    }
}

 

可通过日志查看到后台线程打印的计数内容。

编写本地服务和Activity交互的示例

上面的示例是通过startService和stopService启动关闭服务的。适用于服务和activity之间没有调用交互的情况。如果之间需要传递参数或者方法调用。需要使用bind和unbind方法。

具体做法是,服务类需要增加接口,比如ICountService,另外,服务类需要有一个内部类,这样可以方便访问外部类的封装数据,这个内部类需要继承Binder类并实现ICountService接口。还有,就是要实现Service的onBind方法,不能只传回一个null了。

这是新建立的接口代码:

package com.easymorse;

public interface ICountService {
   
public abstract int getCount();
}

 

修改后的CountService代码:

package com.easymorse;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

public class CountServiceextends Serviceimplements ICountService {

   
privateboolean threadDisable;

   
privateint count;

   
private ServiceBinder serviceBinder=new ServiceBinder();

   
public class ServiceBinderextends Binderimplements ICountService{
        @Override
       
publicint getCount() {
           
return count;

        }

    }

    @Override

    public IBinder onBind(Intent intent) {
       
return serviceBinder;
    }

    @Override
   
public void onCreate() {
       
super.onCreate();
       
new Thread(new Runnable() {

            @Override
           
publicvoid run() {
               
while (!threadDisable) {
                   
try {
                        Thread.sleep(
1000);
                    }
catch (InterruptedException e) {
                    }
                    count
++;
                    Log.v(
"CountService","Count is " + count);
                }
            }
        }).start();
    }

    @Override
   
public void onDestroy() {
       
super.onDestroy();
       
this.threadDisable= true;
        Log.v(
"CountService","on destroy");
    }

   
/* (non-Javadoc)
     * @see com.easymorse.ICountService#getCount()
    
*/
   
public int getCount() {
       
return count;
    }

}

 

服务的注册也要做改动,AndroidManifest.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package
="com.easymorse" android:versionCode="1" android:versionName="1.0">
   
<applicationandroid:icon="@drawable/icon" android:label="@string/app_name">
       
<activityandroid:name=".LocalServiceDemoActivity"
            android:label
="@string/app_name">
           
<intent-filter>
               
<actionandroid:name="android.intent.action.MAIN"/>
               
<categoryandroid:name="android.intent.category.LAUNCHER"/>
           
</intent-filter>
       
</activity>
       
<serviceandroid:name="CountService">
           
<intent-filter>
               
<actionandroid:name="com.easymorse.CountService"/>
           
</intent-filter>
       
</service>
   
</application>
   
<uses-sdkandroid:minSdkVersion="3"/>
</manifest>

 

Acitity代码不再通过startSerivce和stopService启动关闭服务,另外,需要通过ServiceConnection的内部类实现来连接Service和Activity。

package com.easymorse;

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.util.Log;

public class LocalServiceDemoActivity extends Activity {

   
private ServiceConnection serviceConnection= new ServiceConnection() {

        @Override
       
publicvoid onServiceConnected(ComponentName name, IBinder service) {
            countService
= (ICountService) service;
            Log.v(
"CountService","on serivce connected, count is"
                   
+ countService.getCount());
        }

        @Override
       
publicvoid onServiceDisconnected(ComponentName name) {
            countService
=null;
        }

    };

   
private ICountService countService;

   
/** Called when the activity is first created.*/
    @Override
   
public void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
this.bindService(new Intent("com.easymorse.CountService"),
               
this.serviceConnection, BIND_AUTO_CREATE);
    }

    @Override
   
protectedvoid onDestroy() {

          this.unbindService(serviceConnection);       

          super.onDestroy();      //注意先后
    }
}

 

编写传递基本型数据的远程服务

上面的示例,可以扩展为,让其他应用程序复用该服务。这样的服务叫远程(remote)服务,实际上是进程间通信(RPC)。

这时需要使用android接口描述语言(AIDL)来定义远程服务的接口,而不是上述那样简单的java接口。扩展名为aidl而不是java。可用上面的ICountService改动而成ICountSerivde.aidl,eclipse会自动生成相关的java文件。

package com.easymorse;

interface ICountService {
   
int getCount();
}

 

编写服务(Service)类,稍有差别,主要在binder是通过远程获得的,需要通过桩(Stub)来获取。桩对象是远程对象的本地代理。

package com.easymorse;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class CountService extends Service {

   
privateboolean threadDisable;

   
privateint count;

   
private ICountService.Stub serviceBinder= new ICountService.Stub() {

        @Override
       
publicint getCount()throws RemoteException {
           
return count;
        }
    };

    @Override
   
public IBinder onBind(Intent intent) {
       
return serviceBinder;
    }

    @Override
   
public void onCreate() {
       
super.onCreate();
       
new Thread(new Runnable() {

            @Override
           
publicvoid run() {
               
while (!threadDisable) {
                   
try {
                        Thread.sleep(
1000);
                    }
catch (InterruptedException e) {
                    }
                    count
++;
                    Log.v(
"CountService","Count is " + count);
                }
            }
        }).start();
    }

    @Override
   
public void onDestroy() {
       
super.onDestroy();
       
this.threadDisable= true;
        Log.v(
"CountService","on destroy");
    }
}

 

配置文件AndroidManifest.xml和上面的类似,没有区别。

在Activity中使用服务的差别不大,只需要对ServiceConnection中的调用远程服务的方法时,要捕获异常。

private ServiceConnection serviceConnection= new ServiceConnection() {

    @Override
   
public void onServiceConnected(ComponentName name, IBinder service) {
        countService
= (ICountService) service;
       
try {
            Log.v(
"CountService","on serivce connected, count is"
                   
+ countService.getCount());
        }
catch (RemoteException e) {
           
thrownew RuntimeException(e);
        }
    }

    @Override
   
public void onServiceDisconnected(ComponentName name) {
        countService
=null;
    }

};

 

这样就可以在同一个应用程序中使用远程服务的方式和自己定义的服务交互了。

如果是另外的应用程序使用远程服务,需要做的是复制上面的aidl文件和相应的包构到应用程序中,其他调用等都一样。

编写传递复杂数据类型的远程服务

远程服务往往不只是传递java基本数据类型。这时需要注意android的一些限制和规定:

  1. android支持String和CharSequence
  2. 如果需要在aidl中使用其他aidl接口类型,需要import,即使是在相同包结构下;
  3. android允许传递实现Parcelable接口的类,需要import;
  4. android支持集合接口类型List和Map,但是有一些限制,元素必须是基本型或者上述三种情况,不需要import集合接口类,但是需要对元素涉及到的类型import;
  5. 非基本数据类型,也不是String和CharSequence类型的,需要有方向指示,包括in、out和inout,in表示由客户端设置,out表示由服务端设置,inout是两者均可设置。

这里将前面的例子中返回的int数据改为复杂数据类型:

package com.easymorse;

import android.os.Parcel;
import android.os.Parcelable;

public class CountBean implements Parcelable {

   
public static final Parcelable.Creator<CountBean> CREATOR = new Creator<CountBean>() {

        @Override
       
public CountBean createFromParcel(Parcel source) {
            CountBean bean
=new CountBean();
            bean.count
= source.readInt();
           
return bean;
        }

        @Override
       
public CountBean[] newArray(int size) {
           
returnnew CountBean[size];
        }

    };

   
public int count;

    @Override
   
public void writeToParcel(Parcel dest,int flags) {
        dest.writeInt(
this.count);
    }

    @Override
   
public int describeContents() {
       
return0;
    }

}

 

然后,需要在相同包下建一个同名的aidl文件,用于android生成相应的辅助文件:

package com.easymorse;

parcelable CountBean;

 

这一步是android 1.5后的变化,无法通过adt生成aidl,也不能用一个比如全局的project.aidl文件,具体见:

http://www.anddev.org/viewtopic.php?p=20991

然后,需要在服务的aidl文件中修改如下:

package com.easymorse;

import com.easymorse.CountBean;

interface ICountService {
    CountBean getCount();
}

 

其他的改动很小,只需将CountService和调用CountService的部分修改为使用CountBean即可

一个Demo学完Android中所有的服务 注:这个例子来自“安卓巴士”,经阅读,理解,写此文章 说明:这个例子实现了Android中常见的许多服务,下面是实现的截图 接下来,以源代码的方式分析这个例子 1.MainActivity--主界面 这个类主要是实现用户所看到的这个Activity,其中包含了一系列的按钮,用户点击按钮执行相应的动作,所以在这个类中主要是对按钮的定义和对按钮绑定相应的监听器,下面是实 阅读详情

相关推荐

Android开发四大组件Service应用总结Demo

demo包含测试service的生命周期走向,service的启动,停止,绑定,取消绑定,以及IntentService的生命周期走向测试和IntentService与访问者信息通信过程,不清楚之处请参阅我的博客《Android开发四大组件Service总结》

安卓学习笔记1——使用服务实现计时器

安卓学习笔记1——使用服务实现计时器计时器XML布局AndroidMainfestServiceMainActivity效果预览 计时器 根据李先生的要求,我们需要通过服务来实现一个计时器,但是没给具体要求,全靠一手自学,那么设计一个简单功能,即开始计时和停止计时,同时显示相应的时间,具体可能用到服务组件以及通过绑定服务的方式来完成与Service的交互,下面看具体实现。 XML布局 只用到一个文本控件(用来显示计时)和两个按钮控件(分别用来开始和结束计时),下面是布局文件: activity_main.x

weixin_44445770的博客 2353

Android 四大组件Service的Demo

Android 四大组件Service的Demo

Android四大组件Service

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34006468的博客 153

Android四大组件——Service入门

ServiceAndroid系统中的四大组件之一,它是一种长生命周期的,没有可视化界面,运行于后台的一种服务程序。 但是Service是运行于UI线程中的,不能直接进行耗时操作,但可以新建个子线程执行耗时操作。 因为是四大组件之一,所以要在Manifests中注册。 Service的启动方式有两种,StartService和bindService . 1.startServi

卓原的进化之旅 967

安卓四大组件——Service服务(内含Binder的简单解释)

安卓开发四大组件Service部分的混淆点,还有简单的Binder的理解

weixin_44752167的博客 2476

Android】安卓四大组件Service

Android】安卓四大组件Service 1、Service的介绍 1.1 什么是service Service即服务,用大白话讲就是——长期运行在后台的程序,如果我们说的官方一点,那么就是用于执行长期运行的任务,并且没有与用户交互的功能。 每一个service都和activity一样,需要在manifest.xml中配置,赋予其生命。使用<service>标签即可配置 在activity类中,可以使用Context.startService()方法来开启服务,使用Context.stop

woodwhale的博客 685

android四大组件(Activity,Service,BroadcastReceiver,Content Provider)

安卓的四大组建,五大布局Android四大组件:Activity、Service、Broadcast Receiver、Content Provider。1、 Activity 可以去本人博客activity了解学习是Android程序与用户交互的窗口,从视觉效果来看,一个Activity占据当前的窗口,响应所有窗口事件,具备有控件,菜单等界面元素。从内部逻辑来看,Activity需要为了保持各个

Mr_haimeng的博客 1350

Android】安卓四大组件之服务(Service)详解:从基础到进阶

Service作为安卓应用后台任务处理的核心组件,在保障应用功能完整性和提升用户体验方面起着不可或缺的作用。通过掌握Service的生命周期、分类及使用场景,开发者能够合理设计应用架构,实现高效、稳定的后台任务处理。随着安卓系统的不断升级,Service的使用也需与时俱进,结合新特性和替代方案,让应用在后台运行中发挥更大价值。希望本文能帮助大家深入理解Service,在安卓开发中灵活运用这一强大工具

m0_59734531的博客 1500

Android】安卓四大组件Service用法

使用Handler更新UI,基本特点后台执行Service主要用于在后台执行一些长时间运行的操作,比如音乐播放、文件下载等,而不会影响用户界面的交互。

Patrick_yuxuan的博客 1393

Android四大组件Service

https://developer.android.google.cn/guide/components/services.html本篇博客讲解的是Android四大组件Service,下面是内容摘要: 了解Service Android 中的进程 电话窃听器 Service 的生命周期 AIDL的使用 一、Service 的基本概念Android 官方文档对Service 的解释如下:A Ser

JackChan 1174

service应用

练习创建启动模式下运行的Service组件。创建一个Android工程StartModeService,活动名称main.java,创建一个Service类CountService.java。运行后在LogCat窗口观察提示信息。在工程界面上添加两个按钮启动、停止。程序运行后通过按钮实现启动和停止Service

安卓四大组件service

Service作为Android四大组件之一,在每一个应用程序中都扮演着非常重要的角色,所以每一位安卓工程师对其掌握是必然的!针对Service,CSDN博客之星–郭霖写了两篇比较完整的解析博客: Android Service完全解析,关于服务你所需知道的一切(上) Android Service完全解析,关于服务你所需知道的一切(下)

探路的淮--Ontheway的博客 946

android四大组件应用app,安卓四大组件———Service

1.什么是Service(服务)Service是一种后台运行的应用组件。2.Service有哪些应用场景下载任务,qq消息缓存,音乐播放器的播放3.startService方式启动Service怎么做()首先新建一个类继承Service ,实现它的onBind方法,其中可以用onCreate(),onStartCommand()和onDestroy()方法。例如package com.exampl...

weixin_30395941的博客 512

安卓开发四大组件Service

对于activity和服务来说,它指明了请求的操作名称以及作为操作对象的数据的URI和其他一些信息。比方说,它能够承载对一个activity 的请求,让它为用户显示一张图片,或者让用户编辑一些文本。广播i接收器没有用户界面,但可以启动一个activity或service来响应收到的信息,或用NotificationManager来通知用户。静态注册无需担忧是否被关闭,只要设备是开启状态,广播接收器也是打开的。使用URI唯一标识其数据集,这里的URI以content://作为前缀,表示数据由其管理。

gfdr5的博客 296

Android 四大组件Service

Serviceandroid系统中的四大组件之一(Activity、Service、BroadcastReceiver、ContentProvider),它跟Activity的级别差不多,区别是Service只能运行在后台不提供用户界面,并且可以和其他组件进行交互。一个Service是一个可以长期运行在后台的应用程序组件,不提供用户界面。 另一个应用程序组件可以启动一个服务,它将继续在后台运行,...

ZHS_Vistor的博客 471

安卓四大组件Service

Service作为安卓四大组件之一通常用来完成一些不需要用户操作,但是一直运行着的任务  在介绍Service之前 我们先了解一下安卓中进程的优先级: 安卓中的优先级共有5个 1.Foregrounf process 前台进程  当前进程中有Activity处于可见可操作(Activity执行onResume之后) service 以及广播接收者 执行生命周期方法 2.vi

ybx007的博客 504

Android——四大组件Service

文章目录AndroidAndroid四大组件——Service1 简介2 生命周期3 Service分类3.1 started(启动服务)3.2 bound(绑定服务)IBinder接口ServiceConnection接口 Android Android四大组件——Service service用于在后台完成用户指定的操作。 startService() 与 bindService()区别: (a)started service(启动服务)是由其他组件调用startService()方法启动的,这导致服

weixin_45044097的博客 294
上一篇: 小米手机四种刷机方法
下一篇: Android Activity的四种LaunchMode!!!
andy_android
博客等级 码龄15年 278粉丝 90原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值