无法删除 Android 个日历
Cannot delete Android calendar
我一直在尝试使用 Android Calendar Provider 来创建本地(非同步)日历,但我最终得到了 ACCOUNT_TYPE
和 [=14 为空的日历=].我可以在以下位置看到它们:
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: the name must not be empty: null
at
android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:165)
at
android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
at
android.content.ContentProviderProxy.delete(ContentProviderNative.java:544)
at android.content.ContentResolver.delete(ContentResolver.java:1327)
我认为这是由于他们的帐户 type/name 为空造成的。
你知道我怎样才能摆脱它们吗?
注意:设备的 Android 版本是 6.0.1
这是发生了什么(注意所有链接都指向 5.1.1 CalendarProvider,但可以安全地假设它在 Android 6 中工作相同):
- 删除日历将始终通过此行:
CalendarProvider2.java, line 3206
- 现在,在 this line 中,每个要删除的日历都会调用方法
modifyCalendarSubscription
(无论您如何 select 编辑它们)。
- 在
modifyCalendarSubscription
中,提供商读取每个日历的 ACCOUNT_NAME 和 ACCOUNT_TYPE 列,并尝试创建一个 Account
instance
- 由于数据库中的帐户名称和类型是
null
,它在检查 null
值时在 Account
constructor 中崩溃。这就是您看到的 eException 实际被抛出的地方。
因此,无论您如何删除日历,它总是会在 Account
构造函数处失败,因为数据库中的帐户名称为空。
我还没有检查,但您可以使用更新操作覆盖帐户名称和类型。所以尝试将其设置为不是 null
.
的值
如果这不起作用,您要么需要 root 访问权限来手动删除日历,要么转到 Settings
-> Apps
-> All apps
-> Calendar storage
并清除整个日历数据库 (clear data
)。
更新
覆盖 ACCOUNT_NAME
和 ACCOUNT_TYPE
列只有在您设法匹配通过此行的条件时才有效:CalendarProvider2.java, line 3989 假设该行和到达那里的条件仍然存在在 Android 6.
如果您不将日历 ID 附加到 Uri
并且您不按其 ID select 日历,它认为它应该可以工作。因此,将 delete
设为 update
并将 ACCOUNT_NAME
和 ACCOUNT_TYPE
重置为非 null
的值应该可以解决问题。
我也遇到了同样的问题。我这样更新日历行:
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 中添加相同的帐户名称和帐户类型参数。
我一直在尝试使用 Android Calendar Provider 来创建本地(非同步)日历,但我最终得到了 ACCOUNT_TYPE
和 [=14 为空的日历=].我可以在以下位置看到它们:
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: the name must not be empty: null at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:165) at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135) at android.content.ContentProviderProxy.delete(ContentProviderNative.java:544) at android.content.ContentResolver.delete(ContentResolver.java:1327)
我认为这是由于他们的帐户 type/name 为空造成的。
你知道我怎样才能摆脱它们吗?
注意:设备的 Android 版本是 6.0.1
这是发生了什么(注意所有链接都指向 5.1.1 CalendarProvider,但可以安全地假设它在 Android 6 中工作相同):
- 删除日历将始终通过此行: CalendarProvider2.java, line 3206
- 现在,在 this line 中,每个要删除的日历都会调用方法
modifyCalendarSubscription
(无论您如何 select 编辑它们)。 - 在
modifyCalendarSubscription
中,提供商读取每个日历的 ACCOUNT_NAME 和 ACCOUNT_TYPE 列,并尝试创建一个Account
instance - 由于数据库中的帐户名称和类型是
null
,它在检查null
值时在Account
constructor 中崩溃。这就是您看到的 eException 实际被抛出的地方。
因此,无论您如何删除日历,它总是会在 Account
构造函数处失败,因为数据库中的帐户名称为空。
我还没有检查,但您可以使用更新操作覆盖帐户名称和类型。所以尝试将其设置为不是 null
.
如果这不起作用,您要么需要 root 访问权限来手动删除日历,要么转到 Settings
-> Apps
-> All apps
-> Calendar storage
并清除整个日历数据库 (clear data
)。
更新
覆盖 ACCOUNT_NAME
和 ACCOUNT_TYPE
列只有在您设法匹配通过此行的条件时才有效:CalendarProvider2.java, line 3989 假设该行和到达那里的条件仍然存在在 Android 6.
如果您不将日历 ID 附加到 Uri
并且您不按其 ID select 日历,它认为它应该可以工作。因此,将 delete
设为 update
并将 ACCOUNT_NAME
和 ACCOUNT_TYPE
重置为非 null
的值应该可以解决问题。
我也遇到了同样的问题。我这样更新日历行:
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 中添加相同的帐户名称和帐户类型参数。