安卓开发实现监控应用死亡 - DeathRecipient

以下是如何使用Kotlin实现监控应用(客户端)死亡的步骤和代码示例。Android的DeathRecipient接口可以让Service感知到绑定的客户端(如Activity)进程的死亡。


如何监控Application的死亡

基本原理
  1. 客户端(Client):通常是一个Activity,向Service传递一个IBinder对象。
  2. 服务端(Service):通过linkToDeath方法注册一个DeathRecipient,当客户端进程死亡时,Service会收到通知。
  3. 死亡通知:当客户端被杀死(例如通过adb shell kill <pid>),DeathRecipientbinderDied()方法会被调用。
实现步骤
  1. 定义AIDL接口(用于Client和Service之间的通信)。
  2. 在客户端中创建一个Binder对象并传递给Service。
  3. 在Service中实现DeathRecipient,并通过linkToDeath监控客户端的死亡。
  4. 测试:启动应用,绑定Service,杀死客户端进程,观察日志。

Kotlin实现代码

1. 定义AIDL接口(ITest.aidl)

创建一个名为ITest.aidl的文件,路径为app/src/main/aidl/com/example/testservice/ITest.aidl

package com.example.testservice;

interface ITest {
    int getPid();
    void setBinder(IBinder client);
}
2. 客户端实现(MainActivity.kt)
package com.example.testservice

import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.example.testservice.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private val TAG = "TestService"
    private lateinit var binding: ActivityMainBinding
    private val intent = Intent("com.example.action.TEST").apply {
        setPackage(packageName) // 确保绑定到正确的Service
    }
    private val binder = object : android.os.Binder() {} // 客户端的Binder对象
    private var testService: ITest? = null

    private val serviceConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            Log.d(TAG, "onServiceConnected: $name")
            testService = ITest.Stub.asInterface(service)
            try {
                testService?.setBinder(binder) // 传递Binder给Service
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            Log.d(TAG, "onServiceDisconnected")
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // 按钮点击事件
        binding.start.setOnClickListener { startService(intent) }
        binding.stop.setOnClickListener { stopService(intent) }
        binding.bind.setOnClickListener { bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE) }
        binding.unbind.setOnClickListener { unbindService(serviceConnection) }
    }
}
3. 服务端实现(TestService.kt)
package com.example.testservice

import android.app.Service
import android.content.Intent
import android.os.IBinder
import android.util.Log

class TestService : Service() {

    private val TAG = "TestService"
    private val testApi = TestApi()
    private var clientBinder: IBinder? = null

    override fun onBind(intent: Intent?): IBinder {
        Log.d(TAG, "onBind() action=${intent?.action}")
        return testApi
    }

    // DeathRecipient实现
    private inner class TestDeathRecipient : IBinder.DeathRecipient {
        override fun binderDied() {
            Log.d(TAG, "客户端已死亡")
            clientBinder = null // 清理引用
        }
    }

    // AIDL接口实现
    private inner class TestApi : ITest.Stub() {
        override fun getPid(): Int {
            return Thread.currentThread().id.toInt()
        }

        override fun setBinder(client: IBinder?) {
            clientBinder = client
            clientBinder?.linkToDeath(TestDeathRecipient(), 0) // 注册死亡通知
        }
    }
}
4. AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.testservice">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service
            android:name=".TestService"
            android:process=":service">
            <intent-filter>
                <action android:name="com.example.action.TEST" />
            </intent-filter>
        </service>
    </application>
</manifest>
5. 布局文件(activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start" />

    <Button
        android:id="@+id/stop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/start"
        android:text="Stop" />

    <Button
        android:id="@+id/bind"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/start"
        android:text="Bind" />

    <Button
        android:id="@+id/unbind"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/stop"
        android:layout_toRightOf="@id/bind"
        android:text="Unbind" />
</RelativeLayout>

测试步骤

  1. 启动应用,点击“Start”按钮启动Service。
  2. 点击“Bind”按钮绑定Service。
  3. 使用adb shell ps | grep com.example.testservice找到客户端进程的PID。
  4. 使用adb shell kill <pid>杀死客户端进程。
  5. 检查Logcat,观察是否打印出"客户端已死亡"日志。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值