.服务生命周期,开启方式,绑定服务,远程服务
android应用程序的四大组件
-
activity 界面
-
content provider 内容提供者 暴露应用程序私有的数据
-
broadcast receiver 接受广播消息
-
service 后台的服务
四大组件都要在清单文件配置,特殊广播接受者(代码,清单文件)
Service
一个组件长期后台运行,没有界面。 简单的理解:service理解成一个没有界面长期运行的activity。
配置一个服务
第一步 创建一个类,然后继承Service类,在创建的类中写服务的功能
第二步 因为是服务,所以要在配置文件中进行声明
<service android:name="c.c.c.c.MyService"></service>
第三步 开启服务
Intent intent = new Intent(this, MyService.class); startService(intent);
服务的生命周期 (重要)
开启服务
onCreate() -->onStartCommand-->onStart(过时) -->ondestory(销毁) 如果服务已经开启了,就不会重新调用oncreate方法,服务只会被创建一次。
//开启服务
public void start(View view){
Intent intent = new Intent(this,MyService.class);
startService(intent);
}
//停止服务
public void stop(View view){
Intent intent = new Intent(this,MyService.class);
stopService(intent);
}
停止服务业可以直接通过ddms,选中进程然后关掉
服务有两种开启方法
-
startService(); 直接开启服务,服务一旦启动跟调用者(开启者没有任何关系)
调用者activity退出了,服务还是继续运行活的好好的。 调用者activity,没法访问服务里面的方法。
-
bindService(); 绑定开启服务,服务和开启者(调用者)有密切的关系。
** 不求同时生,但求同时死。只要activity挂了,服务跟着挂了。** 调用者activity,可以调用服务里面的方法。
绑定方式开启服务,调用服务方法的流程 (重要)
绑定服务的生命周期 oncreate()-->onbind()--->onDestory(); 不会调用onstart()方法 和 onstartCommand()方法。
绑定的过程
在activity中
第一步 使用bindService的方式开启服务。
bindService(intent, new MyConn(), Context.BIND_AUTO_CREATE);
第二步 实现一个MyConn 服务与activity的通讯频道(中间人的联系渠道)
private class MyConn implements ServiceConnection{
/**
* 当服务被成功绑定的时候执行的方法,得到中间人。
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binder = (MyBinder) service;
}
/**
* 当服务失去绑定的时候调用的方法。当服务突然异常终止的时候
*/
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
在MyService中
第三步 服务成功绑定的时候 会执行onBinde方法,返回中间人
public class MyBinder extends Binder{
/**
* 内部人员帮助我们调用服务的方法。
*/
public void callMethodInService(){
methodInService();
}
}
第四步 在activity代码里面通过中间人调用服务的方法。
public void impl(View view){
mybinder.callMethodInService();
}
第五步 解绑服务
public void jiebang(View view){
unbindService(conn);
}
抽取接口,隐藏私有方法。
将要让中间人能够执行的方法写进一个接口中,并且让中间人实现只能执行的方法的接口,然后调用者在创建中间人的时候,调用接口中的方法
见代码
调用者activity
public class MainActivity extends Activity {
IService binder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 绑定服务
* @param view
*/
public void bind(View view){
Intent intent = new Intent(this,MyService.class);
//1.开启服务的时候 必须使用 绑定的方式开启。
System.out.println("1. 第一步,开启服务 bind方式。");
bindService(intent, new MyConn(), Context.BIND_AUTO_CREATE);
}
private class MyConn implements ServiceConnection{
/**
* 当服务被成功绑定的时候执行的方法
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//3.通讯频道得到服务成功绑定的消息,得到中间人
System.out.println("3. 第三步,成功绑定服务后,在通讯频道里面得到中间人"+service.toString());
binder = (IService) service;
}
/**
* 当服务失去绑定的时候调用的方法。当服务突然异常终止的时候
*/
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
/**
* 调用服务的方法
* @param view
*/
public void call(View view){
System.out.println("4.调用中间人的方法。");
binder.callMethodInService(3000);
}
}
对外提供服务的方法
public interface IService {
public void callMethodInService(int money);
}
服务本身的方法(服务本身有些敏感的方法不能让外部调用)
public class MyService extends Service {
/**
* 官员的小蜜 。潜规则
*
* @author Administrator
*
*/
//重点地方!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
private class MyBinder extends Binder implements IService{
/**
* 内部人员帮助我们调用服务的方法。
*
* @param money
* 如果大于2000 执行,小于两千 ,给个提示
*/
public void callMethodInService(int money) {
if (money >= 2000) {
System.out.println("5.中间人,调用服务的方法");
methodInService();
}else{
Toast.makeText(MyService.this, "再准备点,你懂的", 0).show();
}
}
public void playMajiang(){
System.out.println("一起打麻将");
}
public void xisangna(){
System.out.println("一起洗桑拿");
}
}
/**
* 官员内部的方法,为人民币服务,没有2000块钱是不会执行的。
*/
public void methodInService() {
Toast.makeText(this, "我是服务内部的方法,我被调用了。", 0).show();
}
@Override
public IBinder onBind(Intent intent) {
MyBinder mybinder = new MyBinder();
System.out.println("2. 第二步 服务被成功绑定了。---onbind,返回IBinder代理人"
+ mybinder.toString());
return mybinder;// 返回中间人
}
@Override
public void onCreate() {
System.out.println("服务被创建了---oncreate()");
super.onCreate();
}
@Override
public void onDestroy() {
System.out.println("服务被销毁了");
super.onDestroy();
}
}
远程服务
aidl: android interface definition language(安卓接口定义语言)
Local-side IPC implementation
本地内部进程通信的实现。
什么是远程服务:服务的代码在另外一个应用程序里面。 什么是本地服务:服务的代码在当前应用程序里面。
以上面的代码为例
服务端需要做的配置
1.远程服务修改接口文件的扩展名为aidl,删除访问修饰符public
IService.java 改为 IService.aidl
interface IService {
void callMethodInService(int money);
}
2.修改IBinder的实现类 extends IService.Stub
private class MyBinder extends IService.Stub{
/**
* 内部人员帮助我们调用服务的方法。
*
* @param money
* 如果大于2000 执行,小于两千 ,给个提示
*/
public void callMethodInService(int money) {
if (money >= 2000) {
System.out.println("5.中间人,调用服务的方法");
methodInService();
}else{
Toast.makeText(MyService.this, "再准备点,你懂的", 0).show();
}
}
3,对外提供IService.aidl
4.对外提供服务
<service android:name="com.itheima.remoteservice.MyService"> <intent-filter > <action android:name="com.itheima.remote.service"/> </intent-filter> </service>
客户端配置
第一步.访问远程服务的时候必须使用绑定的方式开启(通过意图开启)
public void bind(View view){
//1.开启服务的时候 必须使用 绑定的方式开启。
System.out.println("1. 第一步,开启服务 bind方式。");
Intent intent = new Intent();
intent.setAction("com.itheima.remote.service");
bindService(intent, new MyConn(), Context.BIND_AUTO_CREATE);
}
第二步.在调用者的工程里面,把远程服务的aidl文件拷贝过来,保证包名也完全一致。
第三步.在调用者里面强制类型转化
iService = com.itheima.remoteservice.IService.Stub.asInterface(service);
private class MyConn implements ServiceConnection{
/**
* 当服务被成功绑定的时候执行的方法
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//3.通讯频道得到服务成功绑定的消息,得到中间人
System.out.println("3. 第三步,成功绑定服务后,在通讯频道里面得到中间人"+service.toString());
iService = com.itheima.remoteservice.IService.Stub.asInterface(service);
}
/**
* 当服务失去绑定的时候调用的方法。当服务突然异常终止的时候
*/
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
第四步.调用远程服务的方法
public void call(View view){
try {
iService.callMethodInService(5000);
} catch (RemoteException e) {
e.printStackTrace();
}
}

浙公网安备 33010602011771号