android 学习随笔十七(服务 )
1、Service
- 四大组件之一
- 运行于后台,没有前台界面的组件,用于运行需要在后台运行的代码
- 可以理解为没有前台的Activity
- 定义方式:创建java类继承Service,清单文件中注册该类
-
package com.ecollab.runservice; import android.app.Service; import android.content.Intent; import android.os.IBinder; public class MyService extends Service { @Override public IBinder onBind(Intent intent) { return null; } @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(); } }
- 清单文件中注册:<service name="com.ecollab.runservice.MyService"/>
2、服务的启动和生命周期
- 用户手动停止服务,服务不会重启,但是如果被自动关闭,内存充足就会重启
- startService的生命周期
- onCreate->onStartCommand->onDestroy
- 重复的startService不会调用onCreate只会重复调用onStartCommand
public void start(View v) {
//启动服务,显示启动服务
Intent service = new Intent(this,MyService.class);
startService(service);
}
public void stop(View v) {
//停止服务
Intent service = new Intent(this,MyService.class);
stopService(service);
}
3、进程优先级
1. 前台进程:拥有一个正在与用户交互的Activity(onResume方法调用)
2. 可见进程:拥有一个不在前台但是对用户依然可见的Activity(onPause方法调用)
3. 服务进程:拥有一个通过startService启动的服务
4. 后台进程:拥有一个对于用户不可见的Activity(onStop方法调用)
5. 空进程:没有任何活动的应用组件(Activity和Service)
4、电话录音
- 创建服务:
package com.ecollab.runservice; 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 RecordService extends Service { @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); //获取电话管理器 TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); //监听电话状态 tm.listen(new MyListener(), PhoneStateListener.LISTEN_CALL_STATE); } class MyListener extends PhoneStateListener{ MediaRecorder recorder; //电话状态改变时会调用 @Override public void onCallStateChanged(int state, String incomingNumber) { super.onCallStateChanged(state, incomingNumber); //判断当前状态 switch (state) { case TelephonyManager.CALL_STATE_IDLE: if(recorder != null){ recorder.stop(); //释放录音机占用的资源 recorder.release(); recorder = null; } break; case TelephonyManager.CALL_STATE_RINGING: recorder = new MediaRecorder(); //设置声音来源 recorder.setAudioSource(MediaRecorder.AudioSource.MIC); //设置音频文件格式 recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); recorder.setOutputFile("sdcard/haha.3gp"); //设置音频文件编码 recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); try { recorder.prepare(); } catch (Exception e) { e.printStackTrace(); } break; case TelephonyManager.CALL_STATE_OFFHOOK: if(recorder != null){ recorder.start(); } break; default: break; } } } }
- 权限:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
- 注册:
<service android:name="com.ecollab.runservice.RecordService"></service>
- 启动服务:
public void startrecord(View v) {
//启动录音机
Intent service = new Intent(this,RecordService.class);
startService(service);
}
5、服务两种启动方式
- startService
* 开始服务,会使进程变成为服务进程
* 启动服务的activity和服务不再有关系
- bindService
* 绑定服务不会使进程变成服务进程,通过bindService启动的服务,进程优先级不变
* 绑定服务,是activity与服务建立连接,如果activity销毁了,服务也会被解绑并销毁,但是如果服务被销毁,activity不会被销毁。不能做后台操作
* 绑定服务和解绑服务的生命周期方法:onCreate->onBind->onUnbind->onDestroy
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
conn = new MyConn();
}
public void start(View v){
Intent intent = new Intent(this, MyService.class);
startService(intent);
}
public void stop(View v){
Intent intent = new Intent(this, MyService.class);
stopService(intent);
}
public void bind(View v){
Intent intent = new Intent(this, MyService.class);
//绑定服务
bindService(intent, conn, BIND_AUTO_CREATE);
}
public void unbind(View v){
//解绑服务
unbindService(conn);
}
class MyConn implements ServiceConnection{
//到服务的连接被建立了,此方法调用
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
}
//到服务的连接中断了,此方法调用
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
}
}
6、调用服务方法
不能直接调用服务中的方法, 可通过中间组件调用服务中的方法。
---------------------------------------------------------------------------------------------------
package com.itheima.leaderservice;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
public class LeaderService extends Service {
@Override
public IBinder onBind(Intent intent) {
// 返回中间人对象
return new FengMiShu();
}
class FengMiShu extends Binder implements PublicBusiness{
//中间人的牵线
@Override
public void qianXian(){
//调用领导的办证
banZheng();
}
public void takeSoap(){
}
}
public void banZheng(){
System.out.println("成功办证");
}
}
--------------------------------------------------------------------------------------------
package com.itheima.leaderservice;//定义接口为了:只有接口中的方法才允许被调用
public interface PublicBusiness {
void qianXian();
}
--------------------------------------------------------------------------------------------
public class MainActivity extends Activity {
// FengMiShu fms;
PublicBusiness pb;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, LeaderService.class);
bindService(intent, new ServiceConnection() {//不解除服务,可以直接newServiceConnection,如果要解除服务必须定义class MyConn implements ServiceConnection
//连接因为异常而终止才会调用
@Override
public void onServiceDisconnected(ComponentName name) {
}
//onBind有返回值此方法才会调用
//service:这个对象就是onBind返回的中间人
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
pb = (PublicBusiness) service;
}
}, BIND_AUTO_CREATE);
}
public void click(View v){
pb.qianXian();
}
}
7、混合启动
为了避免用bindService启动服务后,当activity销毁时,服务也被销毁,可以用混合启动,保证当activity销毁时,服务依然在运行。
混合启动:先startService(intent);再bindService(intent,
startService(intent);
bindService(intent, ..............................解绑后不会摧毁服务,只有停止服务才会摧毁服务
服务的混合启动及摧毁顺序:start-bind-unbind-stop
消息