安卓四大控件之Service

Service介绍

一个Serviceandroid 系统中的四大组件之一(Activity、Service、BroadcastReceiver、ContentProvider),也是一种应用程序组件,
它跟Activity的级别差不多,但不能自己运行只能后台运行,并且可以和其他组件进行交互,不和用户交互应用组件。通常不具有可见的用户界面。
其它的应用程序组件可以启动一个Service,即使在用户切换到另外一个应用程序后,这个Service还是一直会在后台运行。比如播放多媒体的时候
用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,再或者在后台记录你地理信息位置的改变等等,总之服务
总是藏在后台的。

Service分类

  • 按运行地点分类:

本地服务(Local) 该服务依附在主进程上,服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外Local服务因为是在同一
进程因此不需要IPC,也不需要AIDL。相应bindService会方便很多。主进程被Kill后,服务便会终止。    非常常见的应用如:HTC的音乐播放服
务,天天动听音乐播放服务。

远程服务(Remote)该服务是独立的进程,服务为独立的进程,对应进程名格式为所在包名加上你指定的android:process字符串。由于是
独立的进程,因此在Activity所在进程被Kill的时候,该服务依然在运行,不受其他进程影响,有利于为多个进程提供服务具有较高的灵活性。该
服务是独立的进程,会占用一定资源,并且使用AIDL进行IPC稍微麻烦一点。    一些提供系统服务的Service,这种Service是常驻的。
  • 按运行类型分类:

前台服务    会在通知一栏显示 ONGOING 的 Notification,    当服务被终止的时候,通知一栏的 Notification 也会消失,这样对于用户有一定
的通知作用。常见的如音乐播放服务。

默认的服务即为后台服务,即不会在通知一栏显示 ONGOING 的 Notification。  当服务被终止的时候,用户是看不到效果的。某些不需要运行或
终止提示的服务,如天气更新,日期同步,邮件同步等。

Service 与 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生命周期


第一种,startService / stopService
第一次 startService 会触发 onCreate 和 onStartCommand,以后在服务运行过程中,每次 startService 都只会触发 onStartCommand
不论 startService 多少次,stopService 一次就会停止服务

第二种,bindService / unbindService
第一次 bindService 会触发 onCreate 和 onBind,以后在服务运行过程中,每次 bindService 都不会触发任何回调
bindService 多少次,就对应多少次的 unbindService, bindService / unbindService 操作顺序以及次数对应的话, 就会停止当前服务

第三种,前面两种交错
只有当 startService / stopService 与 bindService / unbindService 都满足条件时,才会停止服务

started服务与bind服务的区别:

通过started方式的服务会一直运行在后台,需要由组件本身或外部组件来停止服务才会以结束运行
bind方式的服务,生命周期就要依赖绑定的组件
区别二:参数传递

started服务可以给启动的服务对象传递参数,但无法获取服务中方法的返回值
bind服务可以给启动的服务对象传递参数,也可以通过绑定的业务对象获取返回结果
实际开发中的技巧;

第一次先使用started方式来启动一个服务
之后可以使用bind的方式绑定服务,从而可以直接调用业务方法获取返回值

示例代码

package com.itheima.recorder;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;

public class MainActivity extends Activity {

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


    public void click(View v){
        Intent intent = new Intent(this, RecorderService.class);
        startService(intent);
    }
}

}

package com.itheima.recorder;

import java.io.IOException;

import android.app.Service;
import android.content.Intent;
import android.media.MediaRecorder;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;

public class RecorderService extends Service {
private MediaRecorder recorder;
@Override
public IBinder onBind(Intent intent) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public void onCreate() {
    // TODO Auto-generated method stub
    super.onCreate();
    //拿到电话管理器
    TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
    //监听电话状态
    //events:决定PhoneStateListener侦听什么内容
    tm.listen(new MyListener(), PhoneStateListener.LISTEN_CALL_STATE);
}

class MyListener extends PhoneStateListener{



    //一旦电话状态改变,此方法调用
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        // TODO Auto-generated method stub
        super.onCallStateChanged(state, incomingNumber);

        switch (state) {
        case TelephonyManager.CALL_STATE_IDLE:
            System.out.println("空闲");
            if(recorder != null){
                recorder.stop();
                recorder.release();
                recorder = null;
            }
            break;
        case TelephonyManager.CALL_STATE_RINGING:
            System.out.println("响铃");
            if(recorder == null){
                recorder = new MediaRecorder();
                recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                recorder.setOutputFile("sdcard/luyin.3gp");
                recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                try {
                    recorder.prepare();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            break;
        case TelephonyManager.CALL_STATE_OFFHOOK:
            System.out.println("摘机");
            //开始录音
            if(recorder != null){
                recorder.start();
            }
            break;

        }
    }

}

}

package com.itheima.recorder;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class BootReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    //启动录音机服务
    Intent it = new Intent(context, RecorderService.class);
    context.startService(it);
}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值