Service见名知意“服务”,略懂windows基础的童鞋都会听说过服务吧。比如控制机器连接网络,是否可以发射WIFI信号等都是由服务控制的,android的中服务有一些略微的区别,主要用做于后台,虽然程序已经退出,但依然可以播放歌曲,下载视频…….。Service类似于Activity,所以也需要启动,只是无界面,不可交互,可以长时间运行在后台(不要进行耗时操作),是APP的组件。
可能会有人有疑问,我新开一个工作线程,程序退出了依然可以执行播放歌曲,下载视频,为什么要用Service,以下是在网上搜索的相关资料:
(1)、Service可以放在独立的进程中,所以更安全;
(2)、使用Service可以依赖现有的binder机制,不需要在应用层面上处理线程同步的繁杂工作;
(3)、系统可以重新启动异常死去的Service。
1.两种启动方式:
(1) Context中的startService()
这种启动方式即使启动的控件即使调用者退出也不会结束Service
(2) Context中bindService();
调用者和Service绑定在一起,调用者退出,服务也就终止。该种启动方式用于传值使用。
做为四大组件,记得要配置<service>节点:
<service android:name="com.example.bandingservice.Service2305"></service>
根据上图不难看出分两种启动方式,并且生命周期方法不同。
startService启动:
生命周期三个方法:onCreate-->onStartCommand-->onDestroy
三个方法详细说明:
1) onCreate第一次创建Service实例会调用
2)onStartCommand()可以多次被执行 (2.0之前onStart);
3)onDestroy销毁Service
当startService的时候会依次调用onCreate()à onStartCommand(),此时服务已经正常启动了。
如果调用者退出了,而调用者启动的Service未退出,则该服务一直启动,Service事情一旦做完,应该停止它,stopSelf()、stopService()。
bindService启动:
生命周期方法:onCreate-->onBind-->onUnbind-->onDestroy
1)onCreate:同上
2)onBind:onCreate一样,一个实例只会调用一次
3)onUnbind解除绑定,注意:在解除绑定之前需要判断调用者是否已经绑定,否则会抛java.lang.IllegalStateException: Could not execute method of the activity
bindService(service, conn, flags)参数详解:
参数1:Intent的要启动的Service
参数2:ServiceConnection的实例,用于监听Service连接的情况,连接成功回调ServiceConnection对象的onServiceConnected(ConpontName name,IBinder service)方法,异常终止调用ServiceConnection的onServiceDisconnected(ConponentNamename)方法。该参数同时是调用者和service之间的通讯
参数3:指定是自动创建Service(如果Service还未创建),可以指定0,或者BIND_AUTO_CREATE(自动创建)
以下是代码:
MainActivity:
package com.example.bandingservice; import com.example.bandingservice.Service2305.MyBinder; import android.app.Activity; import android.app.Service; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.view.View; import android.widget.Toast; public class MainActivity extends Activity { MyServiceConnection conn; //标示位 private boolean isConn = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); conn = new MyServiceConnection(); } public void btn(View view) { switch (view.getId()) { case R.id.btn1:// 绑定Service Intent intent = new Intent(this, Service2305.class); //三个参数上面已经注明 bindService(intent, conn, Context.BIND_AUTO_CREATE); break; case R.id.btn2:// 解绑Service if (isConn) { unbindService(conn); } break; default: break; } } class MyServiceConnection implements ServiceConnection { //访问者与Service连接情况,连接成功调用该方法 参数2是Service2305的public IBinder onBind返回值 @Override public void onServiceConnected(ComponentName name, IBinder service) { MyBinder mBinder = (MyBinder) service; // 获取Service实例 Service2305 mService = mBinder.getService(); String servieceStr = mService.getServieceStr(); Toast.makeText(MainActivity.this, servieceStr, 0).show(); } // Service意外断开连接调用 @Override public void onServiceDisconnected(ComponentName name) { isConn = false; } } }Service2305.java
package com.example.bandingservice; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log; public class Service2305 extends Service { private final String TAG = "Service"; private MyBinder binder = new MyBinder(); //绑定时会调用 返回值不要空 返回到客户端的onServiceConnected @Override public IBinder onBind(Intent intent) { return binder; } @Override public void onCreate() { super.onCreate(); } @Override public boolean onUnbind(Intent intent) { return super.onUnbind(intent); } @Override public void onDestroy() { super.onDestroy(); } // Binder是IBinder的子类 class MyBinder extends Binder { //返回当前Service的实例 public Service2305 getService() { return Service2305.this; } } // 体验:客户端调用服务端的方法 public String getServieceStr() { return "service的数据"; } }
startService和bindService结合启动:
为了Activity和Service交互需要绑定,并且解绑之后又不希望停止Service就会使用两种方式结合启动。
//启动Service startService(new Intent(MainActivity.this,Service2306.class)); //要交互的数据 ServiceConnection中的onServiceConnected bindService(new Intent(MainActivity.this,Service2306.class), conn, Context.BIND_AUTO_CREATE); unbindService(conn);//解绑Service API建议写在activity中的onDestroy()方法里
大家都知道线程之间的交互可以使用Handler,进程之间的交互也同样需要一个类,这就是Messenger(信使),Messenger 主要作用是将调用者和后台Service进行交互,在服务器构建Messenger 的实例需要Handle的对象作为构造参数,在通过调用Messenger的getBinder()给客户端返回IBind实例,废话不说上代码
Service类:
public class Service2402 extends Service{ //接收客户端请求---》处理请求 class MyHandler extends Handler{ @Override public void handleMessage(Message msg) { super.handleMessage(msg); System.out.println("处理客户端的请求:"+msg.what); } } //信使 final Messenger messenger=new Messenger(new MyHandler()); @Override public IBinder onBind(Intent intent) { //信使分享一个IBinder给客户端 return messenger.getBinder(); } }
MainActivity类:
public class MainActivity extends Activity { private Messenger messenger; private Conn conn; private boolean isConn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); conn=new Conn(); //绑定上Service bindService(new Intent(MainActivity.this,Service2402.class), conn, Context.BIND_AUTO_CREATE); //按钮点击--》给Service发送指令 findViewById(R.id.btn).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Message msg=Message.obtain(); msg.what=1; try { messenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } }); } class Conn implements ServiceConnection{ //连接上服务 @Override public void onServiceConnected(ComponentName name, IBinder service) { //Messenger对象---->给Service发指令 messenger=new Messenger(service); isConn=true; } //意外断开连接 @Override public void onServiceDisconnected(ComponentName name) { messenger=null; isConn=false; } } @Override protected void onDestroy() { if(isConn){ unbindService(conn); } super.onDestroy(); }