深入分析 Android Service (五)

傲渊山岳  金牌会员 | 2024-6-22 09:17:28 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 571|帖子 571|积分 1713

深入分析 Android Service (五)

1. 深入分析 Service 与 Activity 之间的通信

前面我们介绍了通过 Messenger 和 AIDL 实现 Service 与 Activity 之间的通信。接下来,我们将进一步深入分析这些通信机制的内部工作原理和计划思想。
2. Messenger 的内部工作原理

Messenger 是基于 Handler 实现的轻量级进程间通信(IPC)机制。它利用 Binder 传递消息。下面是 Messenger 工作的详细流程:

  • 创建 Messenger 和 Handler

    • 服务端创建一个 Handler,用于处理客户端发送的消息。
    • 利用这个 Handler 创建一个 Messenger 对象,并通过 Binder 返回给客户端。

  • 绑定服务

    • 客户端通过 bindService 方法绑定服务,获取服务端的 Messenger 对象。

  • 发送消息

    • 客户端通过 Messenger.send(Message msg) 方法发送消息到服务端。
    • 消息通过 Binder 通道传递到服务端的 Handler 进行处理。

以下是服务端和客户端实现的详细代码示例:
2.1 服务端实现

  1. public class MessengerService extends Service {
  2.     static final int MSG_SAY_HELLO = 1;
  3.     class IncomingHandler extends Handler {
  4.         @Override
  5.         public void handleMessage(Message msg) {
  6.             switch (msg.what) {
  7.                 case MSG_SAY_HELLO:
  8.                     Toast.makeText(getApplicationContext(), "Hello!", Toast.LENGTH_SHORT).show();
  9.                     break;
  10.                 default:
  11.                     super.handleMessage(msg);
  12.             }
  13.         }
  14.     }
  15.     final Messenger messenger = new Messenger(new IncomingHandler());
  16.     @Override
  17.     public IBinder onBind(Intent intent) {
  18.         return messenger.getBinder();
  19.     }
  20. }
复制代码
2.2 客户端实现

  1. public class MainActivity extends AppCompatActivity {
  2.     Messenger messenger = null;
  3.     boolean isBound = false;
  4.     private ServiceConnection connection = new ServiceConnection() {
  5.         @Override
  6.         public void onServiceConnected(ComponentName name, IBinder service) {
  7.             messenger = new Messenger(service);
  8.             isBound = true;
  9.         }
  10.         @Override
  11.         public void onServiceDisconnected(ComponentName name) {
  12.             messenger = null;
  13.             isBound = false;
  14.         }
  15.     };
  16.     @Override
  17.     protected void onCreate(Bundle savedInstanceState) {
  18.         super.onCreate(savedInstanceState);
  19.         setContentView(R.layout.activity_main);
  20.         Intent intent = new Intent(this, MessengerService.class);
  21.         bindService(intent, connection, Context.BIND_AUTO_CREATE);
  22.         Button sendButton = findViewById(R.id.sendButton);
  23.         sendButton.setOnClickListener(v -> {
  24.             if (isBound) {
  25.                 Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
  26.                 try {
  27.                     messenger.send(msg);
  28.                 } catch (RemoteException e) {
  29.                     e.printStackTrace();
  30.                 }
  31.             }
  32.         });
  33.     }
  34.     @Override
  35.     protected void onDestroy() {
  36.         super.onDestroy();
  37.         if (isBound) {
  38.             unbindService(connection);
  39.             isBound = false;
  40.         }
  41.     }
  42. }
复制代码
3. AIDL 的内部工作原理

AIDL(Android Interface Definition Language)是一种定义接口的语言,用于进程间通信(IPC)。它允许在不同进程间传递复杂的数据结构。AIDL 的内部工作原理如下:

  • 定义 AIDL 接口

    • 开发者利用 .aidl 文件定义接口和方法。

  • 编译生成代码

    • 编译器生成用于 IPC 的 Stub 和 Proxy 类。

  • 实现 AIDL 接口

    • 服务端实现 Stub 类,处理客户端哀求。

  • 绑定服务

    • 客户端通过 bindService 方法绑定服务,获取 Stub 的 Proxy 对象。

  • 调用远程方法

    • 客户端通过 Proxy 对象调用远程方法,方法调用通过 Binder 通道传递到服务端的 Stub 类进行处理。

以下是详细的实当代码示例:
3.1 定义 AIDL 接口

  1. package com.example;
  2. interface IMyAidlInterface {
  3.     int add(int a, int b);
  4. }
复制代码
3.2 服务端实现

  1. public class MyAidlService extends Service {
  2.     private final IMyAidlInterface.Stub binder = new IMyAidlInterface.Stub() {
  3.         @Override
  4.         public int add(int a, int b) {
  5.             return a + b;
  6.         }
  7.     };
  8.     @Override
  9.     public IBinder onBind(Intent intent) {
  10.         return binder;
  11.     }
  12. }
复制代码
3.3 客户端实现

  1. public class MainActivity extends AppCompatActivity {
  2.     IMyAidlInterface myAidlService = null;
  3.     boolean isBound = false;
  4.     private ServiceConnection connection = new ServiceConnection() {
  5.         @Override
  6.         public void onServiceConnected(ComponentName name, IBinder service) {
  7.             myAidlService = IMyAidlInterface.Stub.asInterface(service);
  8.             isBound = true;
  9.         }
  10.         @Override
  11.         public void onServiceDisconnected(ComponentName name) {
  12.             myAidlService = null;
  13.             isBound = false;
  14.         }
  15.     };
  16.     @Override
  17.     protected void onCreate(Bundle savedInstanceState) {
  18.         super.onCreate(savedInstanceState);
  19.         setContentView(R.layout.activity_main);
  20.         Intent intent = new Intent(this, MyAidlService.class);
  21.         bindService(intent, connection, Context.BIND_AUTO_CREATE);
  22.         Button addButton = findViewById(R.id.addButton);
  23.         addButton.setOnClickListener(v -> {
  24.             if (isBound) {
  25.                 try {
  26.                     int result = myAidlService.add(5, 3);
  27.                     Toast.makeText(MainActivity.this, "Result: " + result, Toast.LENGTH_SHORT).show();
  28.                 } catch (RemoteException e) {
  29.                     e.printStackTrace();
  30.                 }
  31.             }
  32.         });
  33.     }
  34.     @Override
  35.     protected void onDestroy() {
  36.         super.onDestroy();
  37.         if (isBound) {
  38.             unbindService(connection);
  39.             isBound = false;
  40.         }
  41.     }
  42. }
复制代码
4. Service 的优化建媾和最佳实践

4.1 异步操作

为了避免阻塞主线程,在 Service 中处理耗时操作时,应利用异步使命或线程池。例如,利用 AsyncTask 或 ExecutorService 来处理背景使命。
4.2 资源管理

确保在 Service 制止时开释全部资源,避免内存走漏。例如,在 onDestroy 方法中关闭任何打开的资源(如文件、网络连接等)。
4.3 前台服务

对于必要长期运行的服务,利用前台服务,并提供持续显示的关照,确保服务在体系资源紧张时不被杀死。
  1. @Override
  2. public void onCreate() {
  3.     super.onCreate();
  4.     executorService = Executors.newSingleThreadExecutor();
  5.     // Create the notification channel for Android O and above
  6.     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
  7.         NotificationChannel channel = new NotificationChannel("download_channel", "Download Service", NotificationManager.IMPORTANCE_DEFAULT);
  8.         NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
  9.         if (manager != null) {
  10.             manager.createNotificationChannel(channel);
  11.         }
  12.     }
  13.     // Start foreground service
  14.     Notification notification = new NotificationCompat.Builder(this, "download_channel")
  15.             .setContentTitle("Downloading")
  16.             .setContentText("Downloading in progress")
  17.             .setSmallIcon(R.drawable.ic_download)
  18.             .build();
  19.     startForeground(1, notification);
  20. }
复制代码
4.4 权限管理

在必要与其他应用通信的 Service 中,确保利用适当的权限保护机制,防止未授权访问。例如,利用 android:permission 属性限定哪些应用可以绑定服务。
  1. <service android:name=".MyAidlService"
  2.     android:permission="com.example.myapp.permission.BIND_MY_SERVICE">
  3.     <intent-filter>
  4.         <action android:name="com.example.myapp.BIND" />
  5.     </intent-filter>
  6. </service>
复制代码
5. 利用场景和总结

Service 在 Android 应用中的利用场景广泛,包括但不限于:


  • 背景音乐播放:利用 Service 处理音乐播放使命,即利用户脱离了应用界面,音乐也可以继承播放。
  • 数据同步:利用 Service 定期同步数据,如邮件、联系人、日历等。
  • 位置跟踪:利用 Service 持续获取并处理位置信息,实现位置跟踪功能。
  • 文件下载:利用 Service 在背景下载大文件,并在下载完成后关照用户。
  • 网络哀求:利用 Service 处理长时间运行的网络哀求,避免阻塞主线程。
通过深入明白和合理计划 Service,可以有效地提拔 Android 应用的性能和用户体验。无论是简朴的异步使命,还是复杂的跨进程通信,通过合理利用 Service,结合详细需求进行优化,是构建高效、稳定的 Android 应用的重要一环。希望以上示例和详细说明可以或许资助开发者更好地明白和利用 Service,实现更强大和高效的应勤奋能。
接待点赞|关注|收藏|评论,您的肯定是我创作的动力


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

傲渊山岳

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表