순서대로 그림하고 설명 같이 보면됨

 

 

1. 

intent.getExtras(); 라고 하면 그 안에 번들(Bundle)이라는 객체가 있어요.

안에 데이터가 있다.

번들을 통해서 데이터를 뽑아 낼거다.

그런데 어떤게 나오냐면

 

SmsMessage가 여러개 나올 수가 있다. (그래서 배열로 만듬 -> SmsMessage[])

 

   // pdus란? SmsMessage데이터를 처리하는 국제표준 프로토콜이라고 있는데,
   //          SMTP라고 있는데, 그 안에 데이터가 이런 이름으로 들어 가 있다.
   //          그걸 안드로이드 내부의 모듈이 처리를 해서 나한테 던져주는 거다.
   //          pdus 안에 SmsMessage데이터 관련된 내용이 들어가 있다고 생각하면 된다.

 

그걸을 Object[] 배열로 받아 볼거다.

그러면 객체(Object)가 여러개가 들어 갈 것이다

 

 

 

2. 

 

Build.VERSION.SDK_INT        <- 단말에 설치된 OS 버전 상태를 말하는 거다.

Build.VERSION.SDK_CODES.M     <- 마시멜로 가리키는거임. (버전:마시멜로)

 

bundle.getString("format");

format이라는 정보가 같이 인텐트에 들어가 있어요.

그래서 format이라는 정보를 가져와서,

SmsMessage.createFromPdu((byte[]) objs[i],format);       <- 여기다가 넣어준다.

 

return messages; 라고 한다면

parseSmsMessage()메소드에 들어온 Bundle객체 안에 즉, 인텐트 안에 부가데이터로 들어가 있던 데이터(pdus)를 이용해서,

SmsMessage객체로 변환해서 던져 준다는 거다.

 

 

 

 

 

 

 

3. 데이터 뽑아내는 방법

그러면 SmsMessage[] messages =parseSmsMessage(bundle); 안에

뭐가 들어가 있냐 하면?

sms데이터가 들어가 있다.

그래서, 이제 아주 쉽게

그 데이터를 뽑아 낼 수 있게 된다.

 

뽑아 내는 방법

String sender = messages[0].getOriginatingAddress();                // (상대방 번호 = 발신 번호)

String contents = messages[0].getMessageBody().toString();        // 메시지내용

Date receivedDate = new Date(messages[0].getTimestampMillis());    // 발신한 시각

(밑에 그림)

 

이렇게 하고 실행 시킨 다음에  (결과 - 밑에 그림)

 

액티비티는 뭐 한게 없으니깐 앱을 끄고,

자기자신한테 문자를 날리고  (문자 온 것을 확인해볼려고......)

안드로이드 스튜디오의 Logcat을 보면 

코드에 작성한(sender, contents, 날짜) 것들이 출력 된 것을 확인 할 수 있다.

Logcat <- 받은거 찍히는거임

 

 

이젠 위에 처럼

sms를 받았을 때, 이런 sms가 왔습니다라는 화면을 띄워주고 싶겠죠?!

그런데 "브로드캐스트 수신자"는 화면이 없다고 했잖아요!!

그래서 새로 화면(Activity)을 만들어서

화면(Activity)을 띄워주는 것이 가능하다.

어떻게? 띄워 줄 수 있냐면,

"브로드캐스트 리시버(=수신자)"도 "애플리케이션 구성요소"니깐

시스템에서 관리를 하죠!!!!!!

그래서, 인텐트객체를 만들어서 startActivity()로 띄워 줄 화면의 액티비티한테 던져 주어서

그 액티비티는 받아서 화면에 뿌려주게 되는 것이다.!

 

 

 

- 여기까지 코드 구조 -

 

 

 

- 참고 -

그래서 이런 과정을 만들어서,

화면에다가 sms내용을 뿌려줄 수가 있다. (밑에 방법)

 

 

 

 

 

 

 

 

 

4. 화면에다가 뿌려주는 방법

xml,java 파일 만듬(SmsActivity.java, activity_sms.xml)

- activity_sms.xml 화면

- SmsActivity.java 처리

 

이 화면(SmsActivity.java)으로 브로드캐스트리시버(SmsReceiver.java)에서 데이터를 보내줘야 하잖아요!!

데이터를 보낼려면 인텐트에 넣어서 보내주어야 한다. ("보내는 방법"보면 됨)

그러면 이젠 context.startActivity(intent); 하면

SmsReceiver.java(브로드캐스트 수신자)에서 SmsActivity.java(액티비티)쪽으로 화면을 띄워 주는 거죠!

 

 

 

 

이제 SmsActivity.java(액티비티)쪽에서 인텐트 안에 들어가 있는 부가데이터를 받아서 처리 해주면됩니다. (밑에 코드)

싱글 탑(FLAG_ACTIVITY_SINGLE_TOP)이라고 해서,

SmsActivity.java가 화면에 이미 떠 있는 경우라든가, 이미 만들어져 있는 경우에는

onNewIntent()를 재정(오버라이드)이해서 사용하면,

intent가 이쪽으로 전달이 되었을 때, onNewIntent() 쪽으로 전달이 된다.

 

 

 

이렇게 sms 내용을 쉽게 처리 할 수 있다.

 

 

 

 

- 여기까지 코드 구조 -

 

- 결과 -

(자기핸드폰 or 다른 핸드폰)기본 문자로 "야야" 보내면 

(받는 폰에서)바로 이렇게 화면 뜸

 

 

 

5. 

- 참고 -

근데 이거

기본 문자로 나한테 누가 보내면 그냥 전부 이렇게 떠버리네........

음.........

 

설정해줘야함.

 

 

 

 

 

 

 

 

 

 

 

 

 

6. 전체 코드

1) activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

 

2) MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

 

3) SmsReceiver.java

package com.example.mysmsreceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;

import java.text.SimpleDateFormat;
import java.util.Date;

public class SmsReceiver extends BroadcastReceiver {

    private static SimpleDateFormat fm = new SimpleDateFormat("yyyy-MM-dd HH:mm"); // 포맷

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("SmsReceiver","onReceive() 호출됨");

        Bundle bundle = intent.getExtras();
        SmsMessage[] messages =parseSmsMessage(bundle);

        if(messages.length > 0){
            String sender = messages[0].getOriginatingAddress(); // 상대방 번호 = 발신 번호
            Log.d("SmsReceiver","sender : " +sender);

            String contents = messages[0].getMessageBody().toString(); // 메시지내용
            Log.d("SmsReceiver","contents : " +contents);

            Date receivedDate = new Date(messages[0].getTimestampMillis()); // 발신한 시각
            Log.d("SmsReceiver","receivedDate : " +receivedDate);

            // 보내는 방법
            sendToActivity(context,sender,contents,receivedDate);
        }
    }

    private void sendToActivity(Context context, String sender, String contents, Date receivedDate){
        Intent intent = new Intent(context, SmsActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                        |Intent.FLAG_ACTIVITY_SINGLE_TOP
                        |Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.putExtra("sender",sender);
        intent.putExtra("contents",contents);
        intent.putExtra("receivedDate",fm.format(receivedDate));


        context.startActivity(intent);
    }

    private SmsMessage[] parseSmsMessage(Bundle bundle){
        Object[] objs = (Object[])bundle.get("pdus");
        SmsMessage[] messages = new SmsMessage[objs.length];

        for(int i = 0; i<objs.length; i++){ //sms로 복원을 해볼거다.
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
                String format = bundle.getString("format");
                messages[i] = SmsMessage.createFromPdu((byte[]) objs[i],format);
            }else { // 단말이 이전 버전 이면
                messages[i] = SmsMessage.createFromPdu((byte[]) objs[i]);
            }
        }
        return messages;

    }
}

 

 

4) AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.mysmsreceiver">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <receiver
            android:name=".SmsReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity android:name=".SmsActivity"></activity>


    </application>

</manifest>

 

5) activity_sms.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="발신번호"/>

    <EditText
        android:id="@+id/editText3"
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:hint="내용"/>

    <EditText
        android:id="@+id/editText2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="수신시각"/>

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="확인"/>

</LinearLayout>

 

6) SmsActivity.java

package com.example.mysmsreceiver;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class SmsActivity extends AppCompatActivity {
    EditText editText,editText2,editText3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sms);

        editText = (EditText)findViewById(R.id.editText);
        editText2 =  (EditText)findViewById(R.id.editText2);
        editText3 =  (EditText)findViewById(R.id.editText3);

        Button button =  (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });

        Intent passedIntent = getIntent(); // 전달 받은 인텐트 확인
        processCommand(passedIntent);
    }

    private void processCommand(Intent intent){
        // 브로드캐스트 수신자에서 sms를 받으로 화면으로 보여주는 기능
        if(intent != null){ //intent라고 하는게 null 아니면
            String sender = intent.getStringExtra("sender");
            String contents = intent.getStringExtra("contents");
            String receivedDate = intent.getStringExtra("receivedDate");

            editText.setText(sender);
            editText3.setText(contents);
            editText2.setText(receivedDate);
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        processCommand(intent);
        super.onNewIntent(intent);
    }
}