当前位置: 代码迷 >> Android >> 稳扎稳打_Android开发课[5]_Service学习
  详细解决方案

稳扎稳打_Android开发课[5]_Service学习

热度:63   发布时间:2016-04-28 01:43:28.0
步步为营_Android开发课[5]_Service学习

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

  相关解决方案