Service


Service的神奇之处,在于他不需要界面,一切的操作都在后台操作,所以很多全局性(手机助手,语音助手)之类的应用很长需要这个,我们今天也来玩玩

我们新建一个工程——ServiceDemo

1.启动服务

服务是怎么启动的,我们先定义一个按钮吧

     <Button
        android:id="@+id/startservice"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="启动服务" />

我们还得新建一个类——MyService

package com.lgl.servicedemo;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

/**
 * 我的服务
 * Created by lgl on 16/4/10.
 */
public class MyService extends Service {

    @Override
    public IBinder onBind(Intent intent) {

        return null;
    }
}

记得要注册哦

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

好了,我们现在来看看怎么启动,其实跟activity一模一样

case R.id.startservice:
                Intent i = new Intent(this, MyService.class);
                //启动服务
                startService(i);
                break;

我们启动之后就可以在后台看到

这里我们可以看到有一个服务

2.停止服务

停止服务就相对来讲很简单了,首先我们定义一个Button

     <Button
        android:id="@+id/stopservice"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="停止服务" />

然后就可以手动停止了

 case R.id.stopservice:
                Intent intent = new Intent(this, MyService.class);
                //停止服务
                stopService(intent);
                break;

这样就停止了

3.声明周期

用一张图表示,毕竟天天看Activity的生命周期,这个看懂不是难事


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

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

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

这里不多做介绍

4.通话录音机

我们来写个小案例,就是用service监听通话,录音之后保存下来,我們在button中启动这个service,然后在service中一创建,我们就获取电话状态

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

    public void getService() {
        //服务一创建就监听
        TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
        tm.listen(new myListener(), PhoneStateListener.LISTEN_CALL_STATE);
    }

    class myListener extends PhoneStateListener {

        //电话状态改变的回调
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            super.onCallStateChanged(state, incomingNumber);
            //判断当前的状态
            switch (state) {
                //电话空闲
                case TelephonyManager.CALL_STATE_IDLE:
                    Log.i("myListener", "电话空闲");
                    break;
                //电话响铃
                case TelephonyManager.CALL_STATE_RINGING:
                    Log.i("myListener", "电话响铃");

                    break;
                //正在通话
                case TelephonyManager.CALL_STATE_OFFHOOK:
                    Log.i("myListener", "电话通话");

                    break;
            }
        }
    }

这里隐私授权,需要权限哦

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

那我们先来调试一下,我们点击启动服务

现在我们可以在响铃就开始准备录音资源了

         //电话响铃
                case TelephonyManager.CALL_STATE_RINGING:
                    Log.i("myListener", "电话响铃");
                    //判断硬件是否支持录音
                    if (recorder == null) {
                        getRecorder();
                    }

                    break;

录音方法

    /**
     * 通话录音
     */
    private void getRecorder() {
        recorder = new MediaRecorder();
        //麦克风
        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        //设置格式 3GP
        recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        //设置保存目录 权限
        recorder.setOutputFile("sdcard/audio.3gp");
        //设置音频编码
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        try {
            //准备录音
            recorder.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

这里准备好了之后,我们只要接通了就开始录音

             //正在通话
                case TelephonyManager.CALL_STATE_OFFHOOK:
                    Log.i("myListener", "电话通话");
                    if(recorder != null){
                        //开始录音
                        recorder.start();
                    }
                    break;

当我们挂断电话,电话状态重新回到空闲的时候就停止并且释放资源

                //电话空闲
                case TelephonyManager.CALL_STATE_IDLE:
                    Log.i("myListener", "电话空闲");
                    if(recorder != null){
                        //停止录音
                        recorder.stop();
                        //释放资源
                        recorder.release();
                        recorder = null;
                    }
                    break;

我们来测试一下,我们拨打一个电话,状态是这样的

我们去目录下翻一翻

这里,可以看到有一个audio.3gp说明我们录音成功了

完整代码

MyService

package com.lgl.servicedemo;

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

import java.io.IOException;

/**
 * 电话录音
 * Created by lgl on 16/4/10.
 */
public class MyService extends Service {

    //录音
    private MediaRecorder recorder;

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

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

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

    /**
     * 获取电话状态
     */
    public void getService() {
        //服务一创建就监听
        TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
        tm.listen(new myListener(), PhoneStateListener.LISTEN_CALL_STATE);
    }

    class myListener extends PhoneStateListener {

        //电话状态改变的回调
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            super.onCallStateChanged(state, incomingNumber);
            //判断当前的状态
            switch (state) {
                //电话空闲
                case TelephonyManager.CALL_STATE_IDLE:
                    Log.i("myListener", "电话空闲");
                    if(recorder != null){
                        //停止录音
                        recorder.stop();
                        //释放资源
                        recorder.release();
                        recorder = null;
                    }
                    break;
                //电话响铃
                case TelephonyManager.CALL_STATE_RINGING:
                    Log.i("myListener", "电话响铃");
                    //判断硬件是否支持录音
                    if (recorder == null) {
                        getRecorder();
                    }

                    break;
                //正在通话
                case TelephonyManager.CALL_STATE_OFFHOOK:
                    Log.i("myListener", "电话通话");
                    if(recorder != null){
                        //开始录音
                        recorder.start();
                    }
                    break;
            }
        }
    }

    /**
     * 通话录音
     */
    private void getRecorder() {
        recorder = new MediaRecorder();
        //麦克风
        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        //设置格式 3GP
        recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        //设置保存目录 权限
        recorder.setOutputFile("sdcard/audio.3gp");
        //设置音频编码
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        try {
            //准备录音
            recorder.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

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

Demo下载:http://download.csdn.net/detail/qq_26787115/9486846

5.Service的两种启动方式

servic启动有两种方式,我们来比对一下。我们写一个新建一个项目ServiceTwo

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_start"
        android:text="启动服务"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/btn_stop"
        android:text="停止服务"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/btn_bind"
        android:text="绑定服务"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/btn_unbind"
        android:text="解除绑定"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

MainActivity

package com.lgl.servicetwo;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn_start, btn_stop, btn_bind, btn_unbind;
    private MyConn conn;

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

        initView();
        conn = new MyConn();
    }

    private void initView() {
        btn_start = (Button) findViewById(R.id.btn_start);
        btn_stop = (Button) findViewById(R.id.btn_stop);
        btn_bind = (Button) findViewById(R.id.btn_bind);
        btn_unbind = (Button) findViewById(R.id.btn_unbind);
        btn_start.setOnClickListener(this);
        btn_stop.setOnClickListener(this);
        btn_bind.setOnClickListener(this);
        btn_unbind.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_start:
                startService(new Intent(this,OneService.class));
                break;
            case R.id.btn_stop:
                stopService(new Intent(this,OneService.class));
                break;
            case R.id.btn_bind:
                bindService(new Intent(this,OneService.class),conn,BIND_AUTO_CREATE);
                break;
            case R.id.btn_unbind:
                unbindService(conn);
                break;
        }
    }

    /**
     * 服务回调
     */
    class  MyConn implements ServiceConnection{

        //到服务的连接被建立了
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {

        }
        //到服务的连接中断了
        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }
}

关于服务里面

OneService

package com.lgl.servicetwo;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

/**
 * Created by lgl on 16/4/10.
 */
public class OneService extends Service {

    //绑定
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    //解绑
    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

    //创建
    @Override
    public void onCreate() {
        super.onCreate();
    }

    //开始
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    //销毁
    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

这里就不赘述了,启动的对应方法,我们通过上面的分析出区别来

  • startService:通过startService启动的服务,该服务所在的进程会变成服务进程

  • bindSevice:进程优先级不变,但是绑定的服务和activity同生共死

6.调用service的方法

你会发现,如果单纯的看startsevice和bindservice,其实区别不大,其实,bindservice有一个用处就是可以调用service的方法,本身来看的话,你是无法吊桶service的方法的,因为你服务是启动起来的,你不能new,所以这里就要用上bindservice了,我们新建一个TwoService,并且写一个方法

 //服务方法
    public void isShow(){
        System.out.print("我是服务里的一个方法");
    }

这个button启动

     <Button
        android:id="@+id/btn_isshow"
        android:text="调用方法"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

TwoService

package com.lgl.servicetwo;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;

/**
 * Created by lgl on 16/4/10.
 */
public class TwoService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        //返回IBinder对象
        return new Onclick();
    }

    /**
     * 中间衔接
     */
    class Onclick extends Binder {
        public void getPic() {
            isShow();
        }
    }

    //服务方法
    public void isShow() {
        Log.i("TwoService","我是服务里的一个方法");
    }
}

这里,我们实现了一个中间回传,把这个方法给传出去,然后在MainActivity中,我们首先先启动这个服务

Intent i = new Intent(this,TwoService.class);
        //如果需要解绑的话就不能用匿名内部类
        bindService(i, new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                //就是返回的对象
                onclick = (TwoService.Onclick) service;
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {

            }
        }, BIND_AUTO_CREATE);

这样,就可以拿到Onclick的事件,我们点击按钮就只要调用

        case R.id.btn_isshow:
                onclick.getPic();
                break;

运行效果

7.方法抽调成接口

当你以为这样就结束了,那就太不给力了,这里service里有些东西是不能对外提供的,java的思想还是来源于生活,所以我们要把他抽调成接口,我们新建一个接口

package com.lgl.servicetwo;

/**
 * 接口
 * Created by lgl on 16/4/12.
 */
public interface PublicGG {
    void getPic();
}

然后让Onclik去实现这个接口

/**
     * 中间衔接
     */
    class Onclick extends Binder implements PublicGG{

        @Override
        public void getPic() {
            isShow();
        }
    }

这样,我们就可以

PublicGG pg;

去接收service同样可以调用getPic的方法

Demo下载:http://download.csdn.net/detail/qq_26787115/9489246

Android实训案例(七)——四大组件之一Service初步了解,实现通话录音功能,抽调接口的更多相关文章

  1. Android实训案例(六)——四大组件之一BroadcastReceiver的基本使用,拨号,短信,SD卡,开机,应用安装卸载监听

    Android实训案例(六)--四大组件之一BroadcastReceiver的基本使用,拨号,短信,SD卡,开机,应用安装卸载监听 Android中四大组件的使用时重中之重,我这个阶段也不奢望能把他 ...

  2. Android实训案例(五)——四大组件之一ContentProvider的使用,通讯录的实现以及ListView的优化

    Android实训案例(五)--四大组件之一ContentProvider的使用,通讯录的实现 Android四大组件是啥这里就不用多说了,看图吧,他们之间通过intent通讯 我们后续也会一一的为大 ...

  3. Android实训案例(四)——关于Game,2048方块的设计,逻辑,实现,编写,加上色彩,分数等深度剖析开发过程!

    Android实训案例(四)--关于Game,2048方块的设计,逻辑,实现,编写,加上色彩,分数等深度剖析开发过程! 关于2048,我看到很多大神,比如医生,郭神,所以我也研究了一段时间,还好是研究 ...

  4. Android实训案例(九)——答题系统的思绪,自己设计一个题库的体验,一个思路清晰的答题软件制作过程

    Android实训案例(九)--答题系统的思绪,自己设计一个题库的体验,一个思路清晰的答题软件制作过程 项目也是偷师的,决心研究一下数据库.所以写的还是很详细的,各位看官,耐着性子看完,实现结果不重要 ...

  5. Android实训案例(八)——单机五子棋游戏,自定义棋盘,线条,棋子,游戏逻辑,游戏状态存储,再来一局

    Android实训案例(八)--单机五子棋游戏,自定义棋盘,线条,棋子,游戏逻辑,游戏状态存储,再来一局 阿法狗让围棋突然就被热议了,鸿洋大神也顺势出了篇五子棋单机游戏的视频,我看到了就像膜拜膜拜,就 ...

  6. Android实训案例(三)——实现时间轴效果的ListView,加入本地存储,实现恋爱日记的效果!

    Android实训案例(三)--实现时间轴效果的ListView,加入本地存储,实现恋爱日记的效果! 感叹离春节将至,也同时感叹时间不等人,一年又一年,可是我依然是android道路上的小菜鸟,这篇讲 ...

  7. Android实训案例(二)——Android下的CMD命令之关机重启以及重启recovery

    Android实训案例(二)--Android下的CMD命令之关机重启以及重启recovery Android刚兴起的时候,着实让一些小众软件火了一把,切水果,Tom猫,吹裙子就是其中的代表,当然还有 ...

  8. Android实训案例(一)——计算器的运算逻辑

    Android实训案例(一)--计算器的运算逻辑 应一个朋友的邀请,叫我写一个计算器,开始觉得,就一个计算器嘛,很简单的,但是写着写着发现自己写出来的逻辑真不严谨,于是搜索了一下,看到mk(没有打广告 ...

  9. Android实训案例(七)——四大组件之中的一个Service初步了解,实现通话录音功能,抽调接口

    Service Service的奇妙之处.在于他不须要界面,一切的操作都在后台操作,所以非常多全局性(手机助手,语音助手)之类的应用非常长须要这个.我们今天也来玩玩 我们新建一个project--Se ...

随机推荐

  1. iOS 中隐藏UITableView最后一条分隔线

    如何优雅的隐藏UITableView中最后一条分割线? 这个问题是很常见,却又不太容易解决的. 可能通常的做法都是隐藏UITableView的分割线,自定义一条. 最近在使用弹出菜单的时候,同样遇到了 ...

  2. 在从1到n的正数中1出现的次数

    #include <iostream> using namespace std; int cal1From0ToN(int n) { int pow1 = 1; int pow2 = 10 ...

  3. Maven仓库概述

    什么是Maven仓库 在Maven世界中,任何一个依赖.插件或项目构建的输出,都可以称为构建.由于Maven引入了坐标机制,任何一个构建都可以由其坐标唯一标识.坐标是一个构建在Maven世界中的逻辑表 ...

  4. GIF动态图制作

    GIF动态图制作 博客写了也有一阵了,一直好奇大牛的博客里demo的动态图是怎么做的,今天抽空研究了一下,找了一个软件,以后再发现有好的工具再继续推荐 GIF制作工具--LICEcap 效果要比下面的 ...

  5. Ribbon WorkBench 当ValueRule的值为空时的设置

    在定制Ribbon按钮的规则的时候,有时需要根据某个字段值是否为空不设定Ribbon按钮的Display rules或Enable Rules,根据Crm的版本的不同,设置有所差别: 对于Dynami ...

  6. ZAB协议

    zookeeper依赖zab协议来实现分布式数据一致性.基于该协议,zookeeper实现了一种主备模式的系统架构来保持ZooKeeper为高可用的一致性协调框架,自然的ZooKeeper也有着一致性 ...

  7. React Native之ViewPagerAndroid 组件

    概述 今天我们来讲解一下关于 ViewPager 的使用,它是一个允许子视图左右滚动翻页的容器.我们知道在Android开发中系统有ViewPager这个组件,作用是实现滚动翻页的,在RN中也是有这么 ...

  8. 19 Handler 总结

    Handler 一, 回顾异步任务 AsyncTask 二, android 使用线程的规则 1,在主线程 不能做阻塞操作 2,在主线程之外的线程不能更新Ui 三, Handler的作用 1,在子线程 ...

  9. CUSTOM.PLL的使用

    在开发中对系统标准form的修改一般不建议修改系统原有FORM,对所需要修改的内容一般写在CUSTOM.PLL里即可,应为每个form运行的时候都会调用CUSTOM.PLL具体概念性东西可参考网上资料 ...

  10. 剑指offer面试题3 二维数组中的查找 (java)

    注:java主要可以利用字符串的length方法求出长度解决这个问题带来方便 public class FindNum { public static void main(String[] args) ...