> 技术文档 > Service与Activity交互的实现:通过Broadcast解耦

Service与Activity交互的实现:通过Broadcast解耦

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Android开发中,Service在后台执行任务时与Activity的交互是通过BroadcastReceiver组件来实现的。Service可以启动和绑定,而BroadcastReceiver用于接收广播并允许Service向Activity传递数据或控制信息,实现后台任务与界面的解耦。通过创建和注册BroadcastReceiver以及发送和接收广播,开发者能够控制Service与Activity之间的数据交换和交互流程。不过需要注意广播的性能影响以及数据安全问题,特别是对隐私数据的保护。建议在新版本Android系统中使用更现代的替代方案如JobScheduler或WorkManager。
Service与多个Activity交互

1. Service组件介绍

Service(服务)是Android平台上实现程序后台操作的重要组件,它可以在没有用户界面的情况下运行,执行长时间运行的操作。Service分为两种:前台服务和后台服务。前者通过通知栏通知用户,而后者则在后台默默无闻地完成任务。

Service的基本概念

Service是Android四大核心组件之一,它用于执行长时间运行的操作而不提供用户界面。Service在应用程序启动时可以启动,并且即使用户离开应用程序,也可以继续运行。Service可以在不同的组件之间共享数据或执行一些特定的任务。

Service的生命周期

Service的生命周期相对简单,关键方法包括onCreate()和onStartCommand()。onCreate()在服务首次创建时调用,用于初始化资源。onStartCommand()则用于处理客户端的请求。Service在不再使用时需要显式地调用stopSelf()方法或通过其他组件调用stopService()方法来停止服务。

理解Service组件是Android应用开发的基础,它对于实现应用后台任务至关重要。在后续章节中,我们将深入探讨Service的启动、绑定以及如何在Service与Activity之间进行高效交互。

2. Service启动与绑定场景分析

4.1 Service启动方式的原理与应用

4.1.1 启动Service的步骤

启动一个Service需要通过调用Context的 startService 方法,并传递一个包含服务信息的Intent对象。Service在被启动时,系统会调用其 onStartCommand 方法,开发者需要在这个方法中定义Service要执行的任务。

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

在这段代码中,我们创建了一个指向 MyService 类的Intent,然后通过调用 startService 方法启动服务。需要注意的是,Service在服务的 onStartCommand 方法中返回一个整数值,这个值决定了系统在Service被意外销毁后的行为。

4.1.2 启动Service时的上下文和任务

Service是一个抽象类,通常需要继承并实现其抽象方法,如 onStartCommand 。Service在后台执行长时间运行的操作时不应该创建它自己的线程;而应该在其 onStartCommand onCreate 方法中创建线程,以避免阻塞主线程。

@Overridepublic int onStartCommand(Intent intent, int flags, int startId) { // 创建一个新线程来处理耗时的任务 new Thread(new Runnable() { @Override public void run() { // 执行耗时操作 } }).start(); // 返回START_STICKY表示系统在内存不足时可以销毁Service,但会尝试重新创建 return START_STICKY;}

在这里,我们创建了一个新的线程来处理耗时的任务,避免阻塞UI线程。 START_STICKY 表示系统在内存不足时可以销毁Service,但在内存充足时会尝试重新创建Service并调用 onStartCommand 方法。

4.2 Service绑定方式的原理与应用

4.2.1 绑定Service的步骤

绑定Service意味着一个组件(通常是Activity)通过 bindService 方法绑定到Service上。通常用一个 ServiceConnection 对象来监听连接的建立与断开。

Intent intent = new Intent(this, MyService.class);bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);

ServiceConnection 接口的 onServiceConnected onServiceDisconnected 方法在组件与Service建立和断开连接时被调用。

private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 获取与Service通信的IBinder对象 } @Override public void onServiceDisconnected(ComponentName name) { // 处理Service意外断开连接的情况 }};

onServiceConnected 方法中,你可以获取到一个 IBinder 对象,它允许你从Activity中与Service进行通信。

4.2.2 绑定Service与Activity的通信

Service和Activity之间的通信通过 IBinder 对象来实现。Service需要提供一个 IBinder 对象,客户端通过这个对象与Service进行交互。

public class MyService extends Service { // ... @Override public IBinder onBind(Intent intent) { // 返回一个实现了IBinder接口的对象,这里以匿名内部类示例 return new Binder() { public int getServiceVersion() { return SERVICE_VERSION; } }; } // ...}

Activity中获取Service版本号的示例代码:

int serviceVersion = 0;private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { // cast the IBinder and get Service specific interface MyService.LocalBinder binder = (MyService.LocalBinder)service; serviceVersion = binder.getServiceVersion(); } @Override public void onServiceDisconnected(ComponentName arg0) { serviceVersion = 0; }};// ...

通过这种方式,Activity就可以与Service进行通信,例如调用Service中的方法或获取Service中的数据。

第五章:Service与Activity通过Broadcast交互的实现

5.1 Broadcast的基本概念与使用场景

5.1.1 Broadcast的定义和作用

Broadcast是Android中组件间通信的一种方式,允许一个应用发布声明,让其他应用(或者应用的其他部分)能够接收并处理这个声明。Broadcast可以分为两种类型:普通Broadcast和有序Broadcast。

Intent intent = new Intent(\"com.example.broadcast.MY_BROADCAST\");intent.putExtra(\"key\", \"value\");sendBroadcast(intent);

上述代码演示了一个发送普通Broadcast的例子。开发者需要指定一个动作字符串,并可以选择性地添加额外的数据。

5.1.2 在Service与Activity间发送和接收Broadcast

为了在Service与Activity间发送和接收Broadcast,首先需要在两者中分别注册和实现 BroadcastReceiver 。以下是一个在Activity中注册 BroadcastReceiver 的示例。

public class MyActivity extends AppCompatActivity { private MyReceiver myReceiver = new MyReceiver(); @Override protected void onResume() { super.onResume(); IntentFilter filter = new IntentFilter(\"com.example.broadcast.MY_BROADCAST\"); registerReceiver(myReceiver, filter); } @Override protected void onPause() { super.onPause(); unregisterReceiver(myReceiver); } private class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // 处理接收到的Broadcast } }}

在上面的代码中, MyActivity 通过 registerReceiver 方法注册了一个 BroadcastReceiver ,并在 onResume onPause 生命周期内分别注册和注销广播接收器

5.2 实践中的交互流程详解

5.2.1 创建自定义的BroadcastReceiver

创建一个 BroadcastReceiver 类来处理特定的Broadcast。这个类需要实现 BroadcastReceiver 类,并重写 onReceive 方法。

public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // 通过Intent获取数据 String data = intent.getStringExtra(\"key\"); // 处理接收到的数据 Log.i(\"MyReceiver\", \"Received data: \" + data); }}
5.2.2 在Activity中发送广播并由Service处理

在Activity中创建并发送一个Broadcast,Service通过注册一个BroadcastReceiver来接收并处理这个 Broadcast。

Intent intent = new Intent(\"com.example.broadcast.MY_BROADCAST\");intent.putExtra(\"key\", \"value\");sendBroadcast(intent);

Service中的实现类似,但通常是在Service的 onStartCommand 方法中注册和注销BroadcastReceiver。

5.2.3 在Service中发送广播并由Activity处理

在Service中发送广播的过程与在Activity中类似,但是需要确保发送的是有序Broadcast,这样可以更精确地控制广播的传递。

Intent intent = new Intent(\"com.example.broadcast.MY_BROADCAST\");intent.putExtra(\"key\", \"value\");sendOrderedBroadcast(intent, null);

在发送有序Broadcast时,可以通过额外的参数来指定接收者的权限。在Activity中,广播接收器将会按照优先级的顺序接收广播。

第六章:Android Oreo及以上版本后台服务和广播的限制及注意事项

6.1 后台服务限制详解

6.1.1 Android Oreo的Background Limitations

Android Oreo引入了新的后台执行限制,主要是为了改善设备的电池使用效率。系统对后台Service和后台任务的执行时间做了更严格的限制,直接在后台启动Service将不再被推荐。

// 旧方式startService(new Intent(this, MyService.class));// 新方式(推荐)startForegroundService(new Intent(this, MyService.class));

startForegroundService 方法需要在服务的 onCreate onStartCommand 方法中调用 startForeground 来将服务置于前台状态。

6.1.2 满足新限制的服务实现方法

对于需要长时间运行的服务,开发者应该考虑将服务置于前台,显示一个通知,这样可以避免服务被系统杀死。

// 在Service的onCreate或onStartCommand方法中startForeground(NOTIFICATION_ID, notification);

这里的 NOTIFICATION_ID 是一个标志符,用于区分不同的通知。 notification 是一个 Notification 对象,用于向用户展示服务正在运行。

6.2 广播使用的限制与应对策略

6.2.1 新版本对广播的限制

在Android Oreo及以上版本中,对广播的使用同样受到了限制。有序广播几乎被完全移除,普通广播则不能在应用外部发送。这些改变旨在减少后台应用程序对系统资源的消耗。

6.2.2 应对广播限制的实践技巧

为了遵守新的限制,开发者应该尽可能地在应用内部使用LocalBroadcastManager来发送和接收广播。这保证了广播的传递仅限于应用内部,不会消耗系统资源。

LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

6.3 开发中广播使用的注意事项

6.3.1 广播接收器的声明与限制

开发者需要注意到在Android Oreo及以上版本中,除了对后台执行的限制,应用在清单文件中声明的广播接收器也需要被限制。不在清单文件中声明的隐式广播接收器将无法接收到广播,而且在清单文件中声明的广播接收器接收的广播将受到更严格的限制。

6.3.2 安全与性能优化的最佳实践

为了保证应用的安全性和性能,建议采用JobScheduler或WorkManager来执行后台任务。这些API允许系统更有效地调度任务,并且不会受到新限制的影响。

// 使用WorkManager来调度后台任务OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(MyWorker.class) .build();WorkManager.getInstance().enqueue(workRequest);

这段代码通过构建一个 OneTimeWorkRequest 对象来安排一个单次的后台任务。 MyWorker 是一个扩展了 Worker 的类,它在其中定义了后台任务的具体内容。

这样,应用能够适应新版本的Android系统限制,并在保证用户体验的同时,确保应用的高效运行。

3. BroadcastReceiver组件介绍

3.1 BroadcastReceiver的核心概念

BroadcastReceiver作为Android中四大组件之一,主要用于监听应用或系统发出的广播。它类似于一种全局监听器,当广播事件发生时,系统会自动创建一个BroadcastReceiver实例,以响应这个事件。无论是系统事件,如电池电量低、电话呼入,还是应用定义的事件,都可以通过BroadcastReceiver来处理。

BroadcastReceiver的典型应用包括系统状态变化的通知、应用间的消息传递等。与Activity不同,BroadcastReceiver不需要用户界面,它只需要注册并实现一个 onReceive() 方法即可,该方法会在接收到广播时被系统调用。BroadcastReceiver可以静态注册在AndroidManifest.xml中,也可以动态注册在代码中。

3.2 BroadcastReceiver的注册与使用

静态注册是在AndroidManifest.xml中声明BroadcastReceiver,系统会在应用安装时自动注册。而动态注册则是通过代码在运行时进行注册,这种方式更加灵活,可以根据需要开启或关闭接收器。

当系统发出广播时,所有的BroadcastReceiver都会按优先级排序,优先级高的BroadcastReceiver会先接收到广播。对于同一个优先级的BroadcastReceiver,系统则会按照它们在Manifest文件中的注册顺序或者代码中注册顺序依次调用。开发者可以通过调用 Intent 对象来发送广播,而 BroadcastReceiver 将会接收到这个 Intent

3.3 BroadcastReceiver的分类与应用场景

BroadcastReceiver分为无序和有序两大类。无序BroadcastReceiver的接收不受顺序限制,所有的无序接收器都会接收到广播。而有序BroadcastReceiver则按优先级顺序接收,高优先级的接收器可以完全截断广播,阻止低优先级的接收器接收到它。

无序BroadcastReceiver适用于需要多个组件响应同一个事件的场景,例如应用更新完成后的多个清理任务。有序BroadcastReceiver则适用于需要处理或者修改广播内容的场景,比如在电量不足时,多个应用可能都需要对自身行为做出调整,有序接收可以使得最后接收到广播的应用得到一个经过前序应用处理过的广播状态。

3.4 BroadcastReceiver的生命周期与注意事项

BroadcastReceiver的生命周期非常短暂,它的 onReceive() 方法必须在10秒内执行完毕,否则系统会报错。开发者需要在 onReceive() 方法中处理完所有逻辑,如果需要进行耗时操作,必须使用其他线程来处理,例如可以使用 AsyncTask 或者 IntentService

在注册BroadcastReceiver时,应该尽可能减少接收器的数量,避免接收不必要的广播,以免浪费系统资源。此外,有序BroadcastReceiver中,发送的广播状态会被接收器修改,因此需要谨慎处理,确保不会对其他应用或系统的正常运行造成影响。

3.4.1 实现BroadcastReceiver

下面是一个简单的BroadcastReceiver实现示例,它监听了电池电量变化的广播:

public class BatteryLevelReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); float batteryPct = level / (float)scale; // 根据电量百分比执行相应操作 if(batteryPct < 0.2) { // 发出电池电量低的通知 } }}

AndroidManifest.xml 中注册BroadcastReceiver:

   

或者在代码中动态注册:

IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);registerReceiver(new BatteryLevelReceiver(), filter);

3.4.2 Broadcast的发送与接收流程

Broadcast的发送与接收是通过Intent对象实现的。当发送广播时,系统会找到所有匹配该Intent的接收器并调用它们的 onReceive() 方法。接收器接收广播的流程如下:

  1. 创建Intent并设置Action。
  2. 创建BroadcastReceiver并设置优先级(可选)。
  3. 调用 sendBroadcast() sendOrderedBroadcast() 发送广播。
  4. 系统匹配接收器,按优先级或顺序创建BroadcastReceiver实例。
  5. 调用BroadcastReceiver的 onReceive() 方法。

3.4.3 代码逻辑分析

在上述的 BatteryLevelReceiver 示例中, onReceive() 方法接收两个参数: Context Intent Intent 中包含广播的数据,通过 getExtra() 方法可以获取这些数据。在实际应用中,如果处理逻辑较为复杂或耗时,可以将任务分发到其他线程处理。

注册时, 标签内的 元素用于指定接收器可以接收的广播类型。在此例中, android.intent.action.BATTERY_CHANGED 是一个预定义的Action,用于接收电池状态变化的广播。

无论是静态还是动态注册,BroadcastReceiver都是在系统中注册广播过滤器,只有符合过滤器条件的广播才会被接收。动态注册的好处在于,可以在不需要的时候取消注册,节省资源。

3.4.4 广播优先级与安全性

在有序广播中,优先级由 标签内的 android:priority 属性指定,值越大优先级越高。系统会按优先级降序来传递广播,高优先级的接收器可以对广播进行修改,并且可以通过设置 result 来阻止其他接收器接收到广播。

安全性方面,从Android 3.1开始,系统提供了 标签的 android:exported 属性来控制BroadcastReceiver是否可以接收来自其他应用的广播。默认情况下,如果 中指定了Action,那么 android:exported 属性的默认值为true,即允许接收外部广播。如果未指定Action,则默认为false,即只能接收来自同一个应用的广播。这一点在设计接收器时需要特别注意。

3.4.5 最佳实践与示例

最佳实践包括合理设置广播优先级、只在需要时注册接收器、使用有序广播时合理处理广播状态等。例如,如果一个应用需要在接收到网络可用的广播后进行某些操作,但又不想影响其他应用的处理逻辑,可以这样设置:

  

使用有序广播时,每个接收器都可以通过返回值来决定是否继续传递广播:

public class CustomOrderedReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // 处理Intent中的数据 // 如果决定不继续传递广播,可以返回true // 如果需要继续传递,则不返回或者返回false return false; }}

在注册有序广播时,可以根据需要设置Action和优先级:

   
IntentFilter filter = new IntentFilter();filter.addAction(\"android.net.conn.CONNECTIVITY_CHANGE\");filter.setPriority(10);registerReceiver(new CustomOrderedReceiver(), filter);

通过上述示例,开发者可以根据应用的需求灵活地使用BroadcastReceiver,实现系统与应用、应用与应用之间的高效交互。

4. Service启动与绑定场景分析

4.1 Service启动方式的原理与应用

4.1.1 启动Service的步骤

Service作为Android四大组件之一,用于执行长时间运行操作而不提供用户界面。通过Intent启动Service是其中的一种典型方式。以下是启动Service的基本步骤:

  1. 创建一个Intent对象,这个Intent指明了要启动的Service类。
  2. 通过 startService() 方法传递该Intent到系统,这个方法会触发Service的 onStartCommand() 方法。
Intent intent = new Intent(this, MyService.class);startService(intent);

在这个例子中, MyService.class 是我们想要启动的Service类。 startService() 方法将创建Service的实例(如果还未创建),并调用其 onStartCommand() 方法。

4.1.2 启动Service时的上下文和任务

Service的启动方式中,上下文(Context)是关键。通常有两种上下文:应用上下文和活动上下文。在启动Service时,通常使用应用上下文,以避免内存泄漏。

启动Service时,我们通常会携带一些数据或任务,这些可以在 onStartCommand() 方法中接收和处理。

@Overridepublic int onStartCommand(Intent intent, int flags, int startId) { // 获取Intent携带的数据 String data = intent.getStringExtra(\"data\"); // 执行任务... return START_STICKY;}

在这个方法中, intent 参数可以传递数据给Service。 START_STICKY 返回值告诉系统如果Service被系统杀死,系统在内存允许的情况下应该重新创建该Service。

4.2 Service绑定方式的原理与应用

4.2.1 绑定Service的步骤

绑定Service与启动Service不同,它允许组件与Service进行交互,甚至调用Service中的公共方法。以下是绑定Service的基本步骤:

  1. 创建一个Intent对象,这个Intent指明了要绑定的Service类。
  2. 调用 bindService() 方法并传递该Intent及 ServiceConnection 的实例。
Intent intent = new Intent(this, MyService.class);bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

mConnection 是一个实现了 ServiceConnection 接口的对象,它定义了绑定成功和解绑时的回调方法。

4.2.2 绑定Service与Activity的通信

Service与Activity绑定后,可以在Service中创建一个Binder对象来实现通信。Activity通过Binder对象来调用Service中的方法。

public class MyService extends Service { // 定义一个Binder对象 private final IBinder mBinder = new LocalBinder(); public class LocalBinder extends Binder { MyService getService() { return MyService.this; } } @Override public IBinder onBind(Intent intent) { return mBinder; }}

Activity通过绑定的Binder对象获取Service的实例,然后调用Service中定义的方法:

MyService myService;ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { myService = ((MyService.LocalBinder)service).getService(); } @Override public void onServiceDisconnected(ComponentName arg0) { myService = null; }};

Activity通过 myService 变量调用Service中的方法,实现组件间通信。

在下一章节中,我们将深入探讨Service与Activity通过BroadcastReceiver交互的实现方式,揭示组件间更复杂的信息交流技术。

5. Service与Activity通过Broadcast交互的实现

5.1 Broadcast的基本概念与使用场景

5.1.1 Broadcast的定义和作用

在Android平台上,广播(Broadcast)是一种广泛应用于组件间通信的机制。它可以允许应用程序发布一些系统范围的事件,其他的应用程序或系统服务可以在其感兴趣的事件发生时接收到这些通知。广播可以由系统发送,也可以由应用程序生成。

Broadcast的定义基于其在Android系统中的通信方式,类似于现实生活中的广播电台,信息被广泛发送出去,但只有特定的接收者才能对其进行解码并作出响应。它是基于消息发布和订阅的模型,用于实现低耦合的系统组件间的事件驱动通信。

在实际的应用场景中,Broadcast可以用于多种目的,如:

  • 当电池电量低时提醒用户
  • 当网络状态发生变化时通知应用
  • 在服务中完成某项任务时通知Activity进行UI更新
  • 用于组件间的同步操作

5.1.2 在Service与Activity间发送和接收Broadcast

在Service与Activity之间通过Broadcast进行通信是一种简单有效的方法。Service在其内部完成某些工作后,可以通过发送Broadcast告知Activity,Activity接收到Broadcast后即可执行相应的操作,如更新UI或响应用户输入。

这种通信机制不需要Service和Activity直接知道对方的存在,它们之间是通过广播机制进行间接通信的。这种方式非常适合于不希望或者不方便使用绑定Service的场景。

5.2 实践中的交互流程详解

5.2.1 创建自定义的BroadcastReceiver

在实现Service与Activity交互时,首先要创建一个自定义的BroadcastReceiver。这个Receiver将用于接收由Service发出的特定的广播消息,并执行相应的逻辑。

public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // 实现当接收到特定广播时要执行的代码 String action = intent.getAction(); if (action.equals(\"com.example.action.SOME_ACTION\")) { // 做出响应,例如更新UI或者处理数据 } }}

5.2.2 在Activity中发送广播并由Service处理

Activity要发送广播时,可以使用Intent和Context的sendBroadcast()方法。在发送之前,需要定义一个广播的Action,然后将这个Action附加到Intent上。

Intent broadcastIntent = new Intent(\"com.example.action.SOME_ACTION\");sendBroadcast(broadcastIntent);

Service在onStartCommand()方法中接收广播,并进行处理:

public class MyService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent.getAction().equals(\"com.example.action.SOME_ACTION\")) { // 处理从Activity发来的广播 } return START_STICKY; }}

5.2.3 在Service中发送广播并由Activity处理

Service发送广播给Activity的过程与Activity发送给Service类似。Service需要创建一个Intent,指定广播接收器(BroadcastReceiver)的类或者Action,然后发送广播。

Intent intent = new Intent(\"com.example.action.RESPOND_ACTION\");intent.setClass(this, MyReceiver.class);sendBroadcast(intent);

Activity中的MyReceiver接收到此广播后,会在onReceive方法中作出相应处理。这种通信方式是单向的,但通过合理的编码可以实现复杂的交互逻辑。

5.3 实现中的注意事项与最佳实践

在实现Service与Activity通过Broadcast交互时,需要遵循Android开发的一些最佳实践:

  • 确保安全 :广播应该明确指定接收者,避免广播的泄漏,防止未授权的组件接收或处理广播。
  • 优化性能 :减少广播发送的频率和大小,避免在主线程中执行复杂的逻辑。
  • 合理注册Receiver :动态注册BroadcastReceiver可以避免应用程序在不必要的情况下加载广播接收器。
  • 理解权限 :对敏感数据传输时,使用合适的权限来保护数据。

通过以上章节,我们深入探讨了Service与Activity通过Broadcast交互的原理和实践操作。下一章将讨论Android Oreo及以上版本对后台服务和广播的限制以及应对策略。

6. Android Oreo及以上版本后台服务和广播的限制及注意事项

随着Android Oreo的发布,系统对后台服务和广播接收器的使用施加了更严格的限制,这些改变影响了应用后台任务和广播事件处理的方式。本章将深入探讨这些限制,并提供应对策略和实践中的注意事项。

6.1 后台服务限制详解

6.1.1 Android Oreo的Background Limitations

Android Oreo引入了新的限制,主要目的是减少后台服务对系统资源的消耗,从而提升设备的整体性能和电池续航。这些限制具体包括:

  • 系统限制了后台服务的启动频率。如果应用试图在短时间内多次启动服务,系统可能会延迟服务的启动或完全拒绝。
  • 在某些情况下,服务可能会被系统终止,特别是在用户长时间未与应用交互时。
  • 对于前台服务,虽然可以较长时间运行,但应用仍需向用户明确展示前台服务的通知,以避免滥用。

6.1.2 满足新限制的服务实现方法

为了适应新的限制,开发者可以采取以下几种方法:

  • 使用 JobScheduler WorkManager 来执行后台任务,这样可以更有效地控制任务的执行时间和条件。
  • 对于需要在后台持续运行的服务,考虑使用 startForegroundService 启动服务,并尽快调用 startForeground 方法,以显示前台通知。
  • 尽可能地利用 startService foregroundServiceType 属性,允许系统在特定条件下自动将服务置于前台,以避免被错误地终止。

6.2 广播使用的限制与应对策略

6.2.1 新版本对广播的限制

Android Oreo对广播的限制同样严格:

  • 对于在 AndroidManifest.xml 中静态注册的广播接收器,系统不再会在应用安装时自动创建实例。这意味着静态注册的广播在Oreo及以上版本将无法正常工作。
  • 动态注册的广播也受到限制,应用必须具有前台状态或处于系统认为合理的上下文中,例如,当用户使用耳机时,接收器可以监听音乐播放状态的广播。

6.2.2 应对广播限制的实践技巧

面对广播限制,开发者可以采取以下实践技巧:

  • 尽可能使用 LocalBroadcastManager 发送应用内部的广播,这样既保证了通信的私密性,又避免了对系统广播的依赖。
  • 对于需要监听系统级广播的情况,考虑使用 EventBus LiveData RxJava 等响应式编程框架来实现组件间的通信。
  • 使用 WorkManager AlarmManager 来代替广播处理一些定时任务。

6.3 开发中广播使用的注意事项

6.3.1 广播接收器的声明与限制

在Oreo及以上版本中,开发者需要特别注意广播接收器的声明方式:

  • 避免在 AndroidManifest.xml 中静态注册广播接收器,改用动态注册,并在适当的时候进行注册与注销。
  • 当应用不再需要接收广播时,应当及时注销广播接收器,避免内存泄漏或不必要的资源消耗。

6.3.2 安全与性能优化的最佳实践

在处理广播和后台服务时,开发者应遵循以下最佳实践以确保应用的安全性和性能:

  • 确保广播接收器的逻辑尽可能高效,避免执行复杂的操作或进行长时间的阻塞。
  • 使用 ForegroundService 来确保重要的后台任务不会被系统轻易终止。
  • 对于需要跨应用通信的广播,应验证发送者身份,避免潜在的安全风险,如广播注入攻击。
  • 使用 WorkManager 的约束功能,确保任务只在满足特定条件下执行,如充电状态、网络可用性等。

应用这些策略和注意事项,开发者可以更好地适应Android的新版本限制,确保应用的顺利运行和用户的良好体验。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Android开发中,Service在后台执行任务时与Activity的交互是通过BroadcastReceiver组件来实现的。Service可以启动和绑定,而BroadcastReceiver用于接收广播并允许Service向Activity传递数据或控制信息,实现后台任务与界面的解耦。通过创建和注册BroadcastReceiver以及发送和接收广播,开发者能够控制Service与Activity之间的数据交换和交互流程。不过需要注意广播的性能影响以及数据安全问题,特别是对隐私数据的保护。建议在新版本Android系统中使用更现代的替代方案如JobScheduler或WorkManager。

本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif