如何在 android 8.1 版中获取日历电子邮件 ID?

how to get the calendar email id in android version 8.1?

我正在尝试使用日历运行时权限获取日历的电子邮件 ID。它在 android 版本 6.1 中完美运行。所以我开始测试 8.1 版。

安装应用程序后,它会请求读取联系人的权限,我请求了权限,但在尝试登录应用程序时它在 logcat needs read contact permission 中输出错误。我不明白为什么会这样。

我需要获取日历电子邮件 ID 才能在 google 日历中插入相同的数据。所以我正在尝试获取读取联系人权限。

清单

<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.ACTION_MANAGE_OVERLAY_PERMISSION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Permissioncheck.java

public class Permissioncheck extends AppCompatActivity
{
    public static final int MY_PERMISSIONS_REQUEST_WRITE_CALENDAR = 123;
    public static final int MY_PERMISSIONS_REQUEST_READ_CONTACTS = 123;

    public static int OVERLAY_PERMISSION_REQ_CODE_CHATHEAD = 1234;
    Context context;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        context = Permissioncheck.this;
        boolean result = checkPermission();
        if (result)
        {
            writeCalendarEvent();
        }
    }

    private void writeCalendarEvent()
    {

        Log.d(Utils.LogTag, "lst_StartService -> Utils.canDrawOverlays(Main.this): " + Utils.canDrawOverlays(Permissioncheck.this));
        if(Utils.canDrawOverlays(Permissioncheck.this))
        {
            checkPermission_Contact();
            startService();
        } else {
            requestPermission(OVERLAY_PERMISSION_REQ_CODE_CHATHEAD);
        }
    }

    public void startService()
    {
        boolean results = checkPermission_Contact();
        if (results)
        {
            Intent k = new Intent(context, Login.class);
            startActivity(k);
        }

    }

    private void needPermissionDialog(final int requestCode)
    {
        android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(Permissioncheck.this);
        builder.setMessage("You need to allow permission");
        builder.setPositiveButton("OK", new android.content.DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which)
            {
                // TODO Auto-generated method stub
                requestPermission(requestCode);
            }
        });
        builder.setNegativeButton("Cancel", new android.content.DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which)
            {
                // TODO Auto-generated method stub

            }
        });
        builder.setCancelable(false);
        builder.show();
    }

    @Override
    protected void onResume()
    {
        // TODO Auto-generated method stub
        super.onResume();
    }

    private void requestPermission(int requestCode)
    {
        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
        intent.setData(Uri.parse("package:" + getPackageName()));
        startActivityForResult(intent, requestCode);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == OVERLAY_PERMISSION_REQ_CODE_CHATHEAD)
        {
            if (!Utils.canDrawOverlays(Permissioncheck.this))
            {
                needPermissionDialog(requestCode);
            } else {
                startService();
            }
        }
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    public boolean checkPermission()
    {
        int currentAPIVersion = Build.VERSION.SDK_INT;
        if(currentAPIVersion>=android.os.Build.VERSION_CODES.M)
        {
            if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED) {
                if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, android.Manifest.permission.WRITE_CALENDAR)) {
                    AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
                    alertBuilder.setCancelable(true);
                    alertBuilder.setTitle("Permission necessary");
                    alertBuilder.setMessage("Write calendar permission is necessary to write event!!!");
                    alertBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {

                        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
                        public void onClick(DialogInterface dialog, int which) {
                            ActivityCompat.requestPermissions((Activity)context, new String[]{android.Manifest.permission.WRITE_CALENDAR}, MY_PERMISSIONS_REQUEST_WRITE_CALENDAR);
                        }
                    });
                    AlertDialog alert = alertBuilder.create();
                    alert.show();

                } else {
                    ActivityCompat.requestPermissions((Activity)context, new String[]{android.Manifest.permission.WRITE_CALENDAR}, MY_PERMISSIONS_REQUEST_WRITE_CALENDAR);
                }
                return false;
            } else {
                return true;
            }
        } else {
            return true;
        }
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    public boolean checkPermission_Contact()
    {
        int currentAPIVersion = Build.VERSION.SDK_INT;
        if(currentAPIVersion>=android.os.Build.VERSION_CODES.M)
        {

            if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {

                if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, Manifest.permission.READ_CONTACTS)) {

                    AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
                    alertBuilder.setCancelable(true);
                    alertBuilder.setTitle("Permission necessary");
                    alertBuilder.setMessage("Write calendar permission is necessary to write event!!!");
                    alertBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {

                        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
                        public void onClick(DialogInterface dialog, int which) {
                            ActivityCompat.requestPermissions((Activity)context, new String[]{android.Manifest.permission.READ_CONTACTS}, MY_PERMISSIONS_REQUEST_READ_CONTACTS);
                        }
                    });

                    AlertDialog alert = alertBuilder.create();
                    alert.show();

                } else {
                    ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.READ_CONTACTS}, MY_PERMISSIONS_REQUEST_READ_CONTACTS);

                } return false;
            } else {
                return true;
            }

        } else {
            return true;
        }

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_WRITE_CALENDAR:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    writeCalendarEvent();
                } else {
                    //code for deny
                }
            break;
        }
    }
}

New_Schedule_Calendar.java //我在这里尝试获取日历电子邮件 ID

int calenderId = -1;
String calenderEmaillAddress = possibleEmail;
String[] projection = new String[]{
    CalendarContract.Calendars._ID,
    CalendarContract.Calendars.ACCOUNT_NAME
};

ContentResolver cr = context.getContentResolver();
Cursor cursor = cr.query(Uri.parse("content://com.android.calendar/calendars"), projection, //here i am getting error
CalendarContract.Calendars.ACCOUNT_NAME + "=? and (" +
CalendarContract.Calendars.NAME + "=? or " +
CalendarContract.Calendars.CALENDAR_DISPLAY_NAME + "=?)",
new String[]{calenderEmaillAddress, calenderEmaillAddress,
calenderEmaillAddress}, null);

if (cursor.moveToFirst()) {

    if (cursor.getString(1).equals(calenderEmaillAddress)) {

        calenderId = cursor.getInt(0);
    }
}
cal_id=calenderId;

logcat错误

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.myapplication, PID: 6789
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.myapplication/com.example.myapplication.Schedule_Delete}: java.lang.SecurityException: Permission Denial: reading com.android.providers.calendar.CalendarProvider2 uri content://com.android.calendar/calendars from pid=6789, uid=10212 requires android.permission.READ_CALENDAR, or grantUriPermission()
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2974)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3059)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1724)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:7000)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:441)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1408)
Caused by: java.lang.SecurityException: Permission Denial: reading com.android.providers.calendar.CalendarProvider2 uri content://com.android.calendar/calendars from pid=6789, uid=10212 requires android.permission.READ_CALENDAR, or grantUriPermission()
at android.os.Parcel.readException(Parcel.java:2021)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
at android.content.ContentProviderProxy.query(ContentProviderNative.java:418)
at android.content.ContentResolver.query(ContentResolver.java:760)
at android.content.ContentResolver.query(ContentResolver.java:710)
at android.content.ContentResolver.query(ContentResolver.java:668)
at com.example.myapplication.New_Schedule_Calendar.writeCalendarEvent(New_Schedule_Calendar.java:111)
at com.example.myapplication.New_Schedule_Calendar.Start_Write(New_Schedule_Calendar.java:50)
at com.example.myapplication.Schedule_Delete.onCreate(Schedule_Delete.java:44)
at android.app.Activity.performCreate(Activity.java:7258)
at android.app.Activity.performCreate(Activity.java:7249)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1222)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2927)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3059) 
at android.app.ActivityThread.-wrap11(Unknown Source:0) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1724) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loop(Looper.java:164) 
at android.app.ActivityThread.main(ActivityThread.java:7000) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:441) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1408) 

我想获取电子邮件 ID 并将数据插入 google 日历。

应用程序崩溃:

已授予所有权限:

请求访问联系人

您似乎误读了 LogCat 上的警告,上面写着:

Caused by: java.lang.SecurityException: ... requires android.permission.READ_CALENDAR ...

原因是你只要求WRITE_CALENDAR权限而不是READ_CALENDAR权限,在Android8之前,如果你被授予任何权限,你也自动授予同一权限组内的所有权限,此行为已被修改,您需要指定所需的所有权限。

所以只需更改

ActivityCompat.requestPermissions((Activity)context, new String[]{android.Manifest.permission.WRITE_CALENDAR}, MY_PERMISSIONS_REQUEST_WRITE_CALENDAR);

至:

ActivityCompat.requestPermissions((Activity)context, new String[]{permission.WRITE_CALENDAR, permission.READ_CALENDAR}, MY_PERMISSIONS_REQUEST_WRITE_CALENDAR);

此外,我认为给 MY_PERMISSIONS_REQUEST_WRITE_CALENDARMY_PERMISSIONS_REQUEST_READ_CONTACTS 不同的请求代码是明智的。