1、服务
运行于后台的一个组件,用来运行适合运行在后台的代码,服务是没有前台界面,可以 视为没有界面的activity
Service
进程的生命周期(进程的优先级)
1、前台进程 拥有一个正在与用户交互的Activity(onResume方法被调用)的进程
2、可见进程 拥有一个可见但是没有焦点的Activity(onPause方法被调用)
3、服务进程 拥有一个通过startService方法启动的服务
4、后台进程 拥有一个不可见的Activity(onStop方法被调用)的进程
5、空进程 没有拥有任何活动的应用组件的进程 很容易被系统杀死
服务开启和关闭:
创建一个服务首先extends Service 方法。
配置清单文件;
显式启动:
<service android:name="com.zh.startservice.MyService"></service>
开启服务:
Intent intent = new Intent(this,MyService.class);//定义意图对象,通过上下文对象,和指定service的class类。
StartService(intent);
关闭服务;
Intent intent = new Intent(this, MyService.class);
stopService(intent);
Service服务的生命周期方法:
onCreate;
onStartCommand;
onDestory();
开启服务时调用:
onCreate;
onStartCommand;
关闭服务时调用:
onDestory的方法。
启动service startService();
第二种方法: bindService(service, conn, flags); 绑定服务
bindService(intent,conn , BIND_AUTO_CREATE);
在服务中调用其方法,直接调用是行不通的,需要定义一个中间类,在类中定义方法调用方法中的方法。
优化:可以将中间类的方法抽出来变成一个接口。然后让中间类实现该接口。interface;
demo:
public interface PublicBusniess {
void qianxian();
}
package com.zh.banzheng;
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) {
// TODO Auto-generated method stub
return new ZhouMi();
}
class ZhouMi extends Binder implements PublicBusniess {
public void qianxian() {
banzheng();
}
public void damajiang() {
System.out.println("陪领导打麻将");
}
}
public void panzheng() {
System.out.println("李处办证");
}
}
package com.zh.banzheng;
import com.zh.banzheng.LeaderService.ZhouMi;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
public class MainActivity extends Activity {
private Intent intent;
private MyServiceconn conn;
private PublicBusniess pb; //定义接口为全局变量;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent(this, LeaderService.class); //
conn = new MyServiceconn();
bindService(intent,conn , BIND_AUTO_CREATE); //绑定服务;
}
public void click(View v) {
// 找领导服务,调用办证的方法:
pb.qianxian();
}
class MyServiceconn implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
pb = (PublicBusniess) service; // IBinder对象里面没有 调用的方法,用其子类。service是由服务传过来,将service赋值给一个全局变量,然后强转过来。
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
}
}
音乐播放器做的时候需要注意的是:
在服务中调用方法,需要中间人对象,启动需要bindService();绑定启动,绑定启动的缺点是它不属于服务进程,当activity销毁时,绑定服务也就结束了。需要混合调用,在绑定之前调用startService; 开启服务。
要注意服务混合调用时开启顺序: 先启动,在绑定,然后解绑,最后停止服务。 顺序错乱会出现bug;
Intent intent = new Intent(this, MusicService.class);
conn = new MyServiceconn();
startService(intent);
bindService(intent, conn , BIND_AUTO_CREATE);
在代码中注册广播接收者,
使用代码配置广播接收者
* 可以使用清单文件注册 :场景应用 电量的监测,屏幕的锁屏 经常反复用的一些东西。
* 广播一旦发出,系统就会去所有清单文件中寻找,哪个广播接收者的action和广播的action是匹配的,如果找到了,就把该广播接收者的进程启动起来
* 可以使用代码注册
* 需要使用广播接收者时,执行注册的代码,不需要时,执行解除注册的代码 代码注册就不要在清单文件中进行配置了。
特殊的广播接收者
- 安卓中有一些广播接收者,必须使用代码注册,清单文件注册是无效的
- 屏幕锁屏和解锁
- 电量改变
使用服务注册广播接收者:
startService 会调用 onCreate方法。
stopService会调用 onDestory方法。
创建service:
package com.zh.register;
import android.app.Service;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
public class RegisterService extends Service {
private ScreenReceiver receiver;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
//创建广播接收者对象。
receiver = new ScreenReceiver();
//创建intent-filter 对象
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
//注册广播接收者
registerReceiver(receiver, filter);
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
//解除注册
unregisterReceiver(receiver);
}
}
创建广播接收者:
package com.zh.register;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class ScreenReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String action= intent.getAction();
if(Intent.ACTION_SCREEN_ON.equals(action)){
System.out.println("屏幕打开");
}else if(Intent.ACTION_SCREEN_OFF.equals(action)){
System.out.println("屏幕关闭");
}
}
}
在MainActivitity中启动和停止service:
package com.zh.register;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener{
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent(this, RegisterService.class);
Button bt_one = (Button) findViewById(R.id.bt_one);
Button bt_two = (Button) findViewById(R.id.bt_two);
bt_one.setOnClickListener(this);
bt_two.setOnClickListener(this); //设置监听。
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
int id = v.getId();
if(id==R.id.bt_one){
//开启服务
startService(intent); //会调用Service的onCreate 方法
}else if(id==R.id.bt_two){
stopService(intent); //会调用ondestory的方法。
}
}
}