프로그래밍 방식으로 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

1
좋은 질문 친구. 나는 비슷한 것을 찾고 있었다 : D cheers
Harsha MV

3
가장 좋은 방법은 처음에 SMS가받은 편지함에 도달하지 못하도록하는 것입니다. stackoverflow.com/questions/1741628/…
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>

당신에 BroadcastReceiveronReceive()방법, 당신의 메시지와 함께 아무것도 수행하기 전에, 단순히 전화abortBroadcast();

편집 : KitKat에서 이것은 더 이상 분명히 작동하지 않습니다.

EDIT2 : KitKat에서 수행하는 방법에 대한 추가 정보 :

4.4.4의 Android에서 SMS 삭제 (영향을받는 행 = 0 (0), 삭제 후)




이 = 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는 android.phone이 수신 된 SMS를 내 의도로 넘겨주는 것을 허용하지 않는 미친 권한 예외를 제공했습니다. 따라서 RECEIVE_SMS 권한 속성을 의도에 넣지 마십시오! 저보다 현명한 사람이 그 이유를 말해 줄 수 있기를 바랍니다.



24

그래서 나는 연극을했고, 이다 수신 된 SMS를 삭제할 수. 불행히도 그것은 모든 평범한 항해가 아닙니다 :(

수신 SMS 메시지를 수신하는 수신기가 있습니다. 이제 Android SMS 수신 라우팅이 작동하는 방식은 메시지를 디코딩하는 코드 조각이 메시지가 도착할 때마다 브로드 캐스트를 전송하는 것입니다 ( sendBroadcast()불행히도 단순히 호출 할 수있는 버전이 아닌 방법을 사용함 abortBroadcast()).

내 수신자는 Systems SMS 수신자보다 먼저 호출되거나 호출되지 않을 수 있으며, 어떤 경우에도 수신 된 브로드 캐스트에는 _idSMS 테이블 의 열을 반영 할 수있는 속성이 없습니다 .

그러나 SmsMessage를 첨부 된 개체로 사용하여 지연된 메시지를 (Handler를 통해) 쉽게 게시 할 수있는 중지되지는 않습니다. (당신도 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 2010-06-18


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를 조회 할 수 있습니다
박사 안드로

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

URI 를 찾아야합니다.메시지 . 그러나 일단 당신이 android.content.ContentResolver.delete (...) 할 수 있어야한다고 생각합니다.

여기에 더 많은 정보가 있습니다.


2

당분간 완벽하게 할 수는 없다고 생각합니다. 두 가지 기본적인 문제가 있습니다.

  1. SMS를 삭제하려고 할 때 SMS가 이미받은 편지함에 있는지 어떻게 확인할 수 있습니까?
    SMS_RECEIVED는 정렬 된 브로드 캐스트가 아닙니다.
    그래서 dmyung의 해결책은 완전히 운을 시험하는 것입니다. Doug의 답변이 지연 되더라도 보장되지 않습니다.

  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받을 수 있습니다, 당신은 단지 permssion의 android.permission.RECEIVE_SMS이 필요합니다. 순서가 지정된 브로드 캐스트이므로 abortBroadcast ()를 호출하여 메시지가받은 편지함에 도달하는 것을 쉽게 중지 할 수도 있습니다. 추신 : 2 년 후 수정 되려면 재미 있어야합니다. :)
lapis aug

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

대화가 아닌 하나의 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 % 확신합니다 :-// 주소로 전체 변환을 삭제하려면 여기에 변환 주소를 넣으십시오 (메인 페스트에서 읽기, 쓰기 권한을 추가하는 것을 잊지 마십시오) 다음은 코드입니다.

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

이 방법 중 하나를 사용하여 마지막으로받은 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.