簡介
在開發中,遇到Calling a method in the system process without a qualified user這樣的錯誤
原因:在Android 4.2以後,增加了多用戶,需要使用如下發送廣播
context.sendBroadcastAsUser(intent,UserHandle.ALL);
添加權限
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
但是會發現UserHandle獲取不到UserHandle.ALL,查看源碼
public final class UserHandle implements Parcelable {
// NOTE: keep logic in sync with system/core/libcutils/multiuser.c
/**
* @hide Range of uids allocated for a user.
*/
@UnsupportedAppUsage
public static final int PER_USER_RANGE = 100000;
/** @hide A user id to indicate all users on the device */
@UnsupportedAppUsage
public static final @UserIdInt int USER_ALL = -1;
/** @hide A user handle to indicate all users on the device */
@SystemApi
@TestApi
public static final @NonNull UserHandle ALL = new UserHandle(USER_ALL);
/** @hide A user id to indicate the currently active user */
@UnsupportedAppUsage
public static final @UserIdInt int USER_CURRENT = -2;
/** @hide A user handle to indicate the current user of the device */
@SystemApi
@TestApi
public static final @NonNull UserHandle CURRENT = new UserHandle(USER_CURRENT);
/** @hide A user id to indicate that we would like to send to the current
* user, but if this is calling from a user process then we will send it
* to the caller's user instead of failing with a security exception */
@UnsupportedAppUsage
public static final @UserIdInt int USER_CURRENT_OR_SELF = -3;
/** @hide A user handle to indicate that we would like to send to the current
* user, but if this is calling from a user process then we will send it
* to the caller's user instead of failing with a security exception */
@UnsupportedAppUsage
public static final @NonNull UserHandle CURRENT_OR_SELF = new UserHandle(USER_CURRENT_OR_SELF);
/** @hide An undefined user id */
@UnsupportedAppUsage
public static final @UserIdInt int USER_NULL = -10000;
/**
* @hide A user id constant to indicate the "owner" user of the device
* @deprecated Consider using either {@link UserHandle#USER_SYSTEM} constant or
* check the target user's flag {@link android.content.pm.UserInfo#isAdmin}.
*/
@UnsupportedAppUsage
@Deprecated
public static final @UserIdInt int USER_OWNER = 0;
}
我們主要使用如下幾個
UserHandle.ALL | 設備上所有用戶可接收到廣播 |
UserHandle.CURRENT | 設備上當前用戶可接收到廣播 |
UserHandle.CURRENT_OR_SELF | 設備上當前用戶或者該應用所屬用戶可接收到廣播 |
UserHandle.OWNER | 設備所有者可接收到廣播 |
UserHandle.SYSTEM | system用戶可以接收到廣播 |
由於上面都是隱藏代碼,所以我們可以使用如下方式獲得
一:反射
Class<UserHandle> cls = UserHandle.class;
try {
Field field = cls.getField("ALL");
Object allObject = field.get(null);
sendBroadcastAsUser(intent, (UserHandle)allObject);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
二:使用parcel
Parcel p = Parcel.obtain();
p.writeInt(-1);
sendBroadcastAsUser(intent, new UserHandle(p));
三:getUserHandleForUid
sendBroadcastAsUser(intent, UserHandle.getUserHandleForUid(-1));
參考