[android] get sender number in SMS, MMS broadcast receiver

 

<uses-permission android:name="android.permission.RECEIVE_MMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />

 

<receiver
    android:name="MMSReceiver"
    android:permission="android.permission.BROADCAST_WAP_PUSH" >
    <intent-filter>
        <action android:name="android.intent.action.DATA_SMS_RECEIVED" />

        <data android:scheme="sms" />
        <data android:host="localhost" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />

        <data android:mimeType="application/vnd.wap.mms-message" />
    </intent-filter>
</receiver>

<receiver
    android:name="SMSReceiver"
    android:permission="android.permission.BROADCAST_SMS" >
    <intent-filter>
        <action android:name="android.provider.Telephony.SMS_RECEIVED" />
    </intent-filter>
</receiver>

 

 

 

public class SMSReceiver extends BroadcastReceiver
{
   @Override
   public void onReceive(Context $context, Intent $intent)
   {
      Bundle bundle = $intent.getExtras();
    
      if (bundle == null)
        return;
      
      Object[] pdus = (Object[]) bundle.get("pdus");
      if (pdus == null)
        return;
      
      ArrayList<String> msgs = new ArrayList<String>();
      String number = "";
      for (int i = 0; i < pdus.length; i++)
      {
        SmsMessage smsMsg = SmsMessage.createFromPdu((byte[]) pdus[i]);
        number = smsMsg.getDisplayOriginatingAddress();
        
        msgs.add(smsMsg.getDisplayMessageBody());
      }
      
      if (!TextUtils.isEmpty(number) && number.contains(";"))
        number = number.split(";")[0];
      
      if (!TextUtils.isEmpty(number))
        number = number.trim().replaceAll("[^0-9]", "");
      
      String msg = TextUtils.join(" ", msgs);
      Log.i("SMSReceiver.java | onReceive", "|" + number + "|" + msg);
   }
}

 

 

MMS는 좀 어려운데, 검색하면 PduParser 등을 이용해야 하는 걸로 많이 나오는데, 딸린 파일이 엄청 많다.

안드로이드 기본 소스에는 들어가있는 것처럼 나오던데, 이상하게 저 클래스를 쓸 수가 없더라.

그렇다고 17MB짜리 jar를 추가해서 쓰기도 좀 그렇고….

public class MMSReceiver extends BroadcastReceiver
{
  private Context _context;

  @Override
  public void onReceive(Context $context, final Intent $intent)
  {
    _context = $context;

    Runnable runn = new Runnable()
    {
      @Override
      public void run()
      {
        parseMMS();
      }
    };
    Handler handler = new Handler();
    handler.postDelayed(runn, 6000); // 시간이 너무 짧으면 못 가져오는게 있더라 
  }

  private void parseMMS()
  {
    ContentResolver contentResolver = _context.getContentResolver();
    final String[] projection = new String[] { "_id" };
    Uri uri = Uri.parse("content://mms");
    Cursor cursor = contentResolver.query(uri, projection, null, null, "_id desc limit 1");

    if (cursor.getCount() == 0)
    {
      cursor.close();
      return;
    }

    cursor.moveToFirst();
    String id = cursor.getString(cursor.getColumnIndex("_id"));
    cursor.close();

    String number = parseNumber(id);
    String msg = parseMessage(id);
    Log.i("MMSReceiver.java | parseMMS", "|" + number + "|" + msg);
  }

  private String parseNumber(String $id)
  {
    String result = null;

    Uri uri = Uri.parse(MessageFormat.format("content://mms/{0}/addr", $id));
    String[] projection = new String[] { "address" };
    String selection = "msg_id = ? and type = 137";// type=137은 발신자
    String[] selectionArgs = new String[] { $id };

    Cursor cursor = _context.getContentResolver().query(uri, projection, selection, selectionArgs, "_id asc limit 1");

    if (cursor.getCount() == 0)
    {
      cursor.close();
      return result;
    }

    cursor.moveToFirst();
    result = cursor.getString(cursor.getColumnIndex("address"));
    cursor.close();

    return result;
  }
  
  private String parseMessage(String $id)
  {
    String result = null;
    
    // 조회에 조건을 넣게되면 가장 마지막 한두개의 mms를 가져오지 않는다.
    Cursor cursor = _context.getContentResolver().query(Uri.parse("content://mms/part"), new String[] { "mid", "_id", "ct", "_data", "text" }, null, null, null);
    
    Log.i("MMSReceiver.java | parseMessage", "|mms 메시지 갯수 : " + cursor.getCount() + "|");
    if (cursor.getCount() == 0)
    {
      cursor.close();
      return result;
    }
    
    cursor.moveToFirst();
    while (!cursor.isAfterLast())
    {
      String mid = cursor.getString(cursor.getColumnIndex("mid"));
      if ($id.equals(mid))
      {
        String partId = cursor.getString(cursor.getColumnIndex("_id"));
        String type = cursor.getString(cursor.getColumnIndex("ct"));
        if ("text/plain".equals(type))
        {
          String data = cursor.getString(cursor.getColumnIndex("_data"));
          
          if (TextUtils.isEmpty(data))
            result = cursor.getString(cursor.getColumnIndex("text"));
          else
            result = parseMessageWithPartId(partId);
        }
      }
      cursor.moveToNext();
    }
    cursor.close();
    
    return result;
  }
  
  
  private String parseMessageWithPartId(String $id)
  {
    Uri partURI = Uri.parse("content://mms/part/" + $id);
    InputStream is = null;
    StringBuilder sb = new StringBuilder();
    try
    {
      is = _context.getContentResolver().openInputStream(partURI);
      if (is != null)
      {
        InputStreamReader isr = new InputStreamReader(is, "UTF-8");
        BufferedReader reader = new BufferedReader(isr);
        String temp = reader.readLine();
        while (!TextUtils.isEmpty(temp))
        {
          sb.append(temp);
          temp = reader.readLine();
        }
      }
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
    finally
    {
      if (is != null)
      {
        try
        {
          is.close();
        }
        catch (IOException e)
        {
        }
      }
    }
    return sb.toString();
  }
}

 

*LG G2에서는 MMS의 발신자 정보 들어있는 곳에 수신자 전화번호가 보여서 가져올 수가 없다.