在Android手机上,注册到应用程序的SMS消息也会发送到设备的收件箱.但是,为了防止混乱,能够从收件箱中删除特定于应用程序的SMS消息以减少这些消息的潜在溢出是很好的.
关于从Android收件箱中删除短信的程序化方式获得明确答案的其他Google网上论坛的问题似乎并不紧迫.
场景如下:
Android App启动.
注册SMS消息类型X,Y和Z.
消息P,Q,X,Y,Z流经过一段时间,全部存放在收件箱中
Android应用程序检测到X,Y,Z的接收(可能是程序中断事件的一部分)
过程X,Y,Z
Desirement!X,Y,Z将从Android收件箱中删除
它完成了吗?可以吗?
"从Android 1.6开始,传入的SMS消息广播(android.provider.Telephony.SMS_RECEIVED
)作为"有序广播"传送 - 这意味着您可以告诉系统哪些组件应该首先接收广播."
这意味着您可以拦截传入的消息并进一步中止广播.
在您的AndroidManifest.xml
文件中,确保将优先级设置为最高:
在您BroadcastReceiver
的onReceive()
方法中,在对您的消息执行任何操作之前,只需致电abortBroadcast();
编辑:从KitKat开始,这显然不再起作用了.
EDIT2:有关如何在KitKat上执行此操作的更多信息:
在4.4.4上删除Android上的短信(受影响的行= 0(零),删除后)
使用别人的建议,我想我得到了它的工作:
(使用SDK v1 R2)
它并不完美,因为我需要删除整个会话,但出于我们的目的,这是一个充分的妥协,因为我们至少会知道所有消息都将被查看和验证.我们的流程可能需要监听消息,捕获我们想要的消息,执行查询以获取最近发送的消息的thread_id并执行delete()调用.
在我们的活动中:
Uri uriSms = Uri.parse("content://sms/inbox"); Cursor c = getContentResolver().query(uriSms, null,null,null,null); int id = c.getInt(0); int thread_id = c.getInt(1); //get the thread_id getContentResolver().delete(Uri.parse("content://sms/conversations/" + thread_id),null,null);
注意:我无法对内容进行删除:// sms/inbox /或content:// sms/all /
看起来线程优先,这是有道理的,但错误信息只会使我更加愤怒.在sms/inbox /或sms/all /上尝试删除时,您可能会得到:
java.lang.IllegalArgumentException: Unknown URL at com.android.providers.telephony.SmsProvider.delete(SmsProvider.java:510) at android.content.ContentProvider$Transport.delete(ContentProvider.java:149) at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:149)
另外参考,请确保将其放入您的意向接收器的清单中:
请注意,接收器标签看起来不像这样:
当我有这些设置时,android给了我一些疯狂的权限异常,不允许android.phone将收到的短信交给我的意图.所以,不要将RECEIVE_SMS权限属性放在你的意图中!希望比我更聪明的人能告诉我为什么会这样.
所以,我有一出戏,它是可以删除收到的短信.不幸的是,这不是一帆风顺:(
我有一个接收器,可以接收传入的短信.现在,Android SMS传入路由的工作方式是负责解码消息的代码段发送一个广播(它使用的sendBroadcast()
方法 - 不幸的是,这不是允许你简单调用的版本abortBroadcast()
)每当消息到达时.
我的接收器可能会或可能不会在系统SMS接收器之前被调用,并且在任何情况下,所接收的广播都没有可以反映_id
SMS表中的列的属性.
但是,我不能轻易地停止(通过处理程序)使用SmsMessage作为附加对象的延迟消息.(我想你也可以给自己发一个Runnable ......)
handler.sendMessageDelayed(handler.obtainMessage(MSG_DELETE_SMS, msg), 2500);
延迟是为了确保在消息到达时所有广播接收器都已完成其内容并且消息将安全地存储在SMS表中.
当收到消息(或Runnable)时,我就是这样做的:
case MSG_DELETE_SMS: Uri deleteUri = Uri.parse("content://sms"); SmsMessage msg = (SmsMessage)message.obj; getContentResolver().delete(deleteUri, "address=? and date=?", new String[] {msg.getOriginatingAddress(), String.valueOf(msg.getTimestampMillis())});
我使用原始地址和时间戳字段来确保仅删除我感兴趣的消息的概率非常高.如果我想更加偏执,我可以将msg.getMessageBody()
内容作为查询的一部分包含在内.
是的,消息被删除(万岁!).不幸的是,通知栏未更新:(
当你打开通知区域时,你会看到那里的信息......但是当你点击它打开它时它就消失了!
对我来说,这还不够好 - 我希望消息的所有痕迹都消失 - 我不希望用户认为没有TXT(这只会导致错误报告).
在手机操作系统的内部MessagingNotification.updateNewMessageIndicator(Context)
,但我已经从API中隐藏了这个类,我不想复制所有代码只是为了使指标准确.
public boolean deleteSms(String smsId) { boolean isSmsDeleted = false; try { mActivity.getContentResolver().delete(Uri.parse("content://sms/" + smsId), null, null); isSmsDeleted = true; } catch (Exception ex) { isSmsDeleted = false; } return isSmsDeleted; }
在AndroidManifiest中使用此权限
最好使用_id和thread_id来删除消息.
Thread_id是分配给来自同一用户的消息的东西.因此,如果您仅使用thread_id,则发件人的所有邮件都将被删除.
如果您使用_id,thread_id的组合,那么它将删除您要删除的确切消息.
Uri thread = Uri.parse( "content://sms"); int deleted = contentResolver.delete( thread, "thread_id=? and _id=?", new String[]{String.valueOf(thread_id), String.valueOf(id)} );
您需要找到消息的URI.但是一旦你这样做,我认为你应该能够android.content.ContentResolver.delete(...)它.
这里有更多信息.