Android多进程之Binder的意外死亡及权限校验

简介:

Android多进程系列

通过前几篇文章,我们对Binder的使用和工作流程有了一定的了解,但是还有几个问题休要我们去解决。一个是如果服务端进程意外退出,Binder死亡,那客户端就会请求失败;还有一个就是权限校验问题,就是服务端需要校验一下客户端的身份权限,不能谁都能请求服务端的服务

Binder意外死亡的处理

给Binder设置DeathRecipient监听
  • 在绑定Service服务后的onServiceConnected回调中给Binder注册死亡回调DeathRecipient
private ServiceConnection mConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        Log.e(TAG, "ServiceConnection-->"+ System.currentTimeMillis());
        IBookManager bookManager = BookManagerImpl.asInterface(iBinder);
        mRemoteBookManager = bookManager;
        try {
            //注册死亡回调
            iBinder.linkToDeath(mDeathRecipient,0);
            ...

        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        Log.e(TAG, "onServiceDisconnected-->binder died");
    }
};
  • 在DeathRecipient中相应的处理,比如重新连接服务端
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
    @Override
    public void binderDied() {
        Log.e(TAG, "mDeathRecipient-->binderDied-->");
        if (mRemoteBookManager == null) {
            return;
        }
        mRemoteBookManager.asBinder().unlinkToDeath(mDeathRecipient, 0);
        mRemoteBookManager = null;
        //Binder死亡,重新绑定服务
        Log.e(TAG, "mDeathRecipient-->bindService");
        Intent intent = new Intent(MainActivity.this, BookManagerService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }
};
  • 为了测试,我们在服务端添加结束进程的代码
@Override
public void onCreate() {
    super.onCreate();
    Log.e(TAG, "onCreate-->"+ System.currentTimeMillis());
    new Thread(new ServiceWorker()).start();
}

private class ServiceWorker implements Runnable {
    @Override
    public void run() {
        while (!mIsServiceDestoryed.get()) {
            try {
                Thread.sleep(5000);
            }catch (InterruptedException e) {
                e.printStackTrace();
            }

            int bookId = mBookList.size() + 1;
            if (bookId == 8) {
                //结束当前进程,测试Binder死亡回调
                android.os.Process.killProcess(android.os.Process.myPid());
                return;
            }
            ...
        }
    }
}
  • 测试效果

服务端进程意外退出,客户端收到回调成功启动服务端

从上面的测试我们可以看到客户端在服务端进程意外退出后,通过重新绑定服务又把服务端进程启动了。此外,我们还可以在ServiceConnection的onServiceDisconnected方法中处理服务端进程意外退出的情况,方法是一样的,就不测试了。2种方法的区别就在于onServiceDisconnected方法在客户端的UI线程中被回调,而binderDied方法在客户端的Binder线程池中被回调

权限验证

在onBind中通过自定义权限来验证
  • 首先要自定义一个权限
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xxq2dream.android_ipc">
    
    <permission
        android:name="com.xxq2dream.permission.ACCESS_BOOK_SERVICE"
        android:protectionLevel="normal"/>
    
</manifest>
  • 然后在Service中的onBind方法中校验
@Nullable
@Override
public IBinder onBind(Intent intent) {
    Log.e(TAG, "onBind-->"+ System.currentTimeMillis());
    int check = checkCallingOrSelfPermission("com.xxq2dream.permission.ACCESS_BOOK_SERVICE");
    if (check == PackageManager.PERMISSION_DENIED) {
        Log.e(TAG, "PERMISSION_DENIED");
        return null;
    }
    Log.e(TAG, "PERMISSION_GRANTED");
    return mBinder;
}

权限校验被拒绝

  • 从上图中我们可以看到,由于我们的应用客户端没有声明服务端校验的权限,所以服务端校验不通过,我们只需要在我们的客户端添加相应的权限声明即可
<uses-permission android:name="com.xxq2dream.permission.ACCESS_BOOK_SERVICE"/>

权限校验通过

在onTransact方法中进行权限校验
private Binder mBinder = new BookManagerImpl(){
    @Override
    public List<Book> getBookList() throws RemoteException {
        Log.e(TAG, "getBookList-->"+ System.currentTimeMillis());
        return mBookList;
    }

    ...
    
    @Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        int check = checkCallingOrSelfPermission("com.xxq2dream.permission.ACCESS_BOOK_SERVICE");
        if (check == PackageManager.PERMISSION_DENIED) {
            Log.e(TAG, "PERMISSION_DENIED");
            return false;
        }
        
        String packageName = null;
        //获取客户端包名 
        String[] packages = getPackageManager().getPackagesForUid(getCallingUid());
        if (packages != null && packages.length > 0) {
            packageName = packages[0];
        }
        //校验包名
        if (!packageName.startsWith("com.xxq2dream")) {
            return false;
        }
        Log.e(TAG, "PERMISSION_GRANTED");
        return super.onTransact(code, data, reply,flags);
    }
};
结语
  • Binder的一个很好的应用就是推送消息和保活。比如我们可以创建一个Service运行在一个独立的进程中,然后和我们的应用进程中的一个Service绑定。独立进程的Service每隔一定的时间向我们的服务端请求查看是否有新的消息,有的话就拉取新的消息,然后通知给应用进程的Service,执行弹出通知之类的操作。应用程序退出后,我们的Service进程还是存活的,这样就可以一直接收消息。当然,如果用户一键清理或是直接结束应用的话,我们的Service进程仍然会被干掉。

欢迎关注我的微信公众号,期待与你一起学习,一起交流,一起成长!
AntDream

目录
相关文章
|
4月前
|
存储 安全 Android开发
"解锁Android权限迷宫:一场惊心动魄的动态权限请求之旅,让你的应用从平凡跃升至用户心尖的宠儿!"
【8月更文挑战第13天】随着Android系统的更新,权限管理变得至关重要。尤其从Android 6.0起,引入了动态权限请求,增强了用户隐私保护并要求开发者实现更精细的权限控制。本文采用问答形式,深入探讨动态权限请求机制与最佳实践,并提供示例代码。首先解释了动态权限的概念及其重要性;接着详述实现步骤:定义、检查、请求权限及处理结果;最后总结了六大最佳实践,包括适时请求、解释原因、提供替代方案、妥善处理拒绝情况、适应权限变更及兼容旧版系统,帮助开发者打造安全易用的应用。
84 0
|
3月前
|
存储 API Android开发
"解锁Android权限迷宫:一场惊心动魄的动态权限请求之旅,让你的应用从平凡跃升至用户心尖的宠儿!"
随着Android系统的更新,权限管理成为应用开发的关键。尤其在Android 6.0(API 级别 23)后,动态权限请求机制的引入提升了用户隐私保护,要求开发者进行更精细的权限管理。
79 2
|
3月前
|
Java Android开发 数据安全/隐私保护
Android中多进程通信有几种方式?需要注意哪些问题?
本文介绍了Android中的多进程通信(IPC),探讨了IPC的重要性及其实现方式,如Intent、Binder、AIDL等,并通过一个使用Binder机制的示例详细说明了其实现过程。
398 4
|
4月前
|
Android开发 开发者 Kotlin
Android 多进程情况下判断应用是否处于前台或者后台
本文介绍在多进程环境下判断Android应用前后台状态的方法。通过`ActivityManager`和服务信息`RunningAppProcessInfo`可有效检测应用状态,优化资源使用。提供Kotlin代码示例,帮助开发者轻松集成。
305 8
|
5月前
|
缓存 安全 Java
Android深入Binder拦截问题分析
【7月更文挑战第1天】Android Binder 拦截可实现虚拟化、测试、SDK检测、逆向分析及ROM扩展。通过Java层aidl代理,利用IBinder接口规范来拦截通信。拦截步骤包括:替换Binder服务缓存对象,如ActivityManagerService;代理ServiceManager以控制服务获取。此操作需系统权限,可能涉及安全风险和版本差异,非必要时应谨慎。
|
7月前
|
Java Shell Android开发
android 权限申请
android 权限申请
125 5
|
7月前
|
运维 Ubuntu 安全
运维最全linux 命令行操作串口_linux串口命令(2),2024年最新Linux运维源码的Binder权限是如何控制
运维最全linux 命令行操作串口_linux串口命令(2),2024年最新Linux运维源码的Binder权限是如何控制
运维最全linux 命令行操作串口_linux串口命令(2),2024年最新Linux运维源码的Binder权限是如何控制
|
7月前
|
存储 Java API
Android系统 文件访问权限笔记
Android系统 文件访问权限笔记
633 1
|
7月前
|
XML 前端开发 Android开发
Android架构设计——MVC(1),Android多进程从头讲到尾
Android架构设计——MVC(1),Android多进程从头讲到尾
|
7月前
|
XML API 数据库
Android权限
Android权限 【5月更文挑战第3天】
118 0

相关实验场景

更多