targetSdkVersion 23 возвращает массив длины 0 через accountManager.getAccounts()

Я наблюдал следующий странный результат на своем реальном устройстве Nexus 5, Android 6.0.1.

Я запускаю следующий простой код во время запуска моего приложения.

Pattern emailPattern = Patterns.EMAIL_ADDRESS; // API level 8+
AccountManager accountManager = AccountManager.get(this);
Account[] accounts = accountManager.getAccounts();

Приведенный выше код работает нормально, если я устанавливаю для своего targetSdkVersion значение 22, 21, 19. Он возвращает непустой массив.

Однако, когда я меняю targetSdkVersion и тестирую с

defaultConfig {
    applicationId "org.yccheok.myapplication"
    minSdkVersion 19
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"
}

Приведенный выше код возвращает массив нулевой длины!

Любая идея, почему что-то ломается при компиляции с targetSdkVersion=23.

Обратите внимание, что во время возникновения проблемы всякий раз, когда вы меняете targetSdkVersion и запускаете его через Android Studio, вам необходимо очистить данные приложения, очистить кеш приложения и удалить его для всех пользователей вручную.

Вот шаги, чтобы воспроизвести проблему на устройстве Nexus 5, Android 6.0.1.

  1. Создайте проект в Android Studio через File -> New -> New Projetct...
  2. Выберите «Пустая активность»

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.yccheok.myapplication">

    <uses-permission android:name="android.permission.GET_ACCOUNTS"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        applicationId "org.yccheok.myapplication"
        minSdkVersion 19
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:design:23.1.1'
}

MainActivity.java

import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Patterns;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;

import java.util.regex.Pattern;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        int targetSdkVersion = 0;
        try {
            PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
            targetSdkVersion = packageInfo.applicationInfo.targetSdkVersion;
        }
        catch (PackageManager.NameNotFoundException e) {
            android.util.Log.i("CHEOK", e.getMessage());
        }

        Pattern emailPattern = Patterns.EMAIL_ADDRESS; // API level 8+
        AccountManager accountManager = AccountManager.get(this);
        Account[] accounts = accountManager.getAccounts();

        android.util.Log.i("CHEOK", targetSdkVersion + " : numnber of accoutn by ??? = " + accounts.length);

        for (Account account : accounts) {
            if (emailPattern.matcher(account.name).matches()) {
                String possibleEmail = account.name;
                android.util.Log.i("CHEOK", "possibleEmail = " + possibleEmail);
            }
        }

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

Любая идея, почему targetSdkVersion 23 возвращает массив длины 0 через accountManager.getAccounts()


person Cheok Yan Cheng    schedule 01.01.2016    source источник
comment
Может ли это быть связано с новой системой разрешений? Возможно, вам нужно будет запросить соответствующее разрешение во время выполнения, и вызов корректно завершится ошибкой? Просто выстрел в темноте.   -  person fweigl    schedule 02.01.2016


Ответы (1)


GET_ACCOUNTS — это опасное разрешение, и при использовании целевого SDK 23 требуется управляться с помощью разрешений во время выполнения, иначе это не сработает.

Фактически вам необходимо запросить разрешение у пользователя во время выполнения. пример:

      ActivityCompat.requestPermissions(this, new String[] 
      {Manifest.permission.GET_ACCOUNTS}, 1);

      int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,
      Manifest.permission.GET_ACCOUNTS);

Я подробно рассказал об этом в этот ответ здесь.

Опасные разрешения охватывают области, в которых приложению требуются данные или ресурсы, которые включают личную информацию пользователя или потенциально могут повлиять на сохраненные данные пользователя или работу других приложений. Например, возможность чтения контактов пользователя является опасным разрешением. Если приложение заявляет, что ему требуется опасное разрешение, пользователь должен явно предоставить разрешение приложению.

person Community    schedule 02.01.2016
comment
Я по-прежнему получаю 0 возвращаемого размера массива даже со всем этим, и я ориентируюсь на API 27. - person JPM; 20.02.2018
comment
@JPM, вам нужно будет опубликовать автономный вопрос с любыми соответствующими подробностями. В комментариях ответить невозможно. - person ; 21.02.2018
comment
Я видел это в двух разных приложениях, которые я закодировал без решения. Я отправлю отдельный вопрос, но боюсь, что другие просто укажут на это решение. - person JPM; 22.02.2018
comment
@JPM объясните, что вы пробовали и почему это решение не сработало. - person ; 22.02.2018
comment
@JPM Попросите у них разрешение READ_CONTACTS, он вернет список учетных записей. - person Srikar Reddy; 16.07.2018
comment
Я улучшил ответ, я думаю, что отсутствовал ключевой фрагмент примера кода для запроса явного разрешения. Теперь должно быть более ясно. - person MG Developer; 17.09.2018