UserHandle.java学习小结

在Android 4.2.2的代码中看到现在支持多用户了,下面是证据:
public static final boolean MU_ENABLED = true;
在多用户情形下,就会有多个user(有点废话)。要理解多用户,弄清楚三个int值很关键,分别是uid、appid和user id。
这里的user id和uid容易弄混,我的理解是user id代表的就是当前是哪个user,在不支持多用户的系统中,当然这个值是唯一的,应该是0,但现在不一样了,不过本人还没有碰到它不为0的时候,我所见的大多时候它仍然是0,似乎跟单用户没有任何差别,或许以后会不一样的,这里是为以后扩展预留的。
uid = user id * 100,000  + appid(其中,0<=appid<100,000)

这个公式或许能有助于我们理解这三者的关系。下面这三个方法就不难理解了:
PER_USER_RANGE = 100,000

//已知 uid,求user id
public static final int getUserId(int uid) {
        if (MU_ENABLED) {
            return uid / PER_USER_RANGE;
        } else {
            return 0;
        }
    }
//已知uid,求appid
public static final int getAppId(int uid) {
        return uid % PER_USER_RANGE;
    }
//已知user id,appid,求uid
    public static final int getUid(int userId, int appId) {
        if (MU_ENABLED) {
            return userId * PER_USER_RANGE + (appId % PER_USER_RANGE);
        } else {
            return appId;
        }
    }
//代码通过user id判断是否是同一个用户;通过appid判断是否是同一个app。
public static final boolean isSameUser(int uid1, int uid2) {
        return getUserId(uid1) == getUserId(uid2);
    }
public static final boolean isSameApp(int uid1, int uid2) {
        return getAppId(uid1) == getAppId(uid2);
    }



另有几个uid的范围:
user id 为0的user:[0,99 999]
application appid:[10 000, 19 999]
shared application appid:[50 000, 59 999]
isolated appid:[99 000, 99 999]
system appid似乎是从1000开始,那猜测应该是到9 999结束。
有多个范围貌似没有被用到啊。

这个类有一个关键的成员变量:final int mHandle;在被初始化后不能修改,且这个类只有一个实例化方法。
它自己创建了三个实例:
ALL                              mHandle=-1
CURRENT                     mHandle=-2    
CURRENT_OR_SELF      mHandle=-3
OWNER                        mHandle=0   

### 在 Android 12.0 中通过指定 `UserHandle.SYSTEM` 解决 `bindService` 调用时出现的 "Calling a method in the system process without a qualified user" 问题 在 Android 12 中,当调用 `bindService` 方法时,如果未明确指定用户身份,可能会触发 "Calling a method in the system process without a qualified user" 错误。这通常是因为系统尝试以未定义的用户身份调用方法[^1]。为了解决此问题,可以使用 `bindServiceAsUser` 方法,并明确指定用户身份为 `UserHandle.SYSTEM`。 #### 使用 `bindServiceAsUser` 并指定 `UserHandle.SYSTEM` 从 Android 4.2 开始,提供了支持多用户的 API,例如 `bindServiceAsUser`,允许开发者明确指定用户身份。通过指定 `UserHandle.SYSTEM`,可以确保绑定服务时使用系统用户身份,从而避免上述错误。 以下是实现代码示例: ```java Context context = getApplicationContext(); Intent serviceIntent = new Intent(context, YourService.class); // 检查当前 API 级别是否支持 bindServiceAsUser if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { // 明确指定用户身份为 UserHandle.SYSTEM context.bindServiceAsUser(serviceIntent, connection, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM); } else { // 兼容旧版本 context.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE); } ``` #### 关键点说明 - **`UserHandle.SYSTEM`**:表示系统用户,适用于需要以系统身份调用服务的场景[^3]。 - **API 兼容性**:`bindServiceAsUser` 方法仅适用于 Android 4.2(API 级别 17)及更高版本。对于较低版本,需提供向后兼容的实现。 - **权限检查**:确保当前进程拥有足够的权限来绑定目标服务[^4]。 #### 注意事项 - **多用户支持**:确保应用逻辑能够正确处理多用户环境下的权限和数据隔离[^2]。 - **异常处理**:在调用 `bindServiceAsUser` 时,建议添加异常捕获机制,以便在发生错误时进行日志记录或采取其他措施。 #### 示例代码完整版 以下是一个完整的代码示例,展示如何在 Android 12 中安全地调用 `bindService` 并指定 `UserHandle.SYSTEM`: ```java public class MainActivity extends AppCompatActivity { private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 服务已连接 } @Override public void onServiceDisconnected(ComponentName name) { // 服务已断开 } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent serviceIntent = new Intent(this, YourService.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { // 指定用户身份为 UserHandle.SYSTEM bindServiceAsUser(serviceIntent, connection, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM); } else { // 兼容旧版本 bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE); } } } ``` ### 总结 通过使用 `bindServiceAsUser` 方法并指定 `UserHandle.SYSTEM`,可以有效解决在 Android 12 中调用 `bindService` 时出现的 "Calling a method in the system process without a qualified user" 错误。此外,确保应用逻辑与多用户支持机制兼容,并进行充分的权限检查,以避免潜在的问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值