Android04--Android服务

标签: Android


undefined

Service是Android 系统中的四大组件之一(Activity、Service、BroadcastReceiver、ContentProvider),它跟Activity的级别差不多,但不能自己运行只能后台运行,并且可以和其他组件进行交互。

Service可以在很多场合的应用中使用,比如后台播放音乐,后台记录地理信息位置的改变等等。

在Activity里对Service的控制有4种,分别是:启动服务、停止服务、绑定服务、取消绑定服务。

启动、停止服务 #

context.startService() 启动流程:

context.startService() 
-> onCreate()
-> onStartCommand()
-> Service running
-> context.stopService()
-> onDestroy()
-> Service stop 

1)如果Service还没有运行,则android先调用onCreate(),然后调用onStartCommand()
2)如果Service已经运行,则只调用onStartCommand(),所以一个Service的onStartCommand()方法可能会重复调用多次;
3)如果stopService的时候会直接onDestroy(),如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行,该Service的调用者再启动起来后可以通过stopService关闭Service;
4)所以调用startService的生命周期为:onCreate --> onStartCommand (可多次调用) --> onDestroy

注意:onStartCommand()之前的API也写作onStart(),根据官方文档描述,在API5后,onStart()不建议使用:

http://developer.android.com/reference/android/app/Service.html 

onStart(Intent intent, int startId)

This method was deprecated in API level 5. Implement onStartCommand(Intent, int, int) instead.
onStartCommand(Intent intent, int flags, int startId)

Called by the system every time a client explicitly starts the service by calling startService(Intent), providing the arguments it supplied and a unique integer token representing the start request.

绑定、取消绑定服务 #

context.bindService()启动流程:

context.bindService()
-> onCreate()
-> onBind()
-> Service running
-> onUnbind()
-> onDestroy()
-> Service stop

onBind()将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service的实例、运行状态或其他操作。这个时候把调用者(Context,例如Activity)会和Service绑定在一起,Context退出了,Service就会调用onUnbind->onDestroy相应退出。

所以调用bindService的生命周期为:onCreate --> onBind(只一次,不可多次绑定) --> onUnbind --> onDestory

在Service每一次的开启关闭过程中,只有onStartCommand()可被多次调用(通过多次startService调用),其他onCreate,onBind,onUnbind,onDestory在一个生命周期中只能被调用一次。

服务的生命周期 #

Service里比较重要的有onCreate()onStartCommand()onDestroy()三个方法。

当第一次启动Service时,先后调用了onCreate()onStartCommand()这两个方法;当停止Service时,则执行onDestroy()方法。

这里需要注意的是,如果Service已经启动了,当我们再次启动Service时,不会在执行onCreate()方法,而是直接执行onStartCommand()方法。

BindService和Started Service都是Service,有什么地方不一样呢?

  1. Started Service中使用StartService()方法来进行方法的调用,调用者和服务之间没有联系,即使调用者退出了,服务依然在进行。
  2. BindService中使用bindService()方法来绑定服务,调用者和绑定者绑在一起,调用者一旦退出服务也就终止了。

Service启动、停止、绑定、取消绑定生命周期演示 #

activity_main.xml

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="启动服务"
    android:id="@+id/btnStart"
    android:layout_marginTop="99dp"
    android:layout_below="@+id/textView"
    android:layout_toRightOf="@+id/textView"
    android:layout_toEndOf="@+id/textView" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="停止服务"
    android:id="@+id/btnStop"
    android:layout_alignTop="@+id/btnStart"
    android:layout_toRightOf="@+id/btnStart"
    android:layout_toEndOf="@+id/btnStart" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="绑定服务"
    android:id="@+id/btnBind"
    android:layout_marginTop="159dp"
    android:layout_below="@+id/textView"
    android:layout_toRightOf="@+id/textView"
    android:layout_toEndOf="@+id/textView" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="取消绑定服务"
    android:id="@+id/btnUnbind"
    android:layout_alignTop="@+id/btnBind"
    android:layout_toRightOf="@+id/btnBind"
    android:layout_toEndOf="@+id/btnBind" />

页面分别有启动服务、停止服务、绑定服务、取消绑定服务4个按钮。

MyService.java:

package com.a52fhy.learnservicebind;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

/**
 * Created by YJC on 2016/9/15 015.
 */
public class MyService  extends Service{

    @Override
    public void onCreate() {
        Log.i("Service", "onCreate");
        super.onCreate();
    }

    //不建议使用onStart,使用onStartCommand代替
    @Override
    public void onStart(Intent intent, int startId) {
        Log.i("Service", "onStart");
        super.onStart(intent, startId);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("Service", "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.i("Service", "onBind");
        return new Binder();
    }

    @Override
    public boolean onUnbind(Intent intent){
        Log.i("Service", "onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public void onRebind(Intent intent) {
        Log.i("Service", "onRebind");
        super.onRebind(intent);
    }

    @Override
    public void onDestroy() {
        Log.i("Service", "onDestroy");
        super.onDestroy();
    }
}

MainActivity.java

package com.a52fhy.learnservicebind;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class MainActivity extends AppCompatActivity implements View.OnClickListener, ServiceConnection {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.btnStart).setOnClickListener(this);
        findViewById(R.id.btnStop).setOnClickListener(this);
        findViewById(R.id.btnBind).setOnClickListener(this);
        findViewById(R.id.btnUnbind).setOnClickListener(this);
    }

    /**
     * Called when a view has been clicked.
     *
     * @param v The view that was clicked.
     */
    @Override
    public void onClick(View v) {

        Intent intent = new Intent(this, MyService.class);

        switch (v.getId()){
            case R.id.btnStart:
                Log.i("Service", "startService");
                startService(intent);
                break;
            case R.id.btnStop:
                Log.i("Service", "stopService");
                stopService(intent);
                break;
            case R.id.btnBind:
                Log.i("Service", "bindService");
                bindService(intent, this, Context.BIND_AUTO_CREATE);
                break;
            case R.id.btnUnbind:
                Log.i("Service", "unbindService");
                unbindService(this);
                break;
        }
    }

    /**
     * Called when a connection to the Service has been established, with
     * the {@link IBinder} of the communication channel to the
     * Service.
     *
     * @param name    The concrete component name of the service that has
     *                been connected.
     * @param service The IBinder of the Service's communication channel,
     */
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.i("Service",  "onServiceConnected");
    }


    @Override
    public void onServiceDisconnected(ComponentName name) {
        //进程崩溃或被杀会触发
        Log.i("Service",  "onServiceDisconnected");
    }
}

到AndroidManifest.xml注册下服务:

<service
    android:name=".MyService"
    android:enabled="true">
</service>

1)点击启动服务:

com.a52fhy.learnservicebind I/Service: startService
com.a52fhy.learnservicebind I/Service: onCreate
com.a52fhy.learnservicebind I/Service: onStartCommand
com.a52fhy.learnservicebind I/Service: onStart

2)再次点击启动服务:

com.a52fhy.learnservicebind I/Service: startService
com.a52fhy.learnservicebind I/Service: onStartCommand
com.a52fhy.learnservicebind I/Service: onStart

3)停止服务:

com.a52fhy.learnservicebind I/Service: stopService
com.a52fhy.learnservicebind I/Service: onDestroy

4)再次点击停止服务:

com.a52fhy.learnservicebind I/Service: stopService

5)绑定服务:

com.a52fhy.learnservicebind I/Service: bindService
com.a52fhy.learnservicebind I/Service: onCreate
com.a52fhy.learnservicebind I/Service: onBind
com.a52fhy.learnservicebind I/Service: onServiceConnected

6)再次点击绑定服务:

com.a52fhy.learnservicebind I/Service: bindService

7)取消绑定服务:

com.a52fhy.learnservicebind I/Service: unbindService
com.a52fhy.learnservicebind I/Service: onUnbind
com.a52fhy.learnservicebind I/Service: onDestroy

8)点击绑定服务,然后返回键退出Activity:

com.a52fhy.learnservicebind I/Service: bindService
com.a52fhy.learnservicebind I/Service: onCreate
com.a52fhy.learnservicebind I/Service: onBind
com.a52fhy.learnservicebind I/Service: onServiceConnected

com.a52fhy.learnservicebind I/Service: onUnbind
com.a52fhy.learnservicebind I/Service: onDestroy

Service示例:播放音乐 #

MyService.java

package com.a52fhy.learnservice;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.Nullable;

/**
 * Created by YJC on 2016/9/15 015.
 */
public class MyService extends Service {

    private MediaPlayer mediaPlayer;

    @Override
    public void onCreate() {
        super.onCreate();

        if(mediaPlayer == null){
            mediaPlayer = MediaPlayer.create(this, R.raw.tmp); //打开音乐文件
            mediaPlayer.setLooping(false);
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        if(intent == null){
            return 0;
        }

        //获取参数
        Bundle bundle = intent.getExtras();
        Integer op = bundle.getInt("op");

        switch (op){
            case 1:
                play();
                break;
            case 2:
                pause();
                break;
            case 3:
                stop();
                break;
        }

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        if(mediaPlayer != null){
            mediaPlayer.stop();
            mediaPlayer.release();
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    /**
     * 播放音乐
     */
    public void play(){
        if(!mediaPlayer.isPlaying()){
           mediaPlayer.start();
        }
    }

    /**
     * 暂停音乐
     */
    public void pause(){
        if(mediaPlayer != null && mediaPlayer.isPlaying()){
            mediaPlayer.pause();
        }
    }

    /**
     * 停止音乐
     */
    public void stop(){
        if(mediaPlayer != null){
            mediaPlayer.stop();

            try{
                mediaPlayer.prepare();// 在调用stop后如果需要再次通过start进行播放,需要之前调用prepare函数
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

Activity:

package com.a52fhy.learnservice;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Intent intent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.btnPlay).setOnClickListener(this);
        findViewById(R.id.btnPause).setOnClickListener(this);
        findViewById(R.id.btnStop).setOnClickListener(this);
        findViewById(R.id.btnClose).setOnClickListener(this);
        findViewById(R.id.btnExit).setOnClickListener(this);
    }


    /**
     * Called when a view has been clicked.
     *
     * @param v The view that was clicked.
     */
    @Override
    public void onClick(View v) {
        Integer id = v.getId();

        Integer op = -1;
        intent = new Intent(this,MyService.class);

        switch (id){
            case R.id.btnPlay://play
                op = 1;
                break;
            case R.id.btnPause: //pause
                op = 2;
                break;
            case R.id.btnStop: //stop
                op = 3;
                break;
            case R.id.btnClose:
                this.finish();
                break;
            case R.id.btnExit:
                stopService(intent);
                this.finish();
                break;
        }

        //传递参数
        Bundle bundle = new Bundle();
        bundle.putInt("op", op);
        intent.putExtras(bundle);

        startService(intent);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if(intent != null){
            stopService(intent);
        }
    }
}

到AndroidManifest.xml注册下服务:

<service
    android:name=".MyService"
    android:enabled="true">
</service>

参考:
Android Service 服务(一)—— Service - IT-Homer - 博客频道 - CSDN.NET
http://blog.csdn.net/sunboy_2050/article/details/7364024

Build by Loppo 0.6.6