我无法删除Android 8.0上的特定邮件
private void foo() {
Uri dummySms = insertDummySms(context, threadId);
removeDummySms(context, dummySms);
}
private Uri insertDummySms(Context context, long threadId) {
ContentValues values = new ContentValues();
values.put("thread_id", threadId);
values.put("body", "Dummy SMS body.");
Uri insert = context.getContentResolver().insert(Uri.parse("content://sms/sent"), values);
Log.i(TAG, "insertDummySms: " + insert);
return insert;
}
private void removeDummySms(Context context, Uri uri) {
Log.i(TAG, "removeDummySms: START: " + uri.toString() + " :: " + context.getContentResolver().getType(uri));
context.getContentResolver().delete(uri, null, null);
Log.i(TAG, "removeDummySms: END!!!");
}
当我运行foo()
方法时,日志会显示:
I/Test: insertDummySms: content://sms/sent//8
I/Test: removeDummySms: START: content://sms/sent//8 :: vnd.android.cursor.item/sms,
然后它崩溃了:
java.lang.IllegalArgumentException: Unknown URL
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:165)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
相同的代码适用于android 6.x和7.x
有趣的是:如果我删除这样的每一个短信:
context.getContentResolver().delete(uri, null, null); // where uri is equal: content://sms
它就像一个魅力。
任何想法失败的原因?
目前我只有一部手机安装了Android O,所以我不知道它是否会在每台Android O设备上崩溃。我有Nokia TA-1004
答案 0 :(得分:1)
对SmsProvider
类的一个相对较新的更改打破了那里的预期功能。从提供商的Uri
电话中返回的insert()
之前非常简单地表示为:
Uri uri = Uri.parse("content://" + table + "/" + rowID);
其中rowID
是来自insert()
的{{1}}来电的回复。
为了插入常规的完整短信,与您的情况一样,SQLiteDatabase
为table
。但是,还有其他几个表,主要由系统和默认消息传递应用程序使用,使用相同的"sms"
方法;例如,insert()
,"raw"
等。这些表上的插入导致返回的"attachments"
的权限无效;例如Uri
。
现在较新的版本会在无效的权限上抛出异常,而不是以静默方式失败,因此content://raw/123
构造被更改为:
Uri
以及后来:
Uri uri;
if (table == TABLE_SMS) {
uri = Uri.withAppendedPath(url, "/" + rowID);
} else {
uri = Uri.withAppendedPath(url, "/" + table + "/" + rowID );
}
解决第一个问题。
在这两个版本中,Uri uri = Uri.withAppendedPath(url, String.valueOf(rowID));
是您在url
电话中传递的版本。对于代码段中的ContentResolver#insert()
调用,最终会返回类似于insert()
的URI,其中存在问题。当在content://sms/sent/123
调用中传递它时,它与提供者的相应方法认为有效的任何URI都不匹配,因此它会抛出delete()
IllegalArgumentException
。
要解决此问题,您可以从返回中构建自己的有效URI,因为ID实际上只需要知道。例如:
Unknown URL
但是,在Uri del = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, dummySms.getLastPathSegment());
("content://sms/sent"
)开始插入可能是不正确的。该URI和其他类似的“盒子”URI(即Sms.Sent.CONTENT_URI
,Sms.Inbox.CONTENT_URI
等 - 用于查询,而不是写操作。
您应该在基座Sms.Drafts.CONTENT_URI
(Sms.CONTENT_URI
)上插入,并在"content://sms"
中将TYPE
设置为MESSAGE_TYPE_SENT
。例如,推荐的修复:
ContentValues
这将导致ContentValues cv = new ContentValues();
cv.put(Telephony.Sms.ADDRESS, ...);
cv.put(Telephony.Sms.BODY, ...);
cv.put(Telephony.Sms.TYPE, Telephony.Sms.MESSAGE_TYPE_SENT);
Uri uri = getContentResolver().insert(Telephony.Sms.CONTENT_URI, cv);
Uri
SmsProvider
方法识别出来的delete()
,您的删除操作应该像以前一样成功。