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;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
记得要注册哦
<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();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
这里不多做介绍
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;
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
这里隐私授权,需要权限哦
<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);
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();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
这里准备好了之后,我们只要接通了就开始录音
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);
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();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
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>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
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) {
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
关于服务里面
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();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
这里就不赘述了,启动的对应方法,我们通过上面的分析出区别来
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) {
return new Onclick();
}
/**
* 中间衔接
*/
class Onclick extends Binder {
public void getPic() {
isShow();
}
}
public void isShow() {
Log.i("TwoService","我是服务里的一个方法");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
这里,我们实现了一个中间回传,把这个方法给传出去,然后在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);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
这样,就可以拿到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的方法