Android 四大组件 (二) Service 使用
一. Service 介绍
Service属于android四大组件之一,在很多地方经常被用到。开启Service有两种不同的方式:startService和bindService。不同的开启方式,Service执行的生命周期方法也不同。
分 显示/隐示调用 ,但是官网推荐用显式的方式启动Service。下面 service使用 用的就是显示调用;注意事项用的就是隐示调用,在5.0系统上隐示调用会报错。所以这里只介绍使用显示调用。
不能再service里做耗时操作,否则ANR;需要开辟子线程进行耗时操作处理。
二.Service 使用
1.startService使用。
Intent intent = new Intent(this, TestService.class);
Log.w(Tag, "activity====启动服务");
startService(intent);
执行效果:
Log.w(Tag, "activity====停止服务"); stopService(intent);
执行效果:
2.bindService绑定.
private class MyConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { //只有当我们自己写的MyService的onBind方法返回值不为null时,才会被调用 Log.e("call", "onServiceConnected"); } @Override public void onServiceDisconnected(ComponentName name) { // 这个方法只有出现异常时才会调用,服务器正常退出不会调用。 Log.e("call", "onServiceDisconnected"); } }
Log.w(Tag, "activity====绑定服务");
MyConnection conn = new MyConnection(); //第一个参数:Intent意图 // 第二个参数:是一个接口,通过这个接口接收服务开启或者停止的消息,并且这个参数不能为null // 第三个参数:开启服务时的操作,BIND_AUTO_CREATE代表自动创建service bindService(service, conn, BIND_AUTO_CREATE); bindService(intent, conn, BIND_AUTO_CREATE);
执行效果:
Log.w(Tag, "activity====解绑服务");
unbindService(conn);
执行效果:
3.区别:
以下摘自网络,后续验证:
服务不能自己运行,需要通过调用Context.startService()或Context.bindService()方法启动服务。这两个方法都可以启动Service,但是它们的使用场合有所不同。
使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。
如果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。
如果打算采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()-->onDestroy()方法。
三.Service 注意事项:
在5.0系统上使用如下方式start或者bind启动service时候:
Intent intent = new Intent(); intent.setAction("com.example.user.firstapp.FIRST_SERVICE"); bindService(intent,coon,Service.BIND_AUTO_CREATE);
startService(intent);
android 5.0上,报错:IllegalArgumentException: Service Intent must be explicit
原因是:Android5.0中service的intent一定要显性声明!!!
四.附上核心activity代码:
package com.example.hp.testapp; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.TextView; import com.example.hp.testapp.service.TestService; import org.w3c.dom.Text; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private String Tag = "TestServiceTag"; private TextView tv_btn_start; private TextView tv_btn_stop; private TextView tv_btn_bind; private TextView tv_btn_unbind; Intent intent; MyConnection conn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); intent = new Intent(this, TestService.class); conn = new MyConnection(); initView(); initListener(); } private void initView() { tv_btn_start = (TextView) findViewById(R.id.tv_btn_start); tv_btn_stop = (TextView) findViewById(R.id.tv_btn_stop); tv_btn_bind = (TextView) findViewById(R.id.tv_btn_bind); tv_btn_unbind = (TextView) findViewById(R.id.tv_btn_unbind); } private void initListener() { tv_btn_start.setOnClickListener(this); tv_btn_stop.setOnClickListener(this); tv_btn_bind.setOnClickListener(this); tv_btn_unbind.setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.tv_btn_start: /** * 启动服务 */ Log.w(Tag, "activity====启动服务"); startService(intent); break; case R.id.tv_btn_stop: /** * 停止服务 */ Log.w(Tag, "activity====停止服务"); stopService(intent); break; case R.id.tv_btn_bind: /** * 绑定服务 */ Log.w(Tag, "activity====绑定服务"); //第一个参数:Intent意图 // 第二个参数:是一个接口,通过这个接口接收服务开启或者停止的消息,并且这个参数不能为null // 第三个参数:开启服务时的操作,BIND_AUTO_CREATE代表自动创建service bindService(service, conn, BIND_AUTO_CREATE); bindService(intent, conn, BIND_AUTO_CREATE); break; case R.id.tv_btn_unbind: /** * 解绑服务 */ Log.w(Tag, "activity====解绑服务"); if (conn != null) { unbindService(conn); } default: break; } } @Override protected void onStart() { Log.w(Tag, "activity====onStart"); super.onStart(); } @Override protected void onRestart() { Log.w(Tag, "activity====onRestart"); super.onRestart(); } @Override public void onStateNotSaved() { Log.w(Tag, "activity====onStateNotSaved"); super.onStateNotSaved(); } @Override protected void onResume() { Log.w(Tag, "activity====onResume"); super.onResume(); } @Override protected void onPause() { Log.w(Tag, "activity====onPause"); super.onPause(); } @Override protected void onStop() { Log.w(Tag, "activity====onStop"); super.onStop(); } @Override protected void onDestroy() { Log.w(Tag, "activity====onDestroy"); super.onDestroy(); } private class MyConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { //只有当我们自己写的MyService的onBind方法返回值不为null时,才会被调用 Log.e("call", "onServiceConnected"); } @Override public void onServiceDisconnected(ComponentName name) { // 这个方法只有出现异常时才会调用,服务器正常退出不会调用。 Log.e("call", "onServiceDisconnected"); } } }