English 中文(简体)
如何在Android程序中编程从收件箱中删除短信?
原标题:
  • 时间:2009-01-07 04:25:01
  •  标签:

在安卓手机上,注册到应用程序的短信消息也会发送到设备的收件箱。但是,为了避免杂乱,能够从收件箱中删除特定应用程序的短信消息以减少潜在的信息溢出是很好的。

在其他谷歌组上就编程方式从安卓收件箱中删除短信的问题似乎并不紧迫。

所以情况是:

  • Android App startup.
  • register SMS message types X,Y and Z
  • messages P,Q,X,Y,Z stream in over the course of time, all deposited in inbox
  • Android application detects receipt of X,Y,Z (presumably as part of the program interrupt event)
  • process X,Y,Z
  • Desirement!!! X,Y,Z are deleted from the Android inbox

它已经完成了吗?它能完成吗?

问题回答

从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的最新版本,这似乎不再可行。

编辑2:如何在KitKat上完成此操作的更多信息:

从Android 4.4.4中删除短信(删除后受影响的行数为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);

注:我无法删除content:// sms / inbox /或content:// 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权限属性!希望比我更聪明的人能告诉我为什么会出现这种情况。

So, I had a play, and it is possible to delete a received SMS. Unfortunately it s not all plain sailing :(

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

我的接收器可能会在系统SMS接收器之前或之后被调用,而且无论哪种情况,接收到的广播都没有任何属性可以反映SMS表中的_id列。

然而,作为一个不易停止的人,我通过处理程序将SmsMessage作为附加对象发送了一条延迟消息(我想你也可以发送一个Runnable…)

handler.sendMessageDelayed(handler.obtainMessage(MSG_DELETE_SMS, msg), 2500);

延迟存在是为了确保当消息到达时,所有广播接收器都已完成其工作,并且消息将安全地嵌入短信列表中。

当接收到消息(或可运行对象)时,我会做这些:

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()内容作为查询的一部分包含在内。

Yes, the message IS deleted (hooray!). Unfortunately the notification bar is not updated :(

当您打开通知区域时,您会看到消息等待您查看... 但是当您点击打开它时,它就消失了!

对我来说,这还不够好 - 我希望信息的所有痕迹都消失 - 我不想让用户认为有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中使用此权限

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

最好使用_id和thread_id来删除信息。

Thread_id is something assigned to the messages coming from same user. So, if you use only thread_id, all the messages from the sender will get deleted.

如果您使用_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(...)来删除它。

这里有更多的信息

我认为目前无法完全解决它。存在两个基本问题:

  1. How can you make sure the sms is already in the inbox when you try to delete it?
    Notice that SMS_RECEIVED is not an ordered broadcast.
    So dmyung s solution is completely trying one s luck; even the delay in Doug s answer is not a guarantee.

  2. The SmsProvider is not thread safe.(refer to http://code.google.com/p/android/issues/detail?id=2916#c0)
    The fact that more than one clients are requesting delete and insert in it at the same time will cause data corruption or even immediate Runtime Exception.

我无法使用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;
}

然后我可以删除它。然而,正如道格所说,通知仍然存在,即使在打开通知面板时消息已经显示。只有在点击消息时,我才能看到它是空的。

我想唯一的方法是在短信到达系统之前,甚至在到达收件箱之前拦截短信。但是,我非常怀疑这是否可行。如果我错了,请纠正我。

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

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 manifest权限:

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

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

Just have a look at this link, it will give you a brief idea of the logic:

https://gist.github.com/5178e798d9a00cac4ddb
Just call the deleteSMS() function with some delay, because there is a slight difference between the time of notification and when it is saved actually...., for details have a look at this link also..........

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

Thanks..........

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

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

同时更新清单文件,需要写入权限才能删除短信。

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

现在abortBroadcast();方法可用于限制即将到来的消息进入收件箱。

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

getContentResolver().delete(Uri.parse("content://sms/conversations/" + threadID), "_id = ?", new String[]{id});
@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;
}

Try this i am 100% sure this will work fine:- //just put conversion address here for delete whole conversion by address(don t forgot to add read,write permission in mainfest) Here is Code:

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) {

}

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




相关问题
热门标签