プログラムでAndroidの受信トレイからSMSを削除する方法は?


98

Androidフォンでは、アプリケーションに登録されたSMSメッセージもデバイスの受信トレイに送信されます。ただし、混乱を防ぐために、アプリケーション固有のSMSメッセージを受信トレイから削除して、これらのメッセージの潜在的なオーバーフローを削減できると便利です。

プログラムでAndroidの受信トレイからSMSメッセージを削除する方法について明確な回答を得ることに関する他のGoogleグループへの質問は、差し迫ったものではないようです。

したがって、シナリオ:

  • Androidアプリの起動。
  • SMSメッセージタイプX、Y、Zを登録する
  • メッセージP、Q、X、Y、Zは、時間の経過とともにストリーミングされ、すべて受信トレイに保管されます
  • AndroidアプリケーションがX、Y、Zの受信を検出しました(おそらくプログラム割り込みイベントの一部として)
  • プロセスX、Y、Z
  • 欲望!!! X、Y、ZはAndroidの受信トレイから削除されます

それは行われましたか?できますか?


4
Androidの電話機能で何か便利なことをするのは非常に不愉快な経験であることがわかりました。
BobbyShaftoe 2009年

1
良い質問の仲間。私は似たようなものを探していました:D乾杯
Harsha MV

3
SMSが最初に受信トレイに到達しないようにするのが最善の方法です。stackoverflow.com
Christopher Orr

回答:


87

「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でそれを行う方法の詳細:

4.4.4のAndroidからSMSを削除します(影響を受ける行= 0(ゼロ)、削除後)



ここで、stackoverflow.com / questions / 25988574 / …をご覧ください。
Gangadhar Nimballi 2014

これに対する最良の答え= D
マイクブライアンオリベラ

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

注: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.phoneが受信したSMSを自分の意図に引き渡すことができない、クレイジーなアクセス許可の例外がいくつかありました。したがって、そのRECEIVE_SMS権限属性を意図的に使用しないでください。うまくいけば、私より賢い誰かが私にその理由を教えてくれるでしょう。


ここで、stackoverflow.com / questions / 25988574 / …をご覧ください。
Gangadhar Nimballi 2014

24

なので、遊んだところ、受信したSMSを削除すること可能です。残念ながら、それはすべて単純な航海ではありません:(

着信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がない場合にユーザーにTXTがあると思わせたくないです(バグレポートが発生するだけです)。

内部的にはOSで電話が呼び出されますがMessagingNotification.updateNewMessageIndicator(Context)、そのクラスはAPIから隠されており、インジケーターを正確にするためだけにそのコードのすべてを複製したくありませんでした。


ダグ、これは素晴らしい。質問として、ハンドラに投稿する必要があるかどうか知っていますか?SMSがシステムのSMSデータベースに挿入されてから、放送受信機が呼び出される前に挿入されるのでしょうか 挿入が発生する場所を確認するためにOSを調べる必要があるでしょうが、SMSのデータベースへの挿入は、ブロードキャストレシーバーに通知される前に行われると想定しています。これについて何か洞察がありますか、それともすでに確認しましたか?
Hamy

ここで、stackoverflow.com / questions / 25988574 / …をご覧ください。
Gangadhar Nimballi 2014

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

1
どうすればSMS IDを取得できますか?
Dev01 2014年


@ Dev01あなたが特定のSMSを削除したい場合は、そのIDが必要です?そうでない場合は、アドレスまたはsmsbodyのいずれかでIDをクエリする必要があります
Dr. aNdRO 2018

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

ここで、stackoverflow.com / questions / 25988574 / …をご覧ください。
Gangadhar Nimballi 2014

5

メッセージのURIを見つける必要があります。しかし、一度実行すると、android.content.ContentResolver.delete(...)を実行できるはずです。

ここではいくつかのより多くのだ情報


2

とりあえず、これは完全にはできません。2つの基本的な問題があります。

  1. SMSを削除しようとしたときに、SMSが受信トレイに既にあることをどのように確認できますか?
    SMS_RECEIVEDは順序付けられたブロードキャストではないことに注意してください。
    したがって、dmyungの解決策は、自分の運を完全に試すことです。ダグの答えの遅れでさえ、保証ではありません。

  2. SmsProviderはスレッドセーフではありません。(http://code.google.com/p/android/issues/detail?id=2916#c0を参照)
    複数のクライアントが削除と挿入を要求しているという事実同時にデータが破損したり、即座にランタイム例外が発生したりします。


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が受信トレイに到達する前に、SMSを実際に何らかの方法でインターセプトすることだと思います。しかし、私はこれが実行可能であることを強く疑います。私が間違っていたら訂正してください。


さて、あなた受信トレイの前にメッセージを傍受することについて間違っています:あなたはブロードキャストandroid.provider.Telephony.SMS_RECEIVEDを受信することができます、あなたはパーマションandroid.permission.RECEIVE_SMSだけを必要とします。メッセージは順序付けられたブロードキャストであるため、abortBroadcast()を呼び出すことで、メッセージが受信トレイに届かないようにすることも簡単にできます。PS 2年後に修正するにはおかしい必要があります:)
ラピス'17

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

1

デフォルトのSMSアプリの通知をオフにするだけです。すべてのテキストメッセージの独自の通知を処理します!


1

ちょうどこのリンクを見て、それはあなたのロジックの簡単なアイデアを与えるだろう。

https://gist.github.com/5178e798d9a00cac4ddb
時間の間にわずかな違いがあるためだけで、いくつかの遅延でdeleteSMS()関数を呼び出します通知のタイミングと実際に保存されるタイミング....、詳細については、このリンクも参照して

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

ありがとう..........


1

次のコードを試してみてください。すべて電話にあるすべてのSMSを削除します(受信または送信済み)

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

1

また、書き込み権限が必要なSMSを削除するために、マニフェストファイルを更新します。

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

1

これで、このabortBroadcast();メソッドを使用して、受信メッセージが受信トレイに移動するのを制限できます。


0

会話ではなく1つのSMSを削除するサンプル:

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

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

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

}

0

この方法の1つを使用して、最後に受信したSMSを選択して削除します。ここでは、最上位のSMSを取得して、スレッドと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();
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.