编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

Android Service初步了解,实现通话录音功能,...

wxchong 2024-08-13 12:15:18 开源技术 11 ℃ 0 评论

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

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表