`
haric
  • 浏览: 117763 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Android教程(2.2) 使用Service

阅读更多

后台的幽灵 - Service

本节内容涉及到
一 什么是Service
如何使用Service
Service的生命周期

一 什么是Service

Service,看名字就知道跟正常理解的“服务”差不多,后台运行,可交互这样的一个东西。它跟Activity的级别差不多,但是他不能自己运行,需要通过某一个Activity或者其他Context对象来调用, Context.startService() 和 Context.bindService()。

两种启动Service的方式有所不同。这里要说明一下的是如果你在Service的onCreate或者onStart做一些很耗时间的事情,最好在Service里启动一个线程来完成,因为Service是跑在主线程中,会影响到你的UI操作或者阻塞主线程中的其他事情。

什么时候需要Service呢?比如播放多媒体的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,再或者在后台记录你地理信息位置的改变等等,总之服务嘛,总是藏在后头的。

 

如何使用Service

那接下来用代码来说明一下怎么使用Service,这里我们要讲的是Local Service也就是你自己的一个Service, 你也可以操作别的应用程序的service如果它允许你那么去做的话,这就设计到一个比较麻烦的东西interprocess communication (IPC),在不同的进程中通信的机制,这个我自己也还没有用过,等用了以后再跟大伙说说,通常情况下Local的就够用啦。

跟Activity一样首先你要写一个类继承自android.app.Service,在这里我叫他TestService
代码如下:

package com.haric.tutorial;

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

public class TestService extends Service {
	private static final String TAG = "TestService";
	private NotificationManager _nm;

	@Override
	public IBinder onBind(Intent i) {
		Log.e(TAG, "============> TestService.onBind");
		return null;
	}

	public class LocalBinder extends Binder {
		TestService getService() {
			return TestService.this;
		}
	}

	@Override
	public boolean onUnbind(Intent i) {
		Log.e(TAG, "============> TestService.onUnbind");
		return false;
	}

	@Override
	public void onRebind(Intent i) {
		Log.e(TAG, "============> TestService.onRebind");
	}

	@Override
	public void onCreate() {
		Log.e(TAG, "============> TestService.onCreate");
		_nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		showNotification();
	}

	@Override
	public void onStart(Intent intent, int startId) {
		Log.e(TAG, "============> TestService.onStart");
	}

	@Override
	public void onDestroy() {
		_nm.cancel(R.string.service_started);
		Log.e(TAG, "============> TestService.onDestroy");
	}

	private void showNotification() {
		Notification notification = new Notification(R.drawable.face_1,
				"Service started", System.currentTimeMillis());

		PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
				new Intent(this, TestServiceHolder.class), 0);

		// must set this for content view, or will throw a exception
		notification.setLatestEventInfo(this, "Test Service",
				"Service started", contentIntent);

		_nm.notify(R.string.service_started, notification);
	}
}

 其中用到Notification是为了明显地表明Service存活的状态,跟demo的code学过来的,这样看上去直观一点,更多关于Notification的内容以后UI部分来写吧,现在就知道怎么使用就好了。

@Override
	public void onCreate() {
		Log.e(TAG, "============> TestService.onCreate");
		_nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		showNotification();
	}

像这样,我在Service的几个生命周期函数中加了打印log的语句,方便测试。

 

public class LocalBinder extends Binder {
		TestService getService() {
			return TestService.this;
		}
	}

这个方法是为了让调用者得到这个Service并操作它。
Service本身就这样简单了,你需要做什么就在onCreate和onStart里做好了,起个线程什么的。

再看一下它的调用者,TestServiceHolder

package com.haric.tutorial;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class TestServiceHolder extends Activity {
	private boolean _isBound;
	private TestService _boundService;

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.test_service_holder);
		setTitle("Service Test");

		initButtons();
	}
	
	private ServiceConnection _connection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
        	_boundService = ((TestService.LocalBinder)service).getService();
            
            Toast.makeText(TestServiceHolder.this, "Service connected",
                    Toast.LENGTH_SHORT).show();
        }

        public void onServiceDisconnected(ComponentName className) {
            // unexpectedly disconnected,we should never see this happen.
        	_boundService = null;
            Toast.makeText(TestServiceHolder.this, "Service connected",
                    Toast.LENGTH_SHORT).show();
        }
    };

	private void initButtons() {
		Button buttonStart = (Button) findViewById(R.id.start_service);
		buttonStart.setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				startService();
			}
		});

		Button buttonStop = (Button) findViewById(R.id.stop_service);
		buttonStop.setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				stopService();
			}
		});

		Button buttonBind = (Button) findViewById(R.id.bind_service);
		buttonBind.setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				bindService();
			}
		});

		Button buttonUnbind = (Button) findViewById(R.id.unbind_service);
		buttonUnbind.setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				unbindService();
			}
		});
	}

	private void startService() {
		Intent i = new Intent(this, TestService.class);
		this.startService(i);
	}

	private void stopService() {
		Intent i = new Intent(this, TestService.class);
		this.stopService(i);
	}

	private void bindService() {
		Intent i = new Intent(this, TestService.class);
		 bindService(i, _connection, Context.BIND_AUTO_CREATE);
		 _isBound = true;
	}

	private void unbindService() {
		if (_isBound) {
            unbindService(_connection);
            _isBound = false;
        }
	}
}

 

这里可以看到两种启动方法,start和bind,当然也是通过intent调用的,在intent中指明指定要启动的Service的名字,stop也一样

private void startService() {
		Intent i = new Intent(this, TestService.class);
		this.startService(i);
	}

private void stopService() {
		Intent i = new Intent(this, TestService.class);
		this.stopService(i);
	}

对于bind的话,需要一个ServiceConnection对象

private ServiceConnection _connection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
        	_boundService = ((TestService.LocalBinder)service).getService();
            
            Toast.makeText(TestServiceHolder.this, "Service connected",
                    Toast.LENGTH_SHORT).show();
        }

        public void onServiceDisconnected(ComponentName className) {
            // unexpectedly disconnected,we should never see this happen.
        	_boundService = null;
            Toast.makeText(TestServiceHolder.this, "Service connected",
                    Toast.LENGTH_SHORT).show();
        }
    };

用来把Activity和特定的Service连接在一起,共同存亡,具体的生命周期细节下一段来讲。


Service的生命周期

Service的生命周期方法比Activity少一些,只有onCreate, onStart, onDestroy
我们有两种方式启动一个Service,他们对Service生命周期的影响是不一样的。


1 通过startService

    Service会经历 onCreate -> onStart
   stopService的时候直接onDestroy

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

 

  2 通过bindService   

    Service只会运行onCreate, 这个时候 TestServiceHolder 和TestService绑定在一起

   TestServiceHolder 退出了,Srevice就会调用onUnbind->onDestroyed
   所谓绑定在一起就共存亡了。

 

那有同学问了,要是这几个方法交织在一起的话,会出现什么情况呢?
一个原则是Service的onCreate的方法只会被调用一次,就是你无论多少次的startService又bindService,Service只被创建一次。如果先是bind了,那么start的时候就直接运行Service的onStart方法,如果先是start,那么bind的时候就直接运行onBind方法。如果你先bind上了,就stop不掉了,对啊,就是stopService不好使了,只能先UnbindService, 再StopService,所以是先start还是先bind行为是有区别的。

看起来情况很多,不过我会把这次的代码包括上回Activity生命周期的研究代码都贴上了,希望你喜欢!大家有兴趣可以回去点点按钮看看log,多看几遍就知道了。

 

29
1
分享到:
评论
11 楼 chenmingde 2012-04-27  
service并不是一定在后台长久运行的,会被资源紧张情况下杀死
10 楼 yinyan_happy 2012-01-11  
TestService getService() { 
            return TestService.this; 
      }
楼主,请教下,这是干什么的?
9 楼 蒋瑾珂 2011-08-09  
我是杜锦东的同学噢~~   
8 楼 diyisoft 2011-02-07  
habzyhs 写道
用来研究service的生命周期是蛮不错的,主要是清晰明了。但是没看出来showNotification()这个方法起什么用处。



在这里是显示调试信息吧。
7 楼 yancewong 2011-01-21  
不赖 , mark下 , 日后研究
6 楼 rmn190 2010-11-06  
不错, Mark下,日后研究。
5 楼 minds.buffer 2010-10-26  
才刚在group里面看到你的ID哦.. 没想到我要用service了 搜了一下 service的文章就找到这里了
文写的不错 挺有用的 继续努力 XD
4 楼 habzyhs 2010-07-20  
用来研究service的生命周期是蛮不错的,主要是清晰明了。但是没看出来showNotification()这个方法起什么用处。
3 楼 蒙太奇 2010-03-18  
想搞业余android开发,但是目前连gPhone都买不起。
谢谢你的教程!
2 楼 haric 2010-01-31  
呵呵 。。。 充满故事性
1 楼 dandy 2010-01-12  
后台的幽灵,名字不错嘛!

相关推荐

    Android2.2 API中文文档

    Android2.2 API中文文档 (1) —— TextView (2) —— EditText (3) —— AccessibilityService (4) —— Manifest (5) —— View (6) —— ImageView (7) —— ImageButton (8) —— ...

    Android2.2 API 中文文档系列(3) —— AccessibilityService

    Android2.2 API 中文文档,注意这里只有AccessibilityService控件的,请关注http://over140.cnblogs.com/的更新。

    好的-Android2.2 API中文文档——AccessibilityService.doc

    Android2.2 API中文文档——AccessibilityService.doc

    android_2.2系统自带软件整理目录(新)

    AccountProvider.apk Service Account Provider(帐户存储) ApplicationsProvider.apk com.android.providers.applications(应用程序存储) AutoPowerOff.apk backupandrestore.apk 备份与还原 Bluetooth.apk ...

    Android开发案例驱动教程 配套代码

    《Android开发案例驱动教程》 配套代码。 注: 由于第12,13,14章代码太大,无法上传到一个包中。 这三节代码会放到其他压缩包中。 作者:关东升,赵志荣 Java或C++程序员转变成为Android程序员 采用案例驱动模式...

    Android in Action

    2.2 Fitting the pieces together 2.3 Building an Android application in Eclipse 2.4 The Android Emulator 2.5 Debugging 2.6 Summary Part 2 Exercising the Android SDK 3 User interfaces 3.1 Creating the...

    Android Google 手机程序设计教程

    2.2 安裝 Android 的 SDK 2.3 安裝 Eclipse 整合開發環境 2.4 在 Eclipse 中安裝 Android 外掛元件 第 3 章開發您的第一個程式 3.1 建立 Android 程式專案 3.2 修改 XML 介面 3.3 執行專案程式 3.4 程式執行...

    Android入门到精通源代码.

    2.5 使用Eclipse开发Android应用程序 2.5.1 使用Eclipse创建Android项目 2.5.2 Eclipse中Android项目架构 2.5.3 Eclipse中Android项目的调试和运行 第3章 Android中的Activity 3.1 Activity的作用 3.2 单Activity的...

    [Android应用开发记录-字幕播放器(5)完善]附属工程,源码

    (Android2.2以上版本) 4.拔掉耳机线时自动暂停(Android2.2以上版本) 5.在【正在进行中】画面中表示启动用快捷方式 6.改善(没有解决)定位歌词不准确(选中的歌词的前面一段时间不能播放)

    Android代码-sample-googleassistant

    Google Assistant SDK for ...Android Studio 2.2 . Android Things compatible board. AIY Projects Voice Kit or supported microphone and speaker (See audio configuration). Google API Console Project. Run

    疯狂Android讲义源码

     1.3.2 使用Android模拟器  (Emulator) 14  1.3.3 使用DDMS进行调试 15  1.3.4 Android Debug Bridge(ADB)  的用法 16  1.3.5 使用DX编译Android应用 18  1.3.6 使用Android Asset Packaging  Tool...

    android-framework-hal

    1.5 使用 Android emulator 1.6 Vanilla Kernel & Android Kernel 编译 2.HAL 技术详解 2.1 HAL 的意义与二进位布署(Binary File Deploy) 2.2 Service与Manager的意义与用途 2.3 libhardware 与 HAL API 2.4 Stub & ...

    精通ANDROID 3(中文版)1/2

    25.2.1 Android2.2之前的多点触摸  25.2.2 自Android 2.2开始的多点触摸  25.3 触摸地图  25.4 手势  25.4.1 捏合手势  25.4.2 GestureDetector和OnGestureListener  25.4.3 自定义手势  25.4.4 ...

    《Android高级编程》

    2.2 面向移动设备的开发 2.2.1 关于硬件设计的考虑事项 2.2.2 考虑用户环境 2.2.3 Android开发 2.3 To-Do List示例 2.4 Android开发工具 2.4.1 Android模拟器 2.4.2 Dalvik调试监控服务(DDMS) 2.4.3 Android调试桥...

    android开发入门与实战(下)

    10.2 使用Service 10.3 Service的生命周期 10.4 实例学习Service 10.4.1 精彩实例一——定时提醒 10.4.2 精彩实例二——音乐播放器 10.5 本章小结 第11章 循序渐进——开发Android应用的基本步骤 11.1 兵马未动粮草...

    android 开发技巧合集

    0、ANDROID常用类库说明 6 1、ANDROID文件系统与应用程序架构 7 ...2.3.2、如何使用Service 27 2.3.3、Service的生命周期 32 2.3.4、判断服务开启状态 33 2.3.5、获取启动的服务 34 2.4、CONTENT PROVIDER 35

    android系统原理及开发要点详解

     2.2 Android源代码的开发环境 18  2.2.1 Android源代码的获取和提交 18  2.2.2 Android源代码结构 21  2.2.3 编译 24  2.2.4 系统的运行 25  2.3 Android SDK的开发环境 32  2.3.1 SDK的结构 32  2.3.2 ...

    Android天气预报widget的设计与实现毕业论文

    2.2 开发工具ECLIPSE介绍 7 第3章 ANDROID程序设计基础 10 3.1 系统结构 10 3.1.1 应用程序 10 3.1.2 应用程序框架 11 3.1.3 库和运行环境 12 3.2 ANDROID应用程序组成 12 3.2.1 Avtivity介绍 12 3.2.2 Broadcast ...

Global site tag (gtag.js) - Google Analytics