标签:
服务一般分为两种:
1:本地服务, Local Service 用于应用程序内部。
在Service可以调用Context.startService()启动,调用Context.stopService()结束。
在内部可以调用Service.stopSelf() 或 Service.stopSelfResult()来自己停止。无论调用了多少次startService(),都只需调用一次stopService()来停止。
2:远程服务, Remote Service 用于android系统内部的应用程序之间。可以定义接口并把接口暴露出来,以便其他应用进行操作。
调用Context.bindService()方法建立连接,并启动,以调用 Context.unbindService()关闭连接。
多个客户端可以绑定至同一个服务。如果服务此时还没有加载,bindService()会先加载它。
提供给可被其他应用复用,比如定义一个天气预报服务,提供与其他应用调用即可
android中服务是运行在后台的东西,级别与activity差不多。既然说service是运行在后台的服务,那么它就是不可见的,没有界面的东西。你可以启动一个服务Service来播放音乐、记录你地理信息位置的改变、启动一个服务来运行并一直监听某种动作。
Service:Service 是android的一种机制,当它运行的时候如果是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的。如:onCreate,onStart 这些函数在被系统调用的时候都是在主进程的 main 线程上运行的。如果是Remote Service,那么对应的 Service 则是运行在独立进程的 main 线程上。因此请不要把 Service 理解成线程,它跟线程半毛钱的关系都没有!
onCreate() 创建时候调用,初始化。只在第一次创建的时候执行。
onStartCommand() 启动时候调用,每次启动都会去执行。
onDestory() 销毁时候调用,一般回收那些不再使用的资源。
在XML文件里面注册。
startService() 开启服务
stopService() 停止服务
startService() 和 stopService() 方法都定义在Context类中的。所以我们在活动中可以调用这两个方法。
这里完全是由活动来决定服务何时停止的(在按钮点击开始服务就开了,点击停止服务就停了)
服务自己停止自己的办法,在MyService()的任何一个位置调用stopSelf()方法就可以让这个服务停下来。
虽然服务是在活动里面启动的,但是启动之后,服务就和活动没有关系了。
在活动中指挥服务去做什么,onBind()方法。
public class MyService extends Service { private DownloadBinder mBinder = new DownloadBinder(); class DownloadBinder extends Binder{ //开始下载 public void startDownload(){ Log.d("MyService","startDownload executed"); } //查看下载 public int getprogress(){ Log.d("MyService","getProgress executed"); return 0; } } @Override public IBinder onBind(Intent intent) { return mBinder; } }
创建一个专门的Binder对象来对下载功能进行管理。上面活动可以控制服务里面的逻辑。
1、创建了一个DownloadBinder类,继承自Binder,实现了两个模拟方法。
2、创建了DownloadBinder实例,然后在onBinder()方法里面返回这个实例,
绑定服务:活动绑定。,
取消绑定服务:
private MyService.DownloadBinder downloadBinder; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) { downloadBinder = (MyService.DownloadBinder) service; downloadBinder.startDownload(); downloadBinder.getProgress(); } }; @Override public void onClick(View v) { switch (v.getId()) { case R.id.start_service: Intent startIntent = new Intent(this, MyService.class); startService(startIntent); break; case R.id.stop_service: Intent stopIntent = new Intent(this, MyService.class); stopService(stopIntent); break; case R.id.bind_service: Intent bindIntent = new Intent(this, MyService.class); bindService(bindIntent, connection, BIND_AUTO_CREATE); break; case R.id.unbind_service: unbindService(connection); break; case R.id.start_intent_service: Log.d("MainActivity", "Thread id is " + Thread.currentThread().getId()); Intent intentService = new Intent(this, MyIntentService.class); startService(intentService); break; default: break; } }
ServiceConnection的匿名类,重写了两个方法,这两个方法分别在活动与服务成功绑定和解除绑定的时候调用。
那么如何绑定呢?
bindService(intent,ServiceConnection,标志位)
BIND_AUTO_CREATE 表示活动与服务进行绑定后自动创建服务。会使得onCreat()方法执行,但onStartCommand()方法不会执行。
MyService不仅可以和MainActivity绑定,还可以和任何一个其他的活动进行绑定。
当同时调用了startService()和bindService()之后,必须同时调用stopService()和unbindService()方法,onDestory()才会执行。
前台服务和普通服务最大的区别在于,他会一直有一个正在运行的图标在系统的状态栏显示。
@Override public void onCreate() { super.onCreate(); Notification notification = new Notification(R.drawable.ic_launcher,"Notification comes", System.currentTimeMillis()); Intent notificationIntent = new Intent(this, MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,notificationIntent, 0); notification.setLatestEventInfo(this, "This is title", "This is content",pendingIntent); startForeground(1, notification); Log.d("MyService", "onCreate executed"); }
创建通知。只不过这次创建出的Notification对象并没有使用NotificationManager来将通知显示出来,而是调用了startForeground()方法。
startForeground() 第一个参数是ID,类似于notify()方法的第一个参数,第二个参数则是构建出的Notifacation对象。
调用startForeground() 之后就会让MyService变成一个前台服务。并在系统状态栏显示出来。
服务中的代码都是运行在主线程中的,如果直接在服务里去处理一些耗时操作,容易出现ANR情况。
所以这个时候就需要用到Android多线程编程的技术了,在服务中开启一个子线程。
记得开启一个线程,并且关闭这个线程,stopSelf()。
IntentService很好的解决了上面两个问题。
public class MyIntentService extends IntentService { /** * Creates an IntentService. Invoked by your subclass‘s constructor. * * @param name Used to name the worker thread, important only for debugging. */ public MyIntentService(String name) { super(name); } @Override protected void onHandleIntent(Intent intent) { } }
必须要提供一个无参的构造函数,并且必须在其内部调用父类的有参构造函数。然后要在子类内去实现onHandlerIntent()这个抽象方法。在这个方法中可以处理一些具体的逻辑。而不用担心ANR的问题。因为这个方法已经在子线程里面执行了,这里为了证实一下,我们在onHandlerIntent()方法中打印了当前线程的ID,另外根据IntentService的特性,这个服务在运行结束后应该会是自动停止的。
标签:
原文地址:http://www.cnblogs.com/zrui513/p/4847202.html