【安卓笔记】全面解析Service组件
service,android四大组件之一,是一个长期运行在应用后台的android组件,它没有与用户交互的界面。
-------------------------------------------------------------
目录:
service分类简介
一. 如何创建一个service?
二.如何启动/关闭service?
三.如何绑定/解绑service?
四.如何创建前台service?
五.service的生命周期?
六.如何让service与activity进行交互?
七.使用AIDL绑定远程服务
八.service与thread的区别?
------------------------------------------------------------
service分类简介:
一. 如何创建一个service?
import android.app.Service; import android.content.Intent; import android.os.IBinder; public class ServiceExample extends Service { @Override public IBinder onBind(Intent intent) { return null; } }
<service android:name="com.example.xxx"></service>
android:name:服务类名
android:label:服务的标签,如果此项不设置,那么默认显示的服务名则为类名
android:icon:服务的图标
android:permission:申明此服务的权限,这意味着只有提供了该权限的应用才能控制或连接此服务
android:process:表示该服务是否运行在另外一个进程,如果设置了此项,那么将会在包名后面加上这段字符串表示另一进程的名字(即远程服务)
android:enabled:如果此项设置为 true,那么 Service 将会默认被系统启动,不设置默认此项为 false
android:exported:表示该服务是否能够被其他应用程序所控制或连接,不设置默认此项为 false
具体的使用案例我放在了后面,请继续向下看。
二.如何启动/关闭service?
startService(Intent intent)//启动服务 stopService(Intent intent)//关闭服务ntent用于指定我们要开启的服务,可以用显示意图也可以用隐式意图。显式意图很简单,直接指明开启的服务的类名即可,像这样:
Intent intent1 = new Intent(this,MyService.class);如果使用隐式意图,首先我们需要在配置service时增加一个意图过滤器:
<service android:name="com.example.service.PayService"> <intent-filter> <action android:name="com.example.pay"/> </intent-filter> </service>然后我们开启服务的时候,也指定action:
Intent intent = new Intent("com.example.pay");
三.如何绑定/解绑service?
public boolean bindService(Intent service, ServiceConnection conn, int flags)//绑定 public void unbindService(ServiceConnection conn)//解绑
public interface ServiceConnection { public void onServiceConnected(ComponentName name, IBinder service); public void onServiceDisconnected(ComponentName name); }
try { if(conn != null) unbindService(conn); } catch (Exception e) { }
四.如何创建前台service?
public final void startForeground(int id, Notification notification) public final void stopForeground(boolean removeNotification)首先新建一个android工程,然后创建一个类继承service:
package com.example.foregroundservicedemo.service; import android.app.Notification; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.os.IBinder; import com.example.foregroundservicedemo.MainActivity; import com.example.foregroundservicedemo.R; public class MyService extends Service { @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { Notification notification = new Notification(R.drawable.notification, "您有一条新通知", System.currentTimeMillis()); Intent notificationIntent = new Intent(this, MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,notificationIntent, 0); notification.setLatestEventInfo(this, "通知的标题", "通知的内容",pendingIntent); startForeground(1, notification); //开启前台服务 } @Override public void onDestroy() { stopForeground(true);//停止前台服务,并销毁通知 } }
<service android:name="com.example.foregroundservicedemo.service.MyService"></service>最后,我们编写一个activity,添加两个按钮分别用于启动/停止服务,代码很简单,下面只贴出onclick方法:
public void onClick(View v) { switch (v.getId()) { case R.id.but_start: Intent intent = new Intent(this,MyService.class); this.startService(intent); break; case R.id.but_stop: Intent intent2 = new Intent(this,MyService.class); this.stopService(intent2); break; } }
五.service的生命周期?
(1). 被启动的服务的生命周期:如果一个Service被某个Activity 调用 Context.startService 方法启动,那么不管是否有Activity使用bindService绑定或unbindService解除绑定到该Service,该Service都在后台运行。如果一个Service被startService 方法多次启动,那么onCreate方法只会调用一次,onStart将会被调用多次(对应调用startService的次数),并且系统只会创建Service的一个实例(因此你应该知道只需要一次stopService调用)。该Service将会一直在后台运行,而不管对应程序的Activity是否在运行,直到被调用stopService,或自身的stopSelf方法。当然如果系统资源不足,android系统也可能结束服务。
(2). 被绑定的服务的生命周期:如果一个Service被某个Activity 调用 Context.bindService 方法绑定启动,不管调用 bindService 调用几次,onCreate方法都只会调用一次,同时onStart方法始终不会被调用。当连接建立之后,Service将会一直运行,除非调用Context.unbindService 断开连接或者之前调用bindService 的 Context 不存在了(如Activity被finish的时候),系统将会自动停止Service,对应onDestroy将被调用。
至于第三种比较特殊了,我们也来总结下它的生命周期:package com.example.servicedemo2.myservice; import com.example.servicedemo2.binder.IService; import android.app.Service; import android.content.Intent; import android.content.ServiceConnection; import android.os.Binder; import android.os.IBinder; import android.util.Log; import android.widget.Toast; public class MyService extends Service { private static final String TAG = "MyService"; @Override public void onCreate() { Log.i(TAG,"服务被创建"); } @Override public IBinder onBind(Intent intent) { Log.i(TAG,"服务被绑定"); return new MyBinder(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG,"onstartCommand方法调用,startId = "+startId); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.i(TAG,"服务被销毁"); } private class MyBinder extends Binder implements IService { @Override public void func() { myServiceFunc();//通过一个binder将服务中的方法暴露给外界 } } /** * 服务中的私有的方法 */ private void myServiceFunc() { Toast.makeText(getApplicationContext(),"成功调用了服务中的方法...", 0).show(); } @Override public boolean onUnbind(Intent intent) { Log.i(TAG,"服务被解除绑定..."); return super.onUnbind(intent); } }
package com.example.servicedemo2; import com.example.servicedemo2.binder.IService; import com.example.servicedemo2.myservice.MyService; import android.app.Activity; import android.app.Service; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; /** * @author Rowand jj * */ public class MainActivity extends Activity implements OnClickListener { protected static final String TAG = "MainActivity"; private Button but_start,but_stop,but_bind,but_unbind,but_func; private IService s = null; private ServiceConnection conn = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); but_start = (Button) findViewById(R.id.but_start); but_stop = (Button) findViewById(R.id.but_stop); but_bind = (Button) findViewById(R.id.but_bind); but_unbind = (Button) findViewById(R.id.but_unbind); but_func = (Button) findViewById(R.id.but_func); but_start.setOnClickListener(this); but_stop.setOnClickListener(this); but_bind.setOnClickListener(this); but_unbind.setOnClickListener(this); but_func.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.but_start: Intent intent1 = new Intent(this,MyService.class); this.startService(intent1); break; case R.id.but_stop: Intent intent2 = new Intent(this,MyService.class); this.stopService(intent2); break; case R.id.but_bind: Intent intent3 = new Intent(this,MyService.class); conn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { Log.i(TAG,"onServiceDisconnected运行了..."); } @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.i(TAG,"成功连接上了服务,现在可以调用服务中的方法了"); s = (IService) service;//因为我们知道在Myservice中的IBinder对象继承了Binder并实现了IService接口 } }; this.bindService(intent3, conn, Service.BIND_AUTO_CREATE); break; case R.id.but_unbind: if(conn != null) this.unbindService(conn); break; case R.id.but_func: if(s != null) { s.func();//调用IBinder的方法间接与service通信 } else { Toast.makeText(this,"还没有绑定服务...",0).show(); } break; } } @Override protected void onDestroy()//activity销毁时,为避免报错,自动解除绑定service,之所以try起来,是因为service只能被解除绑定一次 { super.onDestroy(); try { if(conn != null) unbindService(conn); } catch (Exception e) { } } }IService接口:
package com.example.servicedemo2.binder; public interface IService { public void func(); }运行效果:
六.如何让service与activity进行交互?
package com.example.service; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.IBinder; import android.widget.Toast; public class MyService extends Service { private MyReceiver receiver = null; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { IntentFilter filter = new IntentFilter(); filter.addAction("com.example.broadcast");//监听的动作 receiver = new MyReceiver(); this.registerReceiver(receiver, filter);//注册广播接收者 } /** * 服务中的方法 */ private void serviceMethod() { Toast.makeText(getApplicationContext(),"我是服务中的方法...",0).show(); } @Override public void onDestroy() { if(receiver!=null) this.unregisterReceiver(receiver);//解除注册 } public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { serviceMethod(); } } }测试的activity:
package com.example.myservicedemo3; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import com.example.service.MyService; public class MainActivity extends Activity { private Button but_send = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 开启service服务 Intent intent = new Intent(this,MyService.class); this.startService(intent); but_send = (Button) findViewById(R.id.but_send); but_send.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent broadcast = new Intent(); broadcast.setAction("com.example.broadcast");//和service中的receiver接收的action一致 MainActivity.this.sendBroadcast(broadcast);//发广播 } }); } }
七.使用AIDL绑定远程服务
package com.example.service; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class PayService extends Service { private static final String TAG = "PayService"; @Override public IBinder onBind(Intent intent) { Log.i(TAG,"绑定了支付服务..."); return new MyBinder(); } @Override public boolean onUnbind(Intent intent) { Log.i(TAG,"解除绑定支付服务..."); return false; } private class MyBinder extends IService.Stub { @Override public void callServiceFunc() { pay(); } } /** * 服务内部的支付方法 */ private void pay() { Log.i(TAG,"调用了支付的方法..."); } }
package com.example.service; interface IService { void callServiceFunc(); }
package com.example.thirdapplication; import android.app.Activity; import android.app.Service; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; import com.example.service.IService; import com.example.service.IService.Stub; /** * @author Rowand jj * *这是第三方的应用,用来远程调用支付服务。 *使用aidl调用远程服务。 * aidl:Android Interface Definition Language */ public class MainActivity extends Activity implements OnClickListener { private Button but_bind = null; private Button but_pay = null; private IService myService = null; private ServiceConnection conn = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); but_bind = (Button) findViewById(R.id.but_bind); but_pay = (Button) findViewById(R.id.but_pay); but_bind.setOnClickListener(this); but_pay.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.but_bind: Intent intent = new Intent("com.example.pay"); conn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) { myService = Stub.asInterface(service); } }; this.bindService(intent, conn, Service.BIND_AUTO_CREATE); Toast.makeText(this,"绑定成功...", 0).show(); break; case R.id.but_pay: try { if(myService!=null) myService.callServiceFunc(); } catch (RemoteException e) { e.printStackTrace(); } break; } } @Override protected void onDestroy() { super.onDestroy(); if(conn != null) this.unbindService(conn); } }工程截图如下:
八.service与thread的区别?
示例代码打包下载
------------------------------------------------------------------------------------------------------------------------------------------------------
ps.写一篇博客不容易,希望尊重作者的劳动成果,转载请声明出处:http://blog.csdn.net/chdjj/article/details/19333171
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。