热点新闻
Android服务(Service)
2023-07-11 03:44  浏览:402  搜索引擎搜索“富博农业网”
温馨提示:信息一旦丢失不一定找得到,请务必收藏信息以备急用!本站所有信息均是注册会员发布如遇到侵权请联系文章中的联系方式或客服删除!
联系我时,请说明是在富博农业网看到的信息,谢谢。
展会发布 展会网站大全 报名观展合作 软文发布
一、介绍

Service是一种可在后台执行长时间运行操作而不提供界面的应用组件。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。此外,组件可通过绑定到服务与之进行交互,甚至是执行进程间通信 (IPC)。例如,服务可在后台处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序进行交互。

二、3种服务

服务分为三种:前台服务、后台服务、绑定服务

【1】前台服务 前台服务执行一些用户能注意到的操作。 例如,音频应用会使用前台服务来播放音频曲目。 前台服务必须显示通知。即使用户停止与应用的交互,前台服务仍会继续运行。 【2】后台服务 后台服务执行用户不会直接注意到的操作。 例如,如果应用使用某个服务来压缩其存储空间,则此服务通常是后台服务。 【3】绑定服务 当应用组件通过调用 bindService() 绑定到服务时,服务即处于绑定状态。 绑定服务会提供客户端-服务器接口,以便组件与服务进行交互、发送请求、接收结果, 甚至是利用进程间通信 (IPC) 跨进程执行这些操作。仅当与另一个应用组件绑定时,绑定服务才会运行。 多个组件可同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。

三、注册服务

Service需要在清单文件中声明:

<manifest ...> <application...> <service android:name=".ExampleService"/> </application> </manifest>

ExampleService 是 Service 的子类:

public class ExampleService extends Service { @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } }

四、启动服务和停止服务

通过 startService 启动服务:

// 必须显示启动services Intent intent = new Intent(MainActivity.this, ExampleService.class); startService(intent);

Intent 必须是显式,否则程序将会报错。

另外,还有一种启动方式,启动前台服务:

startForegroundService() // Android 8.0新增

Android 8.0(API 26)对Service做了一些限制,因为某些限制,新增了 startForegroundService 接口。

API 26 之后,当在前台启动Service时,startService 和 startForegroundService 并没有什么区别。当在后台启动Service时,则必须使用 startForegroundService 接口,将 Service 从后台切换到前台,并且在5秒之内调用自己的 startForeground() 方法。

通过 stopService 可以停止服务:

Intent intent = new Intent(MainActivity.this, ExampleService.class); stopService(intent);

当然,也可以在服务结束的地方执行 stopSelf() 来停止服务。

启动服务之后,服务将在内存中一直运行,直到执行 stopService 或者 stopSelf 停止服务。

五、IntentService

onStartCommand 方法中不能存在耗时操作,否则主线程会被阻塞,甚至可能导致发生crash和ANR。
即使 onStartCommand 执行的不是耗时操作,当多次启动服务,onStartCommand 会被执行多次,这种情况仍然可能导致程序异常或者ANR。
为了保守起见,onStartCommand 的工作应该另起一个线程执行,除非能够保证没有耗时操作。

IntentService 会创建一个作业线程来执行任务,并且还可以保证线程安全,所以可以把 IntentService 做为 Service 的替代方案。

IntentService同样需要在注册:

<manifest ...> <application...> <service android:name=".HelloIntentService"/> </application> </manifest> public class HelloIntentService extends IntentService { public HelloIntentService() { super("HelloIntentService"); } @Override protected void onHandleIntent(Intent intent) { } }

启动IntentService:

Intent intent = new Intent(MainActivity.this, HelloIntentService.class); startService(intent);

启动IntentService会执行以下操作:

  • 创建默认的工作线程,用于在应用的主线程外执行传递给 onStartCommand() 的所有 Intent。
  • 创建工作队列,用于将 Intent 逐一传递给 onHandleIntent() 实现,这样您就永远不必担心多线程问题。
  • 在处理完所有启动请求后停止服务,因此您永远不必调用 stopSelf()。
  • 提供 onBind() 的默认实现(返回 null)。
  • 提供 onStartCommand() 的默认实现,可将 Intent 依次发送到工作队列和 onHandleIntent() 实现。

IntentService的业务逻辑是在 onHandleIntent 方法中执行的,onHandleIntent 方法执行在工作线程,并且能够保证线程安全,这就是 IntentService 的强大之处了。
IntentService 会自动调用 stopSelf() ,所以不需要主动调用 stopService 或者 stopSelf。但是,因为这个特性,IntentService无法保证让 Service 一直处理Running状态。

六、绑定服务

使用 bindService 绑定服务:

Intent intent = new Intent(MainActivity.this, ExampleService.class); bindService(intent, serviceConnection, Service.BIND_AUTO_CREATE); private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { binder = IExampleBinder.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { binder = null; } };

绑定服务后,Service 会自动启动。

解绑服务:

unbindService(serviceConnection);

onBind的返回值不能为null:

public class ExampleService extends Service { private class MyBinder extends IExampleBinder.Stub { @Override public String getName() throws RemoteException { return "zhangsan"; } } @Nullable @Override public IBinder onBind(Intent intent) { Log.d("ExampleService", "==onBind=="); return new MyBinder(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("ExampleService", "==onStartCommand1=="); return super.onStartCommand(intent, flags, startId); } }

IExampleBinder 是AIDL文件(IExampleBinder.aidl):

interface IExampleBinder { String getName(); }

七、新特性

Android 8 之前, 只要调用 startService 就可以启动前台服务和后台服务。

但是,在Android 8.0之后,如果当前程序在后台,就必须启动前台服务 startForegroundService:

startForegroundService(new Intent(getApplicationContext(), RemoteService.class));

启动前台服务之后,必须在5秒之内执行 startForeground 方法:

NotificationChannel channel = new NotificationChannel("persident", "persident", NotificationManager.importANCE_LOW); NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); manager.createNotificationChannel(channel); Notification notification = new NotificationCompat.Builder(this, "persident") .setAutoCancel(true) .setCategory(Notification.CATEGORY_SERVICE) .setongoing(true) .setPriority(NotificationManager.importANCE_LOW).build(); startForeground(10, notification);

startForeground 的 ID 不能为0。

如要从前台移除服务,请调用 stopForeground()。

Android 9 之后,还需要添加权限:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

[本章完...]

发布人:2a07****    IP:117.173.23.***     举报/删稿
展会推荐
让朕来说2句
评论
收藏
点赞
转发