Android—Service与Activity的交互
service—Android的四大组件之一。人称“后台服务”指其本身的运行并不依赖于用户可视的UI界面
实际开发中我们经常需要service和activity之间可以相互传递数据维持程序的运行。
先了解Service的生命周期吧。
新建一个类继Service:
package com.example.myservicedemo.service;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
/**
* 服务类(需要在项目清单文件中注册服务)
*
* @author lenovo
*
*/
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
/**
* 服务创建的时候调用
*/
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
System.out.println("=========onCreate======");
}
/**
* 服务启动的时候调用
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
System.out.println("=========onStartCommand======");
return super.onStartCommand(intent, flags, startId);
}
/**
* 服务销毁的时候调用
*/
@Override
public void onDestroy() {
// TODO Auto-generated method stub
System.out.println("=========onDestroy======");
super.onDestroy();
}
}
新建以上类并继承Service后只会重写onBind()方法,其他方法是我手动手写,为了弄清楚Service的生命周期
MainActivity中(设置两个按钮用来开始和停止服务):
package com.example.myservicedemo.ui;
import com.example.myservicedemo.R;
import com.example.myservicedemo.service.MyService;
import com.example.myservicedemo.service.MyService.DownLoadBinder;
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.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn_start = (Button) findViewById(R.id.btn_start);
Button btn_stop = (Button) findViewById(R.id.btn_stop);
btn_start.setOnClickListener(this);
btn_stop.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
int id = v.getId();
switch (id) {
/*
* 开启服务点击事件
*/
case R.id.btn_start:
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
break;
/*
* 停止服务点击事件
*/
case R.id.btn_stop:
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
break;
default:
break;
}
}
}
切记android中的服务是需要在项目清单文件中注册的(AndroidStudio可以自动,eclipse需要手动添加):
<service android:name="服务类坐所在的包名.MyService"></service>
此时运行程序,点击开启服务时候输出是下图:(我输出多次onStartCommand()是因为我连续点击了多次开启服务按钮)
上图可以看出服务第一次开启时先是调用了onCreate()方法和onStartCommand()方法,多次点击开始服务时只调用了onStartCommand()方法
so:
onCreate()方法是服务创建的时候调用的~
onStartCommand()方法在每次启动服务的时候都会调用~
onDestory()方法在停止服务时候会调用~
点击停止服务后,输出如图:
启动服务还有一种方式是bindService();
此时的MyService类要做改变:
package com.example.myservicedemo.service;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
/**
* 服务类(需要在项目清单文件中注册服务)
*
* @author lenovo
*
*/
public class MyService extends Service {
private DownLoadBinder downLoadBinder=new DownLoadBinder();
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
System.out.println("=====onBind=====");
return downLoadBinder;
}
/**
* 内部类继承Binder
* @author lenovo
*
*/
public class DownLoadBinder extends Binder{
public void startDownLoad(){
System.out.println("=====startDownLoad()=====");
}
public void getProgress(){
System.out.println("=====getProgress()=====");
}
}
/**
* 服务创建的时候调用
*/
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
System.out.println("=========onCreate======");
}
/**
* 服务启动的时候调用
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
System.out.println("=========onStartCommand======");
return super.onStartCommand(intent, flags, startId);
}
/**
* 服务销毁的时候调用
*/
@Override
public void onDestroy() {
// TODO Auto-generated method stub
System.out.println("=========onDestroy======");
super.onDestroy();
}
}
以上的代码和第一次相比,一是多了一个内部类DownLoadBinder继承IBinder并且声明了两个方法,二是将onBind方法的返回值改为了DownLoadBinder类型的变量
activity bindService方法启动服务时候一般是需要传递数据的,核心就在onBind()方法中,往下看
MainActivity中加两个按钮:绑定服务和取消绑定服务
package com.example.myservicedemo.ui;
import com.example.myservicedemo.R;
import com.example.myservicedemo.service.MyService;
import com.example.myservicedemo.service.MyService.DownLoadBinder;
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.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener {
private MyService.DownLoadBinder downLoadBinder;
private MyService myService; //我们自己的service
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn_start = (Button) findViewById(R.id.btn_start);
Button btn_stop = (Button) findViewById(R.id.btn_stop);
Button btn_bind = (Button) findViewById(R.id.btn_bind);
Button 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) {
// TODO Auto-generated method stub
int id = v.getId();
switch (id) {
/*
* 开启服务点击事件
*/
case R.id.btn_start:
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
break;
/*
* 停止服务点击事件
*/
case R.id.btn_stop:
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
break;
/*
* 绑定服务点击事件
*/
case R.id.btn_bind:
Intent bindIntent = new Intent(this, MyService.class);
bindService(bindIntent, connection, BIND_AUTO_CREATE);
break;
/*
* 解除绑定服务点击事件
*/
case R.id.btn_unbind:
unbindService(connection);
break;
default:
break;
}
}
private ServiceConnection connection=new ServiceConnection() {
/**
* 服务解除绑定时候调用
*/
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
/**
* 绑定服务的时候调用
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
//myService=((DownLoadBinder) service).
downLoadBinder=(DownLoadBinder) service;
/*
* 调用DownLoadBinder的方法实现参数的传递
*/
downLoadBinder.startDownLoad();
downLoadBinder.getProgress();
}
};
}
运行后点击绑定服务后输出如下:
说明成功绑定了服务且传递了数据,点击解除绑定服务时候ondestory()方法输出
不过这种方法好像只能传递一次数据,,,,不爽,,,,比如后台在实时更新东西,activity需要实时获取呢???
查找资料大多是以下几种方式:
1.使用接口回调方式,activity实现相应的接口,service通过接口进行回调,比较灵活
2.使用广播
这篇博客主要介绍第一种方法,为什么不介绍第二种???——不愿意介绍,不喜欢。
使用接口回调方式的MyService和MainActivity代码我是备注详细之后才粘贴的,大家可以看注释
MyService代码:
package com.example.myservicedemo.service;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
/**
* 服务类(需要在项目清单文件中注册服务)
*
* @author lenovo
*
*/
public class MyService extends Service {
private DownLoadBinder downLoadBinder=new DownLoadBinder();
/**
* 回调
*/
private Callback callback;
/**
* Timer实时更新数据的
*/
private Timer mTimer=new Timer();
/**
*
*/
private int num;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
System.out.println("=====onBind=====");
return downLoadBinder;
}
/**
* 内部类继承Binder
* @author lenovo
*
*/
public class DownLoadBinder extends Binder{
/**
* 声明方法返回值是MyService本身
* @return
*/
public MyService getService() {
return MyService.this;
}
}
/**
* 服务创建的时候调用
*/
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
/*
* 执行Timer 2000毫秒后执行,5000毫秒执行一次
*/
mTimer.schedule(task, 0, 1000);
}
/**
* 提供接口回调方法
* @param callback
*/
public void setCallback(Callback callback) {
this.callback = callback;
}
/**
*
*/
TimerTask task = new TimerTask(){
@Override
public void run() {
// TODO Auto-generated method stub
num++;
if(callback!=null){
/*
* 得到最新数据
*/
callback.getNum(num);
}
}
};
/**
* 回调接口
*
* @author lenovo
*
*/
public static interface Callback {
/**
* 得到实时更新的数据
*
* @return
*/
void getNum(int num);
}
/**
* 服务销毁的时候调用
*/
@Override
public void onDestroy() {
// TODO Auto-generated method stub
System.out.println("=========onDestroy======");
/**
* 停止Timer
*/
mTimer.cancel();
super.onDestroy();
}
}
MainActivity代码:
package com.example.myservicedemo.ui;
import com.example.myservicedemo.R;
import com.example.myservicedemo.service.MyService;
import com.example.myservicedemo.service.MyService.Callback;
import com.example.myservicedemo.service.MyService.DownLoadBinder;
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.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener {
private MyService.DownLoadBinder downLoadBinder;
// private MyService myService; //我们自己的service
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn_start = (Button) findViewById(R.id.btn_start);
Button btn_stop = (Button) findViewById(R.id.btn_stop);
Button btn_bind = (Button) findViewById(R.id.btn_bind);
Button 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) {
// TODO Auto-generated method stub
int id = v.getId();
switch (id) {
/*
* 开启服务点击事件
*/
case R.id.btn_start:
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
break;
/*
* 停止服务点击事件
*/
case R.id.btn_stop:
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
break;
/*
* 绑定服务点击事件
*/
case R.id.btn_bind:
Intent bindIntent = new Intent(this, MyService.class);
bindService(bindIntent, connection, BIND_AUTO_CREATE);
break;
/*
* 解除绑定服务点击事件
*/
case R.id.btn_unbind:
unbindService(connection);
break;
default:
break;
}
}
private ServiceConnection connection=new ServiceConnection() {
/**
* 服务解除绑定时候调用
*/
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
/**
* 绑定服务的时候调用
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
downLoadBinder = (DownLoadBinder) service;
MyService service2 = downLoadBinder.getService();
/**
* 实现回调,得到实时刷新的数据
*/
service2.setCallback(new Callback() {
@Override
public void getNum(int num) {
// TODO Auto-generated method stub
System.out.println("====num===="+num);
}
});
}
};
}
运行后的结果应该输出如图就对了(输出随service中num的数量而更新):
期间遇到的问题:
bindService后无效,MyService类中的onBind()方法没有被调用
解决:这种情况下你的Activity应该是继承了TabBarActivity,绑定服务的时候调用写这种形式:
this.getApplicationContext().bindService(intent, mConnection, BIND_AUTO_CREATE);
最近几天用到,总结一下,希望可以为大家带来帮助,有错误还请大神指正。