无法删除Android日历

时间:2016-03-18 09:51:54

标签: android android-calendar

我一直在使用Android Calendar Provider来创建本地(非同步)日历,但我最终得到了带有ACCOUNT_TYPEACCOUNT_NAME的日历。我可以看到它们:

getContentResolver().query(CalendarContract.Calendars.CONTENT_URI, null, CalendarContract.Calendars.ACCOUNT_TYPE + " IS NULL", null, null);

现在我的Google日历应用在启动时崩溃了:(

我尝试使用这段代码删除这些虚拟日历(在成功请求WRITE_CALENDAR权限后):

getContentResolver().delete(CalendarContract.Calendars.CONTENT_URI, CalendarContract.Calendars.ACCOUNT_TYPE + " IS NULL", null);

但它引发了以下错误

  

java.lang.IllegalArgumentException:名称不能为空:null   在   android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:165)   在   android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)   在   android.content.ContentProviderProxy.delete(ContentProviderNative.java:544)   在android.content.ContentResolver.delete(ContentResolver.java:1327)

我认为,这是由于他们的帐户类型/名称为空。

你知道如何摆脱它们吗?

注意:Device的Android版本是6.0.1

2 个答案:

答案 0 :(得分:1)

以下是发生的事情(请注意所有链接指向5.1.1 CalendarProvider,但可以安全地假设它在Android 6中的工作方式相同):

  1. 删除日历将始终通过此行: CalendarProvider2.java, line 3206
  2. 现在在this line中,为每个要删除的日历调用方法modifyCalendarSubscription(无论您如何选择它们)。
  3. modifyCalendarSubscription中,提供商会为每个日历读取ACCOUNT_NAME和ACCOUNT_TYPE列,并尝试创建Account instance
  4. 由于数据库中的帐户名称和类型为null,因此在Account constructor检查null值时,它会崩溃。这就是你看到的eException实际上被抛出的地方。
  5. 因此,无论您如何删除日历,它都会在Account构造函数中失败,因为数据库中的帐户名称为空。

    我还没有检查,但您可以使用更新操作覆盖帐户名称和类型。因此,请尝试将其设置为不是null

    的内容

    如果这不起作用,您需要root权限才能手动删除日历,或者转到Settings - > Apps - > All apps - > Calendar storage并清除整个日历数据库(clear data)。

    <强>更新

    覆盖ACCOUNT_NAMEACCOUNT_TYPE列只有在您设置匹配条件才能通过此行时才会有效:CalendarProvider2.java, line 3989给定该行并且Android中的条件仍然存在6。 它认为如果您不将日历ID附加到Uri并且您没有按其ID选择日历,它应该有效。因此,让delete成为update并将ACCOUNT_NAMEACCOUNT_TYPE重置为非null的内容应该可以解决问题。

答案 1 :(得分:0)

我有同样的问题。我像这样更新日历行:

private void updateNullAccount() {
        String selection = CalendarContract.Calendars.ACCOUNT_NAME + " IS NULL";
        Uri uri = CalendarContract.Calendars.CONTENT_URI;
        uri = SyncAdapter.asSyncAdapter(uri);
        ContentValues values = new ContentValues();
        values.put(CalendarContract.Calendars.ACCOUNT_NAME, "NAME BITCH NAME");
        values.put(CalendarContract.Calendars.ACCOUNT_TYPE, CalendarContract.ACCOUNT_TYPE_LOCAL);
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        int count = getContentResolver().update(uri, values, selection, null);
        count++;
    }

我删除了ACCOUNT_NAME后的日历。

创建本地日历时,必须附加查询参数(作为同步适配器,帐户名和帐户类型),并在ContentValues中添加相同的帐户名和帐户类型参数。