[android] 프로그래밍 방식으로 Android의받은 편지함에서 SMS를 삭제하는 방법은 무엇입니까?

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받은 편지함에서 삭제됩니다.

끝났습니까? 할 수 있습니까?



답변

“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), 삭제 후)


답변

다른 사람의 제안을 사용하여 제대로 된 것 같습니다.

(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 권한 속성을 의도에 넣지 마십시오! 저보다 현명한 사람이 그 이유를 말해 줄 수 있기를 바랍니다.


답변

그래서 나는 연극을했고, 이다 수신 된 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에서 숨겨져 있으며 지표를 정확하게 만들기 위해 모든 코드를 복제하고 싶지 않았습니다.


답변

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는 동일한 사용자가 보내는 메시지에 할당 된 것입니다. 따라서 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)} );


답변

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

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


답변

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

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

  2. SmsProvider는 스레드로부터 안전하지 않습니다. ( http://code.google.com/p/android/issues/detail?id=2916#c0 참조 )
    둘 이상의 클라이언트가 삭제를 요청하고 동시에 데이터 손상 또는 즉각적인 런타임 예외가 발생합니다.