Focus on technology, enjoy life!—— QQ:804212028
浏览链接:http://blog.csdn.net/y18334702058/article/details/44624305
- 主题:Service服务相关内容
-Android开发中Service服务是非常重要滴,也是有一定难度滴,不怕,我们一起一步一步来看:
一、 Service简介
Service是android系统中的四大组件之一(Activity、Service、BroadcastReceiver、ContentProvider),它跟Activity的级别差不多,但不能自己运行只能后台运行,并且可以和其他组件进行交互。service可以在很多场合的应用中使用,比如播放多媒体的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,再或者在后台记录你地理信息位置的改变等等,总之服务总是藏在后台的。
Service的启动有两种方式:context.startService() 和 context.bindService()
二、如何开发一个Service组件?
第一步:继承Service类 public class SMSService extends Service {}
第二步:在AndroidManifest.xml文件中的节点里对服务进行配置:
第三步:启动服务
启动服务方法一:context.startService():调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。
步骤:
context.startService() 启动流程: context.startService() -> onCreate()
-> onStart() -> Service running -> context.stopService() -> onDestroy() -> Service stop如果Service还没有运行,则android先调用onCreate(),然后调用onStart();
如果Service已经运行,则只调用onStart(),所以一个Service的onStart方法可能会重复调用多次。
如果stopService的时候会直接onDestroy,如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行,该Service的调用者再启动起来后可以通过stopService关闭Service。
所以调用startService的生命周期为:onCreate –> onStart (可多次调用) –> onDestroy
启动服务方法二:context.bindService():调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点
context.bindService()启动流程: context.bindService() -> onCreate() ->
onBind() -> Service running -> onUnbind() -> onDestroy() ->
Service stop
onBind()将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service的实例、运行状态或其他操作。这个时候把调用者(Context,例如Activity)会和Service绑定在一起,Context退出了,Srevice就会调用onUnbind->onDestroy相应退出。
所以调用bindService的生命周期为:onCreate –> onBind(只一次,不可多次绑定) –> onUnbind –>
onDestory。
在Service每一次的开启关闭过程中,只有onStart可被多次调用(通过多次startService调用),其他onCreate,onBind,onUnbind,onDestory在一个生命周期中只能被调用一次。
三、 Service生命周期
Service生命周期很简单,它只继承了onCreate()、onStart()、onDestroy()三个方法
当我们第一次启动Service时,先后调用了onCreate()、onStart()这两个方法;当停止Service时,则执行onDestroy()方法。
这里需要注意的是,如果Service已经启动了,当我们再次启动Service时,不会在执行onCreate()方法,而是直接执行onStart()方法。
它可以通过Service.stopSelf()方法或者Service.stopSelfResult()方法来停止自己,无论调用了多少次的启动服务方法,只要调用一次stopService()方法便可以停止服务。
onCreate():
该方法在服务被创建时调用,该方法只会被调用一次,无论调用多少次startService()或bindService()方法,服务也只被创建一次。
onDestroy():
该方法在服务被终止时调用。与采用Context.startService()方法启动服务有关的生命周期方法
onStart():
只有采用Context.startService()方法启动服务时才会回调该方法。该方法在服务开始运行时被调用。多次调用startService()方法尽管不会多次创建服务,但onStart() 方法会被多次调用。
onBind():
只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用Context.bindService()方法并不会导致该方法被多次调用。
onUnbind():
只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务解除绑定时被调用
生命周期图:
四:Service和Thread的区别?
答:servie是系统的组件,它由系统进程托管(service manager);它们之间的通信类似于client和server,是一种轻量级的ipc通信,这种通信的载体是binder,它是在linux层交换信息的一种ipc。而thread是由本应用程序托管。
1).Thread:Thread是程序执行的最小单元,它是分配CPU的基本单位。可以用 Thread 来执行一些异步的操作。
2).Service:Service是android的一种机制,当它运行的时候如果是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的。如:onCreate,onStart 这些函数在被系统调用的时候都是在主进程的 main 线程上运行的。如果是Remote Service,那么对应的 Service 则是运行在独立进程的 main 线程上。因此请不要把 Service 理解成线程,它跟线程半毛钱的关系都没有!
既然这样,那么我们为什么要用Service呢?
其实这跟android的系统机制有关,我们先拿Thread来说。Thread的运行是独立于Activity的,也就是说当一个Activity
被finish之后,如果你没有主动停止Thread或者Thread里的run方法没有执行完毕的话,Thread也会一直执行。因此这里会出现一个问题:当Activity被finish之后,你不再持有该Thread的引用。另一方面,你没有办法在不同的
Activity 中对同一 Thread 进行控制。举个例子:如果你的 Thread 需要不停地隔一段时间就要连接服务器做某种同步的话,该 Thread 需要在 Activity
没有start的时候也在运行。这个时候当你 start 一个 Activity 就没有办法在该 Activity 里面控制之前创建的
Thread。因此你便需要创建并启动一个 Service ,在 Service 里面创建、运行并控制该
Thread,这样便解决了该问题(因为任何 Activity 都可以控制同一 Service,而系统也只会创建一个对应 Service
的实例)。因此你可以把Service想象成一种消息服务,而你可以在任何有Context的地方调用Context.startService、Context.stopService、Context.bindService,Context.unbindService,来控制它,你也可以在
Service 里注册 BroadcastReceiver,在其他地方通过发送 broadcast 来控制它,当然这些都是 Thread
做不到的。
Service使用实例(用Service后台播放音乐)
main.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="Welcome to Andy's blog!" android:textSize="16sp"/> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="音乐播放服务"/> <Button android:id="@+id/startMusic" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="开启音乐播放服务"/> <Button android:id="@+id/stopMusic" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="停止音乐播放服务"/> <Button android:id="@+id/bindMusic" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="绑定音乐播放服务"/> <Button android:id="@+id/unbindMusic" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="解除 ——绑定音乐播放服务"/></LinearLayout>
MusicServiceActivity源码:
package com.example.service;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.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.Toast;public class MusicServiceActivity extends Activity { //为日志工具设置标签 private static String TAG = "--------------"; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //输出Toast消息和日志记录 Toast.makeText(this, "MusicServiceActivity", Toast.LENGTH_SHORT).show(); Log.e(TAG, "MusicServiceActivity"); initlizeViews(); } private void initlizeViews(){ Button btnStart = (Button)findViewById(R.id.startMusic); Button btnStop = (Button)findViewById(R.id.stopMusic); Button btnBind = (Button)findViewById(R.id.bindMusic); Button btnUnbind = (Button)findViewById(R.id.unbindMusic); //定义点击监听器 OnClickListener ocl = new OnClickListener() { @Override public void onClick(View v) { //显示指定 intent所指的对象是个 service Intent intent = new Intent(MusicServiceActivity.this,MusicService.class); switch(v.getId()){ case R.id.startMusic: //开始服务 startService(intent); break; case R.id.stopMusic: //停止服务 stopService(intent); break; case R.id.bindMusic: //绑定服务 bindService(intent, conn, Context.BIND_AUTO_CREATE); break; case R.id.unbindMusic: //解绑服务 unbindService(conn); break; } } }; //绑定点击监听 btnStart.setOnClickListener(ocl); btnStop.setOnClickListener(ocl); btnBind.setOnClickListener(ocl); btnUnbind.setOnClickListener(ocl); } //定义服务链接对象 final ServiceConnection conn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { Toast.makeText(MusicServiceActivity.this, "MusicServiceActivity onSeviceDisconnected" , Toast.LENGTH_SHORT).show(); Log.e(TAG, "MusicServiceActivity onSeviceDisconnected"); } @Override public void onServiceConnected(ComponentName name, IBinder service) { Toast.makeText(MusicServiceActivity.this, "MusicServiceActivity onServiceConnected" ,Toast.LENGTH_SHORT).show(); Log.e(TAG, "MusicServiceActivity onServiceConnected"); } };}
MusicService.java源码:
package com.example.service;import android.app.Service;import android.content.Intent;import android.media.MediaPlayer;import android.os.IBinder;import android.util.Log;import android.widget.Toast;public class MusicService extends Service { //为日志工具设置标签 private static String TAG = "--------------"; //定义音乐播放器变量 private MediaPlayer mPlayer; //该服务不存在需要被创建时被调用,不管startService()还是bindService()都会启动时调用该方法 @Override public void onCreate() { Toast.makeText(this, "MusicSevice onCreate()" , Toast.LENGTH_SHORT).show(); Log.e(TAG, "MusicSerice onCreate()"); mPlayer = MediaPlayer.create(getApplicationContext(), R.raw.music); //设置可以重复播放 mPlayer.setLooping(true); super.onCreate(); } @Override public void onStart(Intent intent, int startId) { Toast.makeText(this, "MusicSevice onStart()" , Toast.LENGTH_SHORT).show(); Log.e(TAG, "MusicSerice onStart()"); mPlayer.start(); super.onStart(intent, startId); } @Override public void onDestroy() { Toast.makeText(this, "MusicSevice onDestroy()" , Toast.LENGTH_SHORT).show(); Log.e(TAG, "MusicSerice onDestroy()"); mPlayer.stop(); super.onDestroy(); } //其他对象通过bindService 方法通知该Service时该方法被调用 @Override public IBinder onBind(Intent intent) { Toast.makeText(this, "MusicSevice onBind()" , Toast.LENGTH_SHORT).show(); Log.e(TAG, "MusicSerice onBind()"); mPlayer.start(); return null; } //其它对象通过unbindService方法通知该Service时该方法被调用 @Override public boolean onUnbind(Intent intent) { Toast.makeText(this, "MusicSevice onUnbind()" , Toast.LENGTH_SHORT).show(); Log.e(TAG, "MusicSerice onUnbind()"); mPlayer.stop(); return super.onUnbind(intent); }}
最后在AndroidManifest.xml配置文件中添加对Service的注册
<service android:name=".MusicService"/>
就算我们退出程序回到手机主界面,由于该服务还在后台运行着,音乐还是不会停止播放,这样我们就可以边听歌曲,边聊QQ了。
Focus on technology, enjoy life!—— QQ:804212028
浏览链接:http://blog.csdn.net/y18334702058/article/details/44624305