手机是人们生活中不可或缺的一个有用工具。我们在使用手机时,往往是多线程的,而且是会突然间断的。比如我们会一边浏览网页,一边听MP3。或者正在发短信的时候,突然打进来电话。这样我们必定会离开当前的用户界面。比如你会关闭MP3歌曲列表,去发短信,所以往往就需要有些程序在后台完成,暂时脱离屏幕。这时就可以用到Android中的Service
下面会用一个播放MP3的小应用来体会一下Android的Service
什么是Service
Android引入了Service的概念是为了处理后台进程。Service不实现任何用户界面。最常见的例子如:媒体播放器程序,它可以在转到后台运行的时候仍然能保持播放歌曲;或者如文件下载程序,它可以在后台执行文件的下载。
它跟Activity的级别差不多,但是他不能自己运行,需要通过某一个Activity或者其他Context对象来调用, Context.startService() 和 Context.bindService()。
Service的生命周期
Service的生命周期方法比Activity少一些,只有onCreate, onStart, onDestroy
我们有两种方式启动一个Service,他们对Service生命周期的影响是不一样的。两种启动Service的方式有所不同。这里要说明一下的是如果你在Service的onCreate或者onStart做一些很耗时间的事情,最好在Service里启动一个线程来完成,因为Service是跑在主线程中,会影响到你的UI操作或者阻塞主线程中的其他事情。
创建一个Service
Android中已经定义了一个 ‘Service’类,所有其他的Service都继承于该类。Service类中定义了一系列的生命周期相关的方法,如: onCreate(), onStart(), onDestroy()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
长期推荐成都知名外企(英语好 C++ JAVA)
mail to:[email protected]
http://woshizn.iteye.com/blog/1195498
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
启动Service
有了 Service 类我们如何启动他呢,有两种方法:
Context.startService()
Context.bindService()
在同一个应用任何地方调用 startService() 方法就能启动 Service 了,然后系统会回调 Service 类的 onCreate() 以及 onStart() 方法。这样启动的 Service 会一直运行在后台,直到 Context.stopService() 或者 selfStop() 方法被调用。另外如果一个 Service 已经被启动,其他代码再试图调用 startService() 方法,是不会执行 onCreate() 的,但会重新执行一次 onStart() 。
另外一种 bindService() 方法的意思是,把这个 Service 和调用 Service 的客户类绑起来,如果调用这个客户类被销毁,Service 也会被销毁。用这个方法的一个好处是,bindService() 方法执行后 Service 会回调上边提到的 onBind() 方发,你可以从这里返回一个实现了 IBind 接口的类,在客户端操作这个类就能和这个服务通信了,比如得到 Service 运行的状态或其他操作。如果 Service 还没有运行,使用这个方法启动 Service 就会 onCreate() 方法而不会调用 onStart()。
用其他方式启动 Service
其实不光能从 Activity 中启动 Service ,还有一个很有用的方法是接收系统的广播,这就要用到 Receiver 。在 Mainfest 文件中配置你得 Receiver 能接收什么样的广播消息,那么即使你得程序没有显示给用户,你的 Service 也能启动。你要做的就是继承 android.content.BroadcastReceiver ,然后实现 onReceive(Context context, Intent intent) 方法,就可以启动你得 Service 了。这里不能 bindService 因为一个 Receiver 是一个短暂存在的对象,所以 bind 是没有什么意义的。
与 Service 通信并且让它持续运行
如果我们想保持和 Service 的通信,又不想让 Service 随着 Activity 退出而退出呢?
可以先 startService() 再 bindService()。当不需要绑定的时候再执行 unbindService() 方法,执行这个方法只会触发 Service 的 onUnbind() 而不会把这个 Service 销毁。这样就可以既保持和 Service 的通信,也不会随着 Activity 销毁而销毁了。
提高 Service 优先级
Android 系统对于内存管理有自己的一套方法,为了保障系统有序稳定的运行,系统内部会自动分配,控制程序的内存使用。当系统觉得当前的资源非常有限的时候,为了保证一些优先级高的程序能运行,就会杀掉一些他认为不重要的程序或者服务来释放内存。这样就能保证真正对用户有用的程序仍然再运行。如果你的 Service 碰上了这种情况,多半会先被杀掉。但如果你增加 Service 的优先级就能让他多留一会,我们可以用 setForeground(true) 来设置 Service 的优先级。
为什么是 foreground ? 默认启动的 Service 是被标记为 background,当前运行的 Activity 一般被标记为 foreground,也就是说你给 Service 设置了 foreground 那么他就和正在运行的 Activity 类似优先级得到了一定的提高。当让这并不能保证你得 Service 永远不被杀掉,只是提高了他的优先级。
MP3TestActivity.java提供控制界面
package com.android.mp3test;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;public class MP3TestActivity extends Activity { private Button start; private Button stop; private Intent i; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); start = (Button) this.findViewById(R.id.start); stop = (Button) this.findViewById(R.id.stop); // 指向MP3播放Service的action i = new Intent("com.kennan.android.music"); start.setOnClickListener(startListener); stop.setOnClickListener(stopListener); } private OnClickListener startListener = new OnClickListener() { public void onClick(View v) {// 开始服务 MP3TestActivity.this.startService(i); } }; private OnClickListener stopListener = new OnClickListener() { public void onClick(View v) {// 结束服务 MP3TestActivity.this.stopService(i); } };}
MusicService.java提供MP3播放功能,在开启播放后,可以尝试退出应用程序界面。看是否音乐还在继续播放。
package com.android.mp3test;import android.app.Service;import android.content.Intent;import android.media.MediaPlayer;import android.os.IBinder;public class MusicService extends Service { private MediaPlayer player; public IBinder onBind(Intent arg0) { return null; } public void onStart(Intent intent, int startId) { super.onStart(intent, startId);// 在服务开始时,启动MP3播放 player = MediaPlayer.create(this, R.raw.music); player.start(); } public void onDestroy() {// 在服务消灭时,关闭MP3播放 player.stop(); super.onDestroy(); }}
layout/mean.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" ><TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <Button android:id="@+id/start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/start" /> <Button android:id="@+id/stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/stop" /> </LinearLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.mp3test" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MP3TestActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name="MusicService"> <intent-filter> <action android:name="com.kennan.android.music" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </service> </application> <uses-sdk android:minSdkVersion="4" /></manifest>
参考项目结构