[Android] Android SMS Receiver Example
Updated:
수신한 메시지를 ArrayList에 저장해서 표시하고, Options 메뉴로 메시지를 전송하는 앱을 만들어보자!
필요한 파일 목록
- VO(DTO): Sms- SMS 송/수신:
- SMSReceiveResult
- SMSSendResult
- SMSReceiver
- SMSActivity
- List UI: MsgAdapter, item_layout.xml
- Main Activity: SMSListActivity
1. Sms
public class Sms implements Serializable {
private String phone;
private String message;
//...
}
2. SMSReceiveResult
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
int result = getResultCode();
switch (result) {
case Activity.RESULT_OK:
Toast.makeText(context, "receive : success", Toast.LENGTH_SHORT).show();
break;
case Activity.RESULT_CANCELED:
Toast.makeText(context, "receive : fail", Toast.LENGTH_SHORT).show();
break;
}
}
3. SMSSendResult
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
int result = getResultCode();
switch (result) {
case Activity.RESULT_OK:
Toast.makeText(context, "success", Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
Toast.makeText(context, "generic failure", Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
Toast.makeText(context, "radio off", Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
Toast.makeText(context, "null pdu", Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
Toast.makeText(context, "no service", Toast.LENGTH_SHORT).show();
break;
}
}
4. SMSReceiver
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
Bundle bundle = intent.getExtras();
String msg;
String sender;
int i;
if (bundle != null) {
Object[] rawData = (Object[]) bundle.get("pdus");
SmsMessage[] sms = new SmsMessage[rawData.length];
for (i = 0; i < rawData.length; i++) {
sms[i] = SmsMessage.createFromPdu((byte[]) rawData[i]);
}
for (i = 0; i < sms.length; i++) {
msg = sms[i].getMessageBody();
sender = sms[i].getOriginatingAddress();
Toast.makeText(context, msg + " from " + sender, Toast.LENGTH_SHORT).show();
}
}
}
5. SMSActivity
멤버변수
private EditText editPhone;
private EditText editMessage;
private final static String SEND_ACTION = "SENT";
private final static String DELIVER_ACTION = "DELIVERED";
실행메서드
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sms);
editPhone = findViewById(R.id.editPhone);
editMessage = findViewById(R.id.editMessage);
Intent intent = getIntent();
String tel = intent.getStringExtra("tel");
if (tel != null && !(tel.equals(""))) {
editPhone.setText(tel);
}
SMSSendResult send = new SMSSendResult();
IntentFilter f1 = new IntentFilter();
f1.addAction(SEND_ACTION);
SMSReceiveResult recv = new SMSReceiveResult();
IntentFilter f2 = new IntentFilter();
f2.addAction(DELIVER_ACTION);
registerReceiver(send, f1);
registerReceiver(recv, f2);
}
버튼 onClick 메서드
public void onSend(View view) {
String msg = editMessage.getText().toString();
String phone = editPhone.getText().toString();
if (msg.length() <= 0 || phone.length() <= 0) {
Toast.makeText(getApplicationContext(), "input the message and phone number!", Toast.LENGTH_SHORT).show();
return;
}
// sms 보내는 쪽 상태 학인을 위한 객체
PendingIntent sendStat = PendingIntent.getBroadcast(this, 0, new Intent("SENT"), 0);
// sms 받는 쪽(상대방) 상태 확인을 위한 객체
PendingIntent deliveredStat = PendingIntent.getBroadcast(this, 0, new Intent("DELIVERED"), 0);
SmsManager sms = SmsManager.getDefault();
// sms 전송
sms.sendTextMessage(phone, null, msg, sendStat, deliveredStat);
setResult(RESULT_OK);
finish();
}
6. MsgAdapter
기본설정
private Context context;
private ArrayList<Sms> list;
private int resId;
public MsgAdapter(@NonNull Context context, int resource, @NonNull List<Sms> objects) {
super(context, resource, objects);
this.context = context;
this.list = (ArrayList<Sms>) objects;
resId = resource;
}
getView 메서드
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View itemView = convertView;
if (itemView == null) {
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
itemView = vi.inflate(resId, null);
}
final Sms m = list.get(position);
if (m != null) {
TextView textPhone = itemView.findViewById(R.id.textPhone);
TextView textMsg = itemView.findViewById(R.id.textMsg);
if (textPhone != null) {
textPhone.setText(m.getPhone());
}
if (textMsg != null) {
textMsg.setText(m.getMessage());
}
}
return itemView;
}
7. SMSListActivity
(1) SMS 권한 설정
- onCreate 메서드에 아래 코드 추가
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// For device above MarshMallow
boolean permission = getSMSPermission();
if (permission) {
Toast.makeText(this, "sms 권한 획득", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(this, "권한 획득 필수 아닌 버전", Toast.LENGTH_SHORT).show();
}
- 아래의 두 메서드 추가
public boolean getSMSPermission() {
boolean hasPermission = ((ContextCompat.checkSelfPermission(this,
Manifest.permission.SEND_SMS) == PackageManager.PERMISSION_GRANTED) &&
(ContextCompat.checkSelfPermission(this,
Manifest.permission.RECEIVE_SMS) == PackageManager.PERMISSION_GRANTED));
if (!hasPermission) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.SEND_SMS,
Manifest.permission.RECEIVE_SMS}, 1);
}
return hasPermission;
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 1: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "sms 권한 부여", Toast.LENGTH_SHORT).show();
}
}
}
}
(2) 나머지 코드
- Receiver 등록
private ListView listView;
private ArrayList<Sms> list;
private MsgAdapter adapter;
private String msg;
private String sender;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sms_list);
listView = findViewById(R.id.listView);
list = new ArrayList<>();
adapter = new MsgAdapter(this, R.layout.item_layout, list);
listView.setAdapter(adapter);
registerForContextMenu(listView);
BroadcastReceiver smsRecv = new BroadcastReceiver() {
@Override
public void onReceive(Context context, final Intent intent) {
// an Intent broadcast.
final Bundle bundle = intent.getExtras();
int i;
if (bundle != null) {
Object[] rawData = (Object[]) bundle.get("pdus");
SmsMessage[] sms = new SmsMessage[rawData.length];
for (i = 0; i < rawData.length; i++) {
sms[i] = SmsMessage.createFromPdu((byte[]) rawData[i]);
}
for (i = 0; i < sms.length; i++) {
msg = sms[i].getMessageBody();
sender = sms[i].getOriginatingAddress();
AlertDialog.Builder builder = new AlertDialog.Builder(SMSListActivity.this);
builder.setMessage(msg + "\nfrom: " + sender)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
/*다이얼로그 창 닫고 메시지 ArrayList에 저장하도록 구현 */
list.add(new Sms(sender, msg));
dialogInterface.cancel(); // 다이얼로그 창 닫음
adapter.notifyDataSetChanged();
}
})
.setTitle("You've got Message!");
AlertDialog alertDialog = builder.create(); // 다이얼로그 생성
alertDialog.show(); // 다이얼로그 표시
}
}
}
};
IntentFilter f = new IntentFilter();
f.addAction("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(smsRecv, f); // Receiver에 intent filter 등록
}
- Options 메뉴
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(0, Menu.FIRST, 0, "send");
return true;
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case 1:
Intent intent = new Intent(this, SMSActivity.class);
startActivityForResult(intent, 1);
break;
}
return true;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case 1:
Toast.makeText(this, "message sent", Toast.LENGTH_SHORT).show();
break;
}
}
}
- Context 메뉴
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.add(0, Menu.FIRST, 0, "delete");
}
@Override
public boolean onContextItemSelected(@NonNull MenuItem item) {
super.onContextItemSelected(item);
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
int idx = info.position;
switch (item.getItemId()) {
case 1:
list.remove(idx);
adapter.notifyDataSetChanged();
break;
}
return true;
}
8. Manifest 설정(제일 중요!)
SMS 권한 설정
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
SMSListActivity를 main intent로 설정
<activity android:name=".SMSListActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
SMSActivity를 묵시적으로 활성화: 지난번 전화번호부 app이랑 연동하기 위해
<activity android:name=".SMSActivity">
<!-- 묵시적으로 활성화 -->
<intent-filter>
<action android:name="com.example.receivertest.sms_send" />
</intent-filter>
</activity>
SMSReceiver를 묵시적으로 활성화
<receiver
android:name=".SMSReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
9. 지난번 MyPhoneBook의 PhoneAdaptor에 아래의 코드 추가
sms.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ComponentName cn = new ComponentName("com.example.receivertest", "com.example.receivertest.SMSActivity");
Intent intent = new Intent("com.example.receivertest.sms_send");
intent.putExtra("tel", m.getTel());
intent.setComponent(cn);
context.startActivity(intent);
}
});
Leave a comment