zoukankan      html  css  js  c++  java
  • android 8.0 Account行为变更 账号系统

    我们有个方法,是判断系统的账号有没有登录。

    public static boolean isAccountLogin(Context context) {
            String df = "com.z**;
            AccountManager accountManager = AccountManager.get(context);
    
            try {
                Account[] accounts = accountManager.getAccountsByType(df);
                if (accounts != null && accounts.length > 0) {
                    Account account = accounts[0];
                    SDKLogUtils.d("PackageUtils", account.toString());
                    if (account != null) {
                        return true;
                    }
                } else {
                    SDKLogUtils.d("PackageUtils", "com.ztemt account is null");
                }
            } catch (Exception var5) {
                var5.printStackTrace();
            }
    
            return false;
        }
    

    这个在8.0以前的手机,完全没问题。但是8.0就有问题。而且改一下target 版本到8.0才有问题。

    赶紧查一下。果然8.0变更了。https://developer.android.com/about/versions/oreo/android-8.0-changes.html

    Apps targeting Android 8.0 这个是target 提到8.0以后才需要注意的
    These behavior changes apply exclusively to apps that are targeting Android 8.0 (API level 26) or higher. Apps that compile against Android 8.0, or set targetSdkVersion to Android 8.0 or higher must modify their apps to support these behaviors properly, where applicable to the app.
    Account access and discoverability
    In Android 8.0 (API level 26), apps can no longer get access to user accounts unless the authenticator owns the accounts or the user grants that access. The GET_ACCOUNTS permission is no longer sufficient. To be granted access to an account, apps should either use AccountManager.newChooseAccountIntent() or an authenticator-specific method. After getting access to accounts, an app can can call AccountManager.getAccounts() to access them.
    Android 8.0 deprecates LOGIN_ACCOUNTS_CHANGED_ACTION. Apps should instead use addOnAccountsUpdatedListener() to get updates about accounts during runtime.

    For information about new APIs and methods added for account access and discoverability, see Account Access and Discoverability in the New APIs section of this document.

    OK,下载下来8.0的代码,看下

        public Account[] getAccountsByType(String type) {
            return getAccountsByTypeAsUser(type, Process.myUserHandle());
        }
    
        /** @hide Same as {@link #getAccountsByType(String)} but for a specific user. */
        @NonNull
        public Account[] getAccountsByTypeAsUser(String type, UserHandle userHandle) {
            try {
                return mService.getAccountsAsUser(type, userHandle.getIdentifier(),
                        mContext.getOpPackageName());
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    
    
        private final IAccountManager mService;
    

    这个Service 是个啥?
    我也不知道,用SourceInsight 全局搜一下getAccountsAsUser 这个方法的实现吧。好吧,没收到。
    看了别人的,说是:AccountManagerService,可能是sdk 源码不全

    OK,继续
    最终会调用到这里:

    
        /**
         * Method which handles default values for Account visibility.
         *
         * @param account The account to check visibility.
         * @param packageName Package name to check visibility
         * @param accounts UserAccount that currently hosts the account and application
         *
         * @return Visibility value, the method never returns AccountManager.VISIBILITY_UNDEFINED
         *
         */
        private Integer resolveAccountVisibility(Account account, @NonNull String packageName,
                UserAccounts accounts) {
            Preconditions.checkNotNull(packageName, "packageName cannot be null");
            int uid = -1;
            try {
                long identityToken = clearCallingIdentity();
                try {
                    uid = mPackageManager.getPackageUidAsUser(packageName, accounts.userId);
                } finally {
                    restoreCallingIdentity(identityToken);
                }
            } catch (NameNotFoundException e) {
                Log.d(TAG, "Package not found " + e.getMessage());
                return AccountManager.VISIBILITY_NOT_VISIBLE;
            }
    
            // System visibility can not be restricted.
            if (UserHandle.isSameApp(uid, Process.SYSTEM_UID)) {
                return AccountManager.VISIBILITY_VISIBLE;
            }
    
            int signatureCheckResult =
                    checkPackageSignature(account.type, uid, accounts.userId);
    
            // Authenticator can not restrict visibility to itself.
            if (signatureCheckResult == SIGNATURE_CHECK_UID_MATCH) {
                return AccountManager.VISIBILITY_VISIBLE; // Authenticator can always see the account
            }
    
            // Return stored value if it was set.
            int visibility = getAccountVisibilityFromCache(account, packageName, accounts);
    
            if (AccountManager.VISIBILITY_UNDEFINED != visibility) {
                return visibility;
            }
    
            boolean isPrivileged = isPermittedForPackage(packageName, uid, accounts.userId,
                    Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
    
            // Device/Profile owner gets visibility by default.
            if (isProfileOwner(uid)) {
                return AccountManager.VISIBILITY_VISIBLE;
            }
    
            boolean preO = isPreOApplication(packageName);
            if ((signatureCheckResult != SIGNATURE_CHECK_MISMATCH)
                    || (preO && checkGetAccountsPermission(packageName, uid, accounts.userId))
                    || (checkReadContactsPermission(packageName, uid, accounts.userId)
                        && accountTypeManagesContacts(account.type, accounts.userId))
                    || isPrivileged) {
                // Use legacy for preO apps with GET_ACCOUNTS permission or pre/postO with signature
                // match.
                visibility = getAccountVisibilityFromCache(account,
                        AccountManager.PACKAGE_NAME_KEY_LEGACY_VISIBLE, accounts);
                if (AccountManager.VISIBILITY_UNDEFINED == visibility) {
                    visibility = AccountManager.VISIBILITY_USER_MANAGED_VISIBLE;
                }
            } else {
                visibility = getAccountVisibilityFromCache(account,
                        AccountManager.PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE, accounts);
                if (AccountManager.VISIBILITY_UNDEFINED == visibility) {
                    visibility = AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE;
                }
            }
            return visibility;
        }
    

    只有这里返回对你可见,那么你才能访问账户。
    1.signatureCheckResult != SIGNATURE_CHECK_MISMATCH 同签名
    2.preO && checkGetAccountsPermission(packageName, uid, accounts.userId)
    target 大于android O 并且有GetAccounts 权限
    3.checkReadContactsPermission(packageName, uid, accounts.userId)
    && accountTypeManagesContacts(account.type, accounts.userId)
    当前的包名有 ReadContacts 权限,并且 授予账号的包,有Manifest.permission.WRITE_CONTACTS的权限
    4. 享有特权的, 即 有GET_ACCOUNTS_PRIVILEGED权限

    总结:
    1.源码大概了解意思就行,不必每个东西都弄懂。
    2.一遍看不懂,或者没有看到关键,多看几遍。
    3.使用SourceInSight
    4.要时时关注最新的动态,不要改了东西,自己不知道。遇到问题了,去百度。看别人的博客。才知道怎么解决。

    参考:
    https://blog.csdn.net/gdutxiaoxu/article/details/80099717

  • 相关阅读:
    static_cast与dynamic_cast的联系与区别
    ActiveX控件实现
    Foundation: Rapid Prototyping and Building Framework from ZURB
    Python datetime / time conversions « SaltyCrane Blog
    Extending Django’s database API to include fulltext search
    解决linux下/etc/rc.local开机器不执行的原因。
    巧用 /etc/rc.local,开机时完成一些自动任务 GNU/Linux,Windows的終結者 KM大宝 和讯博客
    Kill process by name in python Stack Overflow
    Linux iostat监测IO状态
    An Introduction to Python: File I/O
  • 原文地址:https://www.cnblogs.com/caoxinyu/p/10568490.html
Copyright © 2011-2022 走看看