Che*_*eng 6 android runtime-permissions
我在真正的Nexus 5设备Android 6.0.1中观察到以下奇怪的结果
我在推出应用程序时运行以下简单代码.
Pattern emailPattern = Patterns.EMAIL_ADDRESS; // API level 8+
AccountManager accountManager = AccountManager.get(this);
Account[] accounts = accountManager.getAccounts();
Run Code Online (Sandbox Code Playgroud)
上面的代码工作正常,如果我将我设置targetSdkVersion为22,21,19.它返回非空数组.
但是,当我改变targetSdkVersion和测试时
defaultConfig {
applicationId "org.yccheok.myapplication"
minSdkVersion 19
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
Run Code Online (Sandbox Code Playgroud)
上面的代码返回0长度数组!
知道为什么在编译时会出现问题targetSdkVersion=23.
请注意,在产生问题期间,无论何时更改targetSdkVersion并通过Android Studio运行,您都需要清除应用数据,清除应用缓存并手动卸载所有用户.
以下是在Nexus 5设备Android 6.0.1中重现问题的步骤
<?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>
Run Code Online (Sandbox Code Playgroud)
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'
}
Run Code Online (Sandbox Code Playgroud)
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);
}
}
Run Code Online (Sandbox Code Playgroud)
知道为什么targetSdkVersion 23通过accountManager.getAccounts()返回0长度数组
小智 4
GET_ACCOUNTS is a dangerous permission and when using target sdk 23 needs to be managed with runtime permissions or it will not work.
You need to actually request permission from the user at runtime. example:
ActivityCompat.requestPermissions(this, new String[]
{Manifest.permission.GET_ACCOUNTS}, 1);
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.GET_ACCOUNTS);
Run Code Online (Sandbox Code Playgroud)
I've gone into detail about this in this answer here.
Dangerous permissions cover areas where the app wants data or resources that involve the user's private information, or could potentially affect the user's stored data or the operation of other apps. For example, the ability to read the user's contacts is a dangerous permission. If an app declares that it needs a dangerous permission, the user has to explicitly grant the permission to the app.
Important Note:
As stated in comment below, READ_CONTACTS permission is also MANDATORY.
If READ_CONTACTS permission is not obtained, accountManager.getAccounts() will return an empty array.
| 归档时间: |
|
| 查看次数: |
2868 次 |
| 最近记录: |