【问题标题】:How to delete an SMS from the inbox in Android programmatically?如何以编程方式从 Android 的收件箱中删除短信?
【发布时间】:2010-09-29 23:17:26
【问题描述】:

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

其他 Google 小组关于以编程方式从 Android 收件箱中删除 SMS 消息的明确答案的问题似乎并不紧迫。

所以场景:

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

完成了吗?能做到吗?

【问题讨论】:

  • 我发现使用 Android 的手机功能做任何有用的事情都是一种非常不愉快的体验。
  • 好朋友。我正在寻找类似的东西:D欢呼
  • 最好首先防止短信到达收件箱:stackoverflow.com/questions/1741628/…

标签: android sms


【解决方案1】:

“从 Android 1.6 开始,传入的 SMS 消息广播 (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>

在您的BroadcastReceiver 中,在onReceive() 方法中,在对您的消息执行任何操作之前,只需调用abortBroadcast();

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

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

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

【讨论】:

【解决方案2】:

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

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

注意:我无法删除 content://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 将收到的 SMS 交给我的意图。所以,不要把那个 RECEIVE_SMS 权限属性放在你的意图中!希望比我更聪明的人能告诉我为什么会这样。

【讨论】:

【解决方案3】:

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

我有一个接收器接收传入的 SMS 消息。现在,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 隐藏了该类,我不想仅仅为了使指标准确而复制所有代码。

【讨论】:

  • 道格,这太棒了。作为一个问题,您知道是否有必要向 Handler 发帖?我想知道在调用广播接收器之前是否将短信插入系统短信数据库?我可能不得不查看操作系统以查看插入发生的位置,但我认为将 SMS 插入某些数据库是在通知广播接收器之前发生的。对此有任何见解或您是否已经检查过?
【解决方案4】:
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"/>

【讨论】:

  • 我们如何获得短信ID?
  • @Dev01如果你想删除一个特定的短信,你必须有它的 id 对吗?如果不是,您必须使用地址或短信正文查询 id
【解决方案5】:

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

【讨论】:

【解决方案6】:

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

这里还有一些info

【讨论】:

    【解决方案7】:

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

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

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

    【讨论】:

      【解决方案8】:

      我无法使用 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 传送到系统之前,甚至在它到达收件箱之前,以某种方式实际拦截它。但是,我高度怀疑这是可行的。如果我错了,请纠正我。

      【讨论】:

      • 嗯,你在收件箱前拦截消息:你可以接收广播android.provider.Telephony.SMS_RECEIVED,你只需要一个权限android.permission.RECEIVE_SMS .您甚至可以通过调用 abortBroadcast() 轻松阻止消息到达收件箱,因为它是有序广播。附言一定很有趣 2 年后才更正:)
      【解决方案9】:

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

      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"/>
      

      【讨论】:

        【解决方案10】:

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

        【讨论】:

          【解决方案11】:

          看看这个链接,它会给你一个简单的逻辑概念:

          https://gist.github.com/5178e798d9a00cac4ddb
          只是延迟调用deleteSMS()函数,因为通知的时间和实际保存的时间略有不同......,详情也可以看看这个链接...... ..

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

          谢谢…………

          【讨论】:

            【解决方案12】:

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

            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);
            }
            

            【讨论】:

              【解决方案13】:

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

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

              【讨论】:

                【解决方案14】:

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

                【讨论】:

                  【解决方案15】:

                  删除一条短信而不是对话的示例:

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

                  【讨论】:

                    【解决方案16】:
                    @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;
                    }
                    

                    【讨论】:

                      【解决方案17】:

                      试试这个,我 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) {
                      
                      }
                      

                      【讨论】:

                        【解决方案18】:

                        使用此方法之一选择最后收到的短信并将其删除,在这种情况下,我将获取最多的短信并使用短信的线程和 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();
                        }
                        

                        【讨论】:

                          猜你喜欢
                          • 2012-03-15
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          相关资源
                          最近更新 更多