Services是Android中四大基础组件(Activities、 Services、 Content Providers、 BroadCast Receivers)之一,主要用于在后台长时间运行操作,不提供界面,如音乐播放器,关闭界面后还能继续播放。当页面需要交互时用线程。

创建Services,继承Service,复写里面的方法,用日志显示运行过程:

package com.example.androidservice;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log; public class MyService extends Service { private static final String TAG="TestTag"; @Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
} @Override
public void onCreate() {
Log.i(TAG, "onCreate");
super.onCreate();
} @Override
public void onStart(Intent intent, int startId) {
Log.i(TAG, "onStart");
super.onStart(intent, startId);
} @Override
public void onDestroy() {
Log.i(TAG, "onDestroy");
super.onDestroy();
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand");
return super.onStartCommand(intent, flags, startId);
} }

服务生命周期:context.startService() ->onCreate()- >onStart()- >onStartCommand()->Service running ->context.stopService()  ->onDestroy() ->Service stop

如果Service还没有运行,则android先调用onCreate()然后调用onStartCommand(),每次调用startService(Intent)的时候,都会调用执行onStartCommand();
如果Service已经运行,则只调用onStartCommand()。

我们要执行操作可在onStartCommand方法中定义,onStartCommand有4种返回值:

 START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。

START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。

START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。

START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。

创建页面用来启动Services,布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".AndroidServiceActivity" > <Button
android:id="@+id/btnStart"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开始" >
</Button> <Button
android:id="@+id/btnStop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="结束" >
</Button> </LinearLayout>

开始结束绑定事件,startService来启动服务(调用者与服务之间没有联系,调用都关闭不影响服务运行),stopService来停止服务,注意其参数为Intent对象,所以可以可以通过些Intent传递一些参数给Service,Service可以通过Intent来接收:

package com.example.androidservice;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button; public class AndroidServiceActivity extends Activity { private Button btnStart;
private Button btnStop; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_android_service);
btnStart=(Button)this.findViewById(R.id.btnStart);
btnStop=(Button)this.findViewById(R.id.btnStop);
btnStart.setOnClickListener(listener);
btnStop.setOnClickListener(listener);
} private OnClickListener listener=new OnClickListener() { @Override
public void onClick(View v) {
Intent intent=new Intent(AndroidServiceActivity.this,MyService.class);
switch(v.getId()){
case R.id.btnStart:
startService(intent);
break;
case R.id.btnStop:
stopService(intent);
break;
} }
}; @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_android_service, menu);
return true;
} }

最后在manifest.xml中添加节点<service android:name=".MyService" />与AndroidServiceActivity的Activity节点同级。

还有一种是用bindService()来启动,通过服务链接(ServiceConnection)或直接获取Service中状态和数据信息 
服务链接能够获取Service的对象,因此绑定Service的组件可以调用Service中的实现的函数 
使用Service的组件通过Context.bindService()建立服务链接,通过Context.unbindService()停止服务链接 
如果在绑定过程中Service没有启动,Context.bindService()会自动启动Service 
同一个Service可以绑定多个服务链接,这样可以同时为多个不同的组件提供服务

创建BindService继承Service,扩展Binder类声明方法getBindService返回BindService,以便调用自定义方法ShowLog()

package com.example.androidservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log; public class BindService extends Service { private static final String TAG="BindService"; private BindServiceX myBinderServiceX=new BindServiceX();
public class BindServiceX extends Binder{
public BindService getBindService() {
return BindService.this;
}
} @Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return myBinderServiceX;
} @Override
public void onCreate() {
Log.i(TAG, "onCreate");
super.onCreate();
} @Override
public void onStart(Intent intent, int startId) {
Log.i(TAG, "onStart");
super.onStart(intent, startId);
} @Override
public void onDestroy() {
Log.i(TAG, "onDestroy");
super.onDestroy();
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand");
return super.onStartCommand(intent, flags, startId);
} public void ShowLog(){
Log.i(TAG, "BindService=>ShowLog");
} }

Manifest.xml文件中声明<service android:name=".BindService" />

界面添加启动停止按钮:

<Button
android:id="@+id/btnStartBindService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开始BindService" >
</Button> <Button
android:id="@+id/btnStopBindService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="结束BindService" >
</Button>

AndroidServiceActivity绑定方法,Context.BIND_AUTO_CREATE表明只要绑定存在,就自动建立Service;同时也告知Android系统,这个Service的重要程度与调用者相同,除非考虑终止调用者,否则不要关闭这个Service。

如果service没被创建,那么调用一次onCreate(),然后调用onBind(),多次绑定时,不会多次调用onBind()。

通过unbindService()函数取消绑定Servcie时,onUnbind()函数将被调用, 
如果onUnbind()函数的返回true,则表示在调用者绑定新服务时, 
onRebind()函数将被调用

取消绑定仅需要使用unbindService()方法,并将ServiceConnnection传递给unbindService()方法需注意的是,unbindService()方法成功后,系统并不会调用onServiceDisconnected(),因为onServiceDisconnected()仅在意外断开绑定时才被调用

当bindService后,不能stopService,需要通过unBindService()来解除绑定

startService()后,不可以通过unBindService()来销毁service

private boolean isConn = false;//用来标志服务是否绑定
private OnClickListener listener = new OnClickListener() { @Override
public void onClick(View v) {
Intent intentBind = new Intent(AndroidServiceActivity.this, BindService.class); switch (v.getId()) {
case R.id.btnStartBindService:
bindService(intentBind, conn, Context.BIND_AUTO_CREATE);
break;
case R.id.btnStopBindService:
if (isConn) {
unbindService(conn); //不可以多次调用
isConn=false;
}
break;
} }
};

声明conn,用来连接服务,调用服务的方法。

private ServiceConnection conn = new ServiceConnection() {

        @Override
public void onServiceDisconnected(ComponentName name) {
isConn=false;
} @Override
public void onServiceConnected(ComponentName name, IBinder service) {
BindServiceX bindServiceX = (BindServiceX) service;
BindService bindService = bindServiceX.getBindService();
bindService.ShowLog();
isConn=true;
}
};

bindService()目的是回调onBind()方法,它的作用是在Service和调用者之间建立一个桥梁,并不负责更多的工作(例如一个Service需要连接服务器的操作),一般使用bindService来绑定到一个现有的Service(即通过StartService启动的服务),Activity 与 Service传递数据和调用接口。

以上两种使用方法并不是完全独立的,在某些情况下可以混合使用以MP3播放器为例,在后台的工作的Service通过Context.startService()启动某个特定音乐播放,但在播放过程中如果用户需要暂停音乐播放,则需要通过Context.bindService()获取服务链接和Service对象,进而通过调用Service的对象中的函数,暂停音乐播放过程,并保存相关信息。在这种情况下,如果调用Context.stopService()并不能够停止Service,需要在所有的服务链接关闭后,Service才能够真正的停止

Android中Services简析的更多相关文章

  1. Android 启动过程简析

    首先我们先来看android构架图: android系统是构建在linux系统上面的. 所以android设备启动经历3个过程. Boot Loader,Linux Kernel & Andr ...

  2. android:descendantFocusability用法简析

    开发中很常见的一个问题,项目中的listview不仅仅是简单的文字,常常需要自己定义listview,自己的Adapter去继承BaseAdapter,在adapter中按照需求进行编写,问题就出现了 ...

  3. Android中Services之异步IntentService

    IntentService:异步处理服务,新开一个线程:handlerThread在线程中发消息,然后接受处理完成后,会清理线程,并且关掉服务. IntentService有以下特点: (1)  它创 ...

  4. 坑爹的属性,android:descendantFocusability用法简析

    开发中很常见的一个问题,项目中的listview不仅仅是简单的文字,常常需要自己定义listview,自己的Adapter去继承 BaseAdapter,在adapter中按照需求进行编写,问题就出现 ...

  5. android:descendantFocusability用法简析(转)

        开发中很常见的一个问题,项目中的listview不仅仅是简单的文字,常常需要自己定义listview,自己的Adapter去继承BaseAdapter,在adapter中按照需求进行编写,问题 ...

  6. lucene中Field简析

    http://blog.csdn.net/zhaoxiao2008/article/details/14180019 先看一段lucene3代码 Document doc = new Document ...

  7. hello-jni Android.mk文件简析

    #删除旧变量 LOCAL_PATH := $(call my-dir) #返回当前目录 include $(CLEAR_VARS) #删除旧变量 #设置新变量 LOCAL_MODULE := hell ...

  8. JDK框架简析--java.lang包中的基础类库、基础数据类型

    题记 JDK.Java Development Kit. 我们必须先认识到,JDK不过,不过一套Java基础类库而已,是Sun公司开发的基础类库,仅此而已,JDK本身和我们自行书写总结的类库,从技术含 ...

  9. Android 11(R) Power HAL AIDL简析 -- 基本接口

    Android 11(R) Power HAL AIDL将分三篇文章来介绍: Android 11(R) Power HAL AIDL简析 -- 基本接口 Android 11(R) Power HA ...

随机推荐

  1. 《利用Python进行数据分析》第6章学习笔记

    数据加载.存储与文件格式 读写文本格式的数据 逐块读取文本文件 read_xsv参数nrows=x 要逐块读取文件,需要设置chunksize(行数),返回一个TextParser对象. 还有一个ge ...

  2. Replication的犄角旮旯(五)--关于复制identity列

    <Replication的犄角旮旯>系列导读 Replication的犄角旮旯(一)--变更订阅端表名的应用场景 Replication的犄角旮旯(二)--寻找订阅端丢失的记录 Repli ...

  3. Linux计划任务crontab运行脚本不正确的问题

    问题的由来 写好的程序希望在崩溃之后能够自启动,于是利用linux的crontab功能,添加一个计划任务,每分钟执行一个脚本查看需要监控的进程是否还在,如果不在则启动之,否则不做任何事情.这么一个简单 ...

  4. MQTT协议简记

    MQTT - MQ Telemetry Transport   轻量级的 machine-to-machine 通信协议. publish/subscribe模式. 基于TCP/IP. 支持QoS. ...

  5. Hibernate的Annotation注解

    当项目变得比较大的时候,如何还使用hbm.xml文件来配置Hibernate实体就会变得比较复杂.这里Hibernate提供了Annotation注解方式,使得Hibernate的映射文件变得很方便管 ...

  6. sizeof && strlen 的区别

    本文主要记录了 sizeof 操作符 和 strlen() 函数的区别,以及各自的用途.(在下才疏学浅,发现错误,还请留言指正) sizeof 和 strlen 的区别 示例代码如下: #includ ...

  7. save与persist差别

    唯一差别: 在没提交事务情况下 save会产生insert语句,然后因为没提交事务进行回滚. 而这种情况,persist是连insert语句都不会产生.

  8. 缓存篇~第七回 Redis实现基于方法签名的数据集缓存(可控更新,分布式数据缓存)

    返回目录 本篇文章可以说是第六回 Microsoft.Practices.EnterpriseLibrary.Caching实现基于方法签名的数据集缓存(可控更新,WEB端数据缓存)的续篇,事实上,有 ...

  9. JS实现无限分页加载——原理图解

    由于网页的执行都是单线程的,在JS执行的过程中,页面会呈现阻塞状态.因此,如果JS处理的数据量过大,过程复杂,可能会造成页面的卡顿.传统的数据展现都以分页的形式,但是分页的效果并不好,需要用户手动点击 ...

  10. H5常用代码:适配方案5

    此方案跟方案4是同一原理,也是通过REM实现的,能单独归类出一个方案,是因为它有一定的实用价值,当你遇到追求完美,追求到一像素的UI或者产品时,那此方案将解决你的困境. 方案5主要是用来解决一像素边框 ...