Android 之 Service 详解

前言:
Android四大组件,Activity,Service,BroadcastReceiver和ContentProvider。最近在工作中遇到很多网络处理操作都用线程来处理,想想好像Service就是用来进行这类操作的,这两者的区别和使用场合有点模糊了,最近主要研究了service并进行总结,以备后用。

一.Service 定义

1.根据官网对于Service的定义翻译为中文:

Service(服务)是一个没有用户界面的在后台运行执行耗时操作的应用组件。其他应用组件能够启动Service,并且当用户切换到另外的应用场景,Service将持续在后台运行。另外,一个组件能够绑定到一个service与之交互(IPC机制),例如,一个service可能会处理网络操作,播放音乐,操作文件I/O或者与内容提供者(content provider)交互,所有这些活动都是在后台进行。

2.加深对Service的理解,可以看下这段描述:

(1).A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of.

(2).A Service is not a thread. It is not a means itself to do work off of the main thread (to avoid Application Not Responding errors).

(个人英语一般,但总感觉这段描述的英文好像有问题)
可以译为:
(1).Service并不是一个单独的进程,Service对象如果不明确指明,不意味着运行在它自身的进程中,它运行在Application的系统进程中,是进程的一部分。
(2).Service不是一个线程,不意味着可以在主线程之外执行其它工作(避免应用ANR)。

关于第二点需要重点说明一下:网上的文章很多都把耗时的操作直接放在Service的onStart方法中,而且没有强调这样会出现Application Not Responding!Service不是一个线程,不能直接处理耗时的操作,如果非要在Service中进行耗时处理,就必须开启一个单独的线程来处理或者采用IntentService来实现。
关于IntentService,后面会加以总结。

二. 与Activity的区别

1.不能与用户交互,对用户透明。
2.不能自己启动。
3.当我们退出应用时,Service进程并没有结束,它仍然可以在系统后台运行。

Service有两种状态:“启动的”和“绑定”。就是当调用服务的startService()和bindService()之后出现的状态。可以简单理解为:”started”和“binded”。

三 Service的启动

有两种方式可以启用一个Service。

a、Context.startService()
使用这个方法时,service与启动者是没有关系的,只是单纯的启动service,若启动者退出了,service依旧在后台运行。(如音乐播放,即使退出了程序,音乐还在播放着)

b、Context.bindService()
使用此方法时,顾名思义,就是把启动者与service绑定在一起了,启动者退出,service也跟着停止。

四 Service的生命周期

服务启用的方式不同,生命周期也不一样.

1.startService()方式启用的Service:

onCreate()—>>onStart()—>>onDestroy();

这里写图片描述

2.bindService()方式启用的Service:

onCreate()—>>onBind()—>>onUnBind()—>>onDestroy();

这里写图片描述

两种方式下的Service生命周期如下图展示:
这里写图片描述

五 一个后台开启音乐的ServiceDemo

类似的Demo网上很多,随便改了一个,写在下面,仅供参考:

1.MusicService.java
继承Service类,必须重写onBind()方法。
Service类的业务处理,写在onCreate()方法内部。

注意:R.raw.ccnnian 要在Res文件夹下面创建raw文件夹,将ccnnian(匆匆那年.mp3)放进去,修改名字。
package com.elvis.musicService;


import com.example.servicedemo.R;

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
{
    //为日志工具设置标签
    String tag = "MusicService";



    //定义音乐播放器变量
    MediaPlayer mPlayer;


    //其他对象通过bindService方法通知该Service时该方法会被调用
    @Override
    public IBinder onBind(Intent arg0) 
    {
        // TODO Auto-generated method stub
        Toast.makeText(this, "MusicService onBind() ",
                Toast.LENGTH_LONG).show();

        Log.i(tag,"MusicService onBind()");

        mPlayer.start();

        return null;        
    }


    //其他对象通过unbindService方法通知该Service时该方法会被调用
    @Override
    public boolean onUnbind(Intent intent) {
        // TODO Auto-generated method stub
        Toast.makeText(this, "MusicService onUnbind()   ",
                Toast.LENGTH_LONG).show();
        Log.i(tag, "MusicService onUnbind()");
        mPlayer.stop();

        return false;
    }




    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        Toast.makeText(this, "MusicService onCreate()   ",
                Toast.LENGTH_LONG).show();
        //创建一个音乐播放器

        //mPlayer = MediaPlayer.create(getApplicationContext(),R.);
        mPlayer = MediaPlayer.create(getApplicationContext(), R.raw.ccnnian);


        mPlayer.setLooping(true);

        Log.i(tag, "MusicService onCreate()");
        super.onCreate();
    }


    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub

        Toast.makeText(this, "MusicSevice onDestroy()"
                , Toast.LENGTH_SHORT).show();
        Log.e(tag, "MusicService onDestroy()");

        mPlayer.stop();
        super.onDestroy();
    }


    @Override
    @Deprecated
    public void onStart(Intent intent, int startId) {
        // TODO Auto-generated method stub
        Toast.makeText(this, "MusicSevice onStart()"
                , Toast.LENGTH_SHORT).show();
        Log.e(tag, "MusicSerice onStart()");

        mPlayer.start();
        super.onStart(intent, startId);
    }





}

2.ServiceActivity.java

两种方式开启服务。注意Intent intent = new Intent(ServiceActivity.this,MusicService.class);
通过Intent对象实现Service启动。
package com.example.servicedemo;

import com.elvis.musicService.MusicService;

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

public class ServiceActivity extends Activity {

    //为日志工具设置标签
    private static String tag = "MusicService";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_service);
         Toast.makeText(this, "ServiceActivity",
                    Toast.LENGTH_LONG).show();
            Log.e(tag, "MusicServiceActivity");
        initView();


    }


    //定义服务链接对象
    final ServiceConnection conn = new ServiceConnection()
    {

        @Override
        public void onServiceConnected(ComponentName arg0, IBinder arg1) {
            // TODO Auto-generated method stub
             Toast.makeText(ServiceActivity.this, "MusicServiceActivity onServiceConnected"
                        ,Toast.LENGTH_SHORT).show();
                Log.e(tag, "MusicServiceActivity onServiceConnected");
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            // TODO Auto-generated method stub
            Toast.makeText(ServiceActivity.this, "MusicServiceActivity onSeviceDisconnected"
                    , Toast.LENGTH_SHORT).show();
            Log.e(tag, "MusicServiceActivity onSeviceDisconnected");
        }

    };







    private void initView()
    {
        Button btnStart = (Button)findViewById(R.id.Button01);
        Button btnStop = (Button)findViewById(R.id.Button02);
        Button btnBind = (Button)findViewById(R.id.Button03);
        Button btnUnbind = (Button)findViewById(R.id.Button04);

        OnClickListener ocl = new OnClickListener(){

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                //显示指定, intent 所指的对象是  service
                Intent intent = new Intent(ServiceActivity.this,MusicService.class);

                switch(v.getId())
                {
                case R.id.Button01:
                    startService(intent);
                    break;
                 case R.id.Button02:
                        //停止服务
                        stopService(intent);
                        break;
                case R.id.Button03:
                    //绑定服务
                    bindService(intent, conn, Context.BIND_AUTO_CREATE);
                    break;
                case R.id.Button04:
                    //解绑服务
                    unbindService(conn);
                    break;
                }

            }

        };

        btnStart.setOnClickListener(ocl);
        btnStop.setOnClickListener(ocl);
        btnBind.setOnClickListener(ocl);
        btnUnbind.setOnClickListener(ocl);
    }

}

3.注册Service

在AndroidManifest.xml文件中,添加
 <service android:name="com.elvis.musicService.MusicService"/>
 到<application>标签内部。

六 总结

startService()方式开启的音乐,在程序退出时依然播放。
bindService()方式开启的音乐,程序退出时停止播放。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值