如何以编程方式从Android收件箱中删除短信?

时间:2009-01-07 04:25:02

标签: android sms

在Android手机上注册到应用程序的短信也会被发送到设备的收件箱。但是,为了防止混乱,能够从收件箱中删除特定于应用程序的SMS消息以减少这些消息的潜在溢出是很好的。

其他Google网上有关以程序化方式从Android收件箱中删除短信的明确答案的问题似乎并不紧迫。

所以场景:

  • Android App启动。
  • 注册短信类型X,Y和Z
  • 消息P,Q,X,Y,Z流在一段时间内全部存入收件箱
  • Android应用程序检测到X,Y,Z的接收(可能是程序中断事件的一部分)
  • 处理X,Y,Z
  • Desirement !!! X,Y,Z从Android收件箱中删除

它已经完成了吗?可以吗?

18 个答案:

答案 0 :(得分:87)

“从Android 1.6开始,传入的短信广播(android.provider.Telephony.SMS_RECEIVED)作为”有序广播“传送 - 这意味着您可以告诉系统哪些组件应首先接收广播。”

这意味着您可以拦截传入的消息并进一步中止广播。

AndroidManifest.xml文件中,请确保将优先级设置为最高:

<receiver android:name=".receiver.SMSReceiver" android:enabled="true">
    <intent-filter android:priority="1000">
        <action android:name="android.provider.Telephony.SMS_RECEIVED" />
    </intent-filter>
</receiver>

BroadcastReceiveronReceive()方法中,在对您的消息执行任何操作之前,只需致电abortBroadcast();

编辑:从KitKat开始,这显然不再有用了。

EDIT2:有关如何在KitKat上执行此操作的更多信息:

Delete SMS from android on 4.4.4 (Affected rows = 0(Zero), after deleted)

答案 1 :(得分:27)

使用其他人的建议,我认为我得到了它的工作:

(使用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)

另外参考,请确保将其放入您的意向接收器的清单中:

<receiver android:name=".intent.MySmsReceiver">
    <intent-filter>
        <action android:name="android.provider.Telephony.SMS_RECEIVED"></action>
    </intent-filter>
</receiver>

请注意,接收器标签看起来不像这样:

<receiver android:name=".intent.MySmsReceiver" 
    android:permission="android.permission.RECEIVE_SMS">

当我有这些设置时,android给了我一些疯狂的权限异常,不允许android.phone将收到的短信交给我的意图。所以,不要将RECEIVE_SMS权限属性放在你的意图中!希望比我更聪明的人能告诉我为什么会这样。

答案 2 :(得分:24)

所以,我有一个游戏, 可以删除收到的短信。 不幸的是,并非一帆风顺:(

我有一个接收器可以接收传入的短信。现在,Android SMS传入路由的工作方式是负责解码消息的代码片段发送广播(它使用sendBroadcast()方法 - 遗憾的是,这不是允许您简单地调用abortBroadcast()的版本)每当有消息到达时。

我的接收方可能会或可能不会在系统SMS接收方之前被呼叫,并且在任何情况下,所接收的广播都没有可以反映SMS表中_id列的属性。

但是,我不能轻易地停止(通过处理程序)一个延迟消息,并将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中隐藏了该类,并且我不想仅为了使指标准确而复制所有代码。

答案 3 :(得分:11)

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中使用此权限

<uses-permission android:name="android.permission.WRITE_SMS"/>

答案 4 :(得分:6)

最好使用_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)} );

答案 5 :(得分:5)

您需要找到邮件的URI。但是一旦你这样做,我认为你应该能够android.content.ContentResolver.delete(...)它。

这里还有一些info

答案 6 :(得分:2)

我认为暂时还不能完美。有两个基本问题:

  1. 当您尝试删除短信时,如何确保短信已经在收件箱中? 请注意,SMS_RECEIVED不是有序广播 所以dmyung的解决方案是完全尝试一个人的运气;即使延迟道格的答案也不能保证。

  2. SmsProvider不是线程安全的。(请参阅http://code.google.com/p/android/issues/detail?id=2916#c0
    多个客户端请求同时删除并插入其中的事实将导致数据损坏甚至立即运行时异常。

答案 7 :(得分:2)

我无法使用dmyung的解决方案,它在获取消息ID或线程ID时给了我一个异常。

最后,我使用了以下方法来获取线程ID:

private long getThreadId(Context context) {
    long threadId = 0;

    String SMS_READ_COLUMN = "read";
    String WHERE_CONDITION = SMS_READ_COLUMN + " = 0";
    String SORT_ORDER = "date DESC";
    int count = 0;

    Cursor cursor = context.getContentResolver().query(
                    SMS_INBOX_CONTENT_URI,
          new String[] { "_id", "thread_id", "address", "person", "date", "body" },
                    WHERE_CONDITION,
                    null,
                    SORT_ORDER);

    if (cursor != null) {
            try {
                count = cursor.getCount();
                if (count > 0) {
                    cursor.moveToFirst();
                    threadId = cursor.getLong(1);                              
                }
            } finally {
                    cursor.close();
            }
    }


    return threadId;
}

然后我可以删除它。但是,正如Doug所说,通知仍然存在,甚至在打开通知面板时也会显示该消息。只有在点击消息时我才能看到它是空的。

所以我猜这个唯一的方法就是在它发送到系统之前,甚至在它到达收件箱之前以某种方式拦截SMS。但是,我非常怀疑这是可行的。如果我错了,请纠正我。

答案 8 :(得分:2)

使用此功能删除特定的消息主题或根据您的需要进行修改:

public void delete_thread(String thread) 
{ 
  Cursor c = getApplicationContext().getContentResolver().query(
  Uri.parse("content://sms/"),new String[] { 
  "_id", "thread_id", "address", "person", "date","body" }, null, null, null);

 try {
  while (c.moveToNext()) 
      {
    int id = c.getInt(0);
    String address = c.getString(2);
    if (address.equals(thread)) 
        {
     getApplicationContext().getContentResolver().delete(
     Uri.parse("content://sms/" + id), null, null);
    }

       }
} catch (Exception e) {

  }
}

只需在下方调用此功能:

delete_thread("54263726");//you can pass any number or thread id here

不要忘记在下面添加android mainfest权限:

<uses-permission android:name="android.permission.WRITE_SMS"/>

答案 9 :(得分:1)

只需关闭默认短信应用的通知即可。处理您自己的所有短信通知!

答案 10 :(得分:1)

只要看一下这个链接,它就会简要介绍一下这个逻辑:

https://gist.github.com/5178e798d9a00cac4ddb
只是稍微调用deleteSMS()函数,因为通知时间和实际保存时间之间存在细微差别....有关详细信息,请查看此链接........ ..

http://htmlcoderhelper.com/how-to-delete-sms-from-inbox-in-android-programmatically/

感谢..........

答案 11 :(得分:1)

您只需尝试以下代码。它将删除所有手机中的短信(已接收或已发送)

Uri uri = Uri.parse("content://sms");

ContentResolver contentResolver = getContentResolver();

Cursor cursor = contentResolver.query(uri, null, null, null,
  null);



while (cursor.moveToNext()) {

 long thread_id = cursor.getLong(1);
 Uri thread = Uri.parse("content://sms/conversations/"
   + thread_id);
 getContentResolver().delete(thread, null, null);
}

答案 12 :(得分:1)

同时更新清单文件以删除需要写入权限的短信。

<uses-permission android:name="android.permission.WRITE_SMS"/>

答案 13 :(得分:1)

现在abortBroadcast();方法可用于限制传入邮件进入收件箱。

答案 14 :(得分:0)

删除一条短信而非会话的示例:

getContentResolver().delete(Uri.parse("content://sms/conversations/" + threadID), "_id = ?", new String[]{id});

答案 15 :(得分:0)

使用此方法之一选择最后收到的短信并删除它,在这种情况下,我获得最多的短信,并使用sms的线程和id值删除

try {
    Uri uri = Uri.parse("content://sms/inbox");
    Cursor c = v.getContext().getContentResolver().query(uri, null, null, null, null);
    int i = c.getCount();

    if (c.moveToFirst()) {
    }
} catch (CursorIndexOutOfBoundsException ee) {
    Toast.makeText(v.getContext(), "Error :" + ee.getMessage(), Toast.LENGTH_LONG).show();
}

答案 16 :(得分:0)

试试这个我100%确定这样可以正常工作: - //只需在此处输入转换地址,以便按地址删除整个转换(不要忘记在mainfest中添加读取,写入权限) 这是代码:

String address="put address only";

Cursor c = getApplicationContext().getContentResolver().query(Uri.parse("content://sms/"), new String[] { "_id", "thread_id", "address", "person", "date", "body" }, null, null, null);

try {
    while (c.moveToNext()) {
        int id = c.getInt(0);
        String address = c.getString(2);
        if(address.equals(address)){
        getApplicationContext().getContentResolver().delete(Uri.parse("content://sms/" + id), null, null);}
    }
} catch(Exception e) {

}

答案 17 :(得分:0)

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
    SMSData sms = (SMSData) getListAdapter().getItem(position);
    Toast.makeText(getApplicationContext(), sms.getBody(),
            Toast.LENGTH_LONG).show();
    Toast.makeText(getApplicationContext(), sms.getNumber(),
            Toast.LENGTH_LONG).show();

    deleteSms(sms.getId());

}

public boolean deleteSms(String smsId) {
    boolean isSmsDeleted = false;
    try {
        MainActivity.this.getContentResolver().delete(
                Uri.parse("content://sms/" + smsId), null, null);
        isSmsDeleted = true;

    } catch (Exception ex) {
        isSmsDeleted = false;
    }
    return isSmsDeleted;
}