1、Service与Activity
service与activity都是android的基本组件,并且都是Context的子类,可以把service当作是没有界面的activity。与activity一样,不能在主线程中作耗时操作。都必须在清单文件中配置。
2、Service两种启动服务的方式和不同。
对于为什么会有两咱启动方式,他们是合适不同的场景的。使用startService启动的服务,它不会随着启动它的组件生命周期结束而结束,只要不调用停止服务或者手机结束进程,服务将一直处于运行中。
而通过bindStart()启动的服务是与启动它的组件生命周期相关联。如果启动它的组件销毁了,那么通过启动它的服务也就销毁了。
1. StartService()的生命周期:
onCreate()——如果服务已经创建,则不会再走onCreate()方法。
onStartCommand—-每一次调用都会执行:
当其它组件,比如一个activity,通过调用startService()请求started方式的服务时,系统将会调用本方法。 一旦本方法执行,服务就被启动,并在后台一直运行下去。 如果你的代码实现了本方法,你就有责任在完成工作后通过调用stopSelf()或stopService()终止服务。 (如果你只想提供bind方式,那就不需要实现本方法。)
onStart()——每一次调用都会执行
onDesotry()——如果不调用.stopService()或者调用Service.stopSelfResult(),service将一直处于开启的状态;
这类服务由其它组件调用startService()来创建。然后保持运行,且必须通过调用stopSelf()自行终止。其它组件也可通过调用stopService() 终止这类服务。服务终止后,系统会把它销毁。
2、 通过bindService()的方式启动启动服务
当其它组件需要通过bindService()绑定服务时(比如执行RPC),系统会调用本方法。 在本方法的实现代码中,你必须返回IBinder来提供一个接口,客户端用它来和服务进行通信。 你必须确保实现本方法,不过假如你不需要提供绑定,那就返回null即可。
bindService()— 调用
onCreate()—–首先会走onCreate()方法
onBind()——-绑定服务
Service running—–服务正在运行中
onUnbind()——-解除绑定
onDesotry()——销毁服务
服务由其它组件(客户端)调用bindService()来创建。然后客户端通过一个IBinder接口与服务进行通信。客户端可以通过调用unbindService()来关闭联接。多个客户端可以绑定到同一个服务上,当所有的客户端都解除绑定后,系统会销毁服务。(服务不需要自行终止。)
3、对于两种启动方式的混合启动。
通过startService()方式启动服务,服务就可以做到长驻内存中(不依赖于组件)。使用bindService()的方式启动服务,服务与绑定组件相依存,并且通过bind的方式可以与service进行很多的交互,在conn中可以获取服务中的信息:比如说连接的状态,如果有下载任务,还可以得到下载的进度,情况等。
但是有时候用过这两种服务的混合开启这种情况使用的也比较多,比如说音乐播放器必须运行在服务中,但又需要被前台activity调用这就要用混合服务的方式启动了。
先startService(),再bindService(),销毁时先unbindService(),再stopService()。
4 、IntentService
intentService可能使用的人比较少,甚至很多人都没听过。但intentService是非常好用和适用的。
利用继承Service写的服务通过startService()启动服务,这种服务一旦启动,就处于运行状态,如果想要在线程执行后停止服务,只能调用 stopSelf()的方法。
为了方便起见,也是减少一些可能发生的错误,比如说经常忘记开启,或者调用stopSelf()的方法。Android中提供了一个IntentService()类,这个类可以简单的创建一个异步的,会自动停止的服务。
IntentService的执行步骤:
创建一个子线程,并且执行onStartCommand()中收到的intent。
创建一个工作队列,每次向onHandleIntent()传入一个intent,
处理完所有的请求后,自动调用stopSelf()停止服务。
详见实例3
5、Service与Activity之间的通信和传递数据;
1、activity向service发送数据比较简单,与activity之间传递数据一样。
Intent intent =new Intent(this,MyService.class);
intent.putExtra(“name”,”yu”);
startService(intent);
String name=intent.getStringExtra(“name”);
Log.i(TAG,name);
2、service向activity传递数据或者更新UI
如果需要数据持久化:
1、在service得到网络数据保存到sp中数据,在activity中从sp中取出数据更新UI;
2、在service中得到网络数据保存到数据库中,在activity中查询数据库,并更新UI
如果不需要持久化:
3、能过BroadcastReceiver把service中的数据传递给activity,
4、如果服务通过bindService的方式启动,还可以通过onBind()方法来传递数据给activity
6、如何用Service开启一个长期运行,定时更新的任务。比如天气,或者新闻每隔三小时更新;
- 在activity中启动服务。
- 在服务中的onStartCommand中开启子线程,连网得到网络数据,并且调用AlermManager定时,用PendingIntent得到广播,并发送给广播。
在广播的onReceive()中再次启动服务,这样就形成了一个长期的在后台运行,并且定时刷新的服务。
详细实例4
1、通过startService启动服务代码:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(MainActivity.this,MyStartService.class));
}
}
在MyStartService()中的代码:
public class MyStartService extends Service {
private static final String TAG="MyStartService";
//如果服务已经开启了,调用将不会再走onCreate()的方法
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG,"service onCreate()");
}
//每一次调用都是执行onStartCommand代码,在这段代码中主要做onStart()方法前的一些工作
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG,"service onStartCommend()");
return super.onStartCommand(intent, flags, startId);
}
//onStart方法是在onStartCommand执行后走的方法。
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.i(TAG, "service onStart()");
}
//销毁服务;
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "service onDestory()");
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
运行结果:第一次走了onCreate()的方法,再次则没有走onCreate()
2、通过bindService()启动服务代码
public class MyBindService extends Service {
private static final String TAG = "MyBindService";
//创建服务;
@Override
public void onCreate() {
Log.i(TAG, "service onCreate()");
super.onCreate();
}
//绑定服务,在绑定的服务中返回一个Bind对象;
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "service onBind()");
return mBinder;
}
//销毁服务
@Override
public void onDestroy() {
Log.i(TAG, "service onDestory()");
super.onDestroy();
}
private MyBinder mBinder = new MyBinder();
//创建MyBinder,继承Binder,调用bind启动服务时,把MyBindService返回
public class MyBinder extends Binder {
public MyBindService getService() {
return MyBindService.this;
}
}
}
在Activity中调用:注意!通过绑定的服务会随着组件的结束而结束,在onDestory()中调用解除绑定代码
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//通过startService()的方式启动服务;
// startService(new Intent(MainActivity.this,MyStartService.class));
//通过bindService()的方式启动服务;
Intent intent = new Intent(MainActivity.this, MyBindService.class);
bindService(intent, conn, BIND_AUTO_CREATE);
}
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onDestroy() {
unbindService(conn);
super.onDestroy();
}
}
效果图:当Activity执行了onDestory()时,服务也就销毁了
3、 intentService实例:
public class HelloIntentService extends IntentService {
/**
* 构造方法是必需的,必须用工作线程名称作为参数
* 调用父类的[http://developer.android.com/reference/android/app/IntentService.html#IntentService(java.lang.String) IntentService(String)]构造方法。
*/
public HelloIntentService() {
super("HelloIntentService");
}
/**
* IntentService从缺省的工作线程中调用本方法,并用启动服务的intent作为参数。
* 本方法返回后,IntentService将适时终止这个服务。
*/
@Override
protected void onHandleIntent(Intent intent) {
// 通常我们会在这里执行一些工作,比如下载文件。
// 作为例子,我们只是睡5秒钟。
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
}
}
继承IntentService后,增加了一个构造方法和一个onHandleIntent()方法的实现。
还可以加上其他方法,比如onCreate()、onStartCommand()、onDestroy(), 请确保调用一下父类的实现代码,以便IntentService能正确处理工作线程的生命周期。
实例4、在后台定时数据更新为例,比如说每隔三小时天气更新。
在activity中代码:
/**
* 如何做一个定时的,在后台运行的长期任务,比如天气,或者新闻每小时更新?
*
* 在activity中启动了service,然后在service中每隔10秒中启动广播,这样onReceive()方法得到执行,
在广播中再次开启service,这样就形成一个永久的循环,一个长期的在后台运行的任务也就启动起来。
*/
public class MainActivity extends Activity {
private TextView tv_time;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_time= (TextView) findViewById(R.id.tv_time);
Intent intent=new Intent(this,AutoService.class);
startService(intent);
}
}
在AutoService中代码:
public class AutoService extends Service {
private static final String TAG="AutoService";
private String str_time="";
//不需要绑定
@Override
public IBinder onBind(Intent intent) {
return null;
}
//onStartCommand在onStart()方法前运行;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
//开启子线程,在这里做耗时操作;比如说获取天气信息;
Log.i(TAG, getTime());
}
}).start();
AlarmManager manager= (AlarmManager) getSystemService(ALARM_SERVICE);
int time=10*1000;
long triggerAtTIME= SystemClock.elapsedRealtime()+time;
Intent i=new Intent(this,AutoBroadcastReceiver.class);
PendingIntent pi=PendingIntent.getBroadcast(this,0,i,0);
manager.set(AlarmManager.ELAPSED_REALTIME, triggerAtTIME, pi);
return super.onStartCommand(intent, flags, startId);
}
public String getTime(){
SimpleDateFormat sdf =new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss ");
Date date=new Date(System.currentTimeMillis());
String str=sdf.format(date);
return str;
}
}
在AutoBroadcastReceiver中代码:
public class AutoBroadcastReceiver extends BroadcastReceiver {
public static final String TAG="AutoBroadcaseReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, AutoService.class);
context.startService(i);
}
}