java.lang.NullPointerException: Attempt to invoke interface method 'int java.lang.CharSequence.length()' on a null object



환경 : Broadcast receiver call, 전화가 왔을때 그 전화번호를 받아와 로그에 출력하는 과정

오류원인 : incomingNumber 변수에 null 값이 들어가서 "Log.d();"  구문에 오류가 발생.

해결방안 : null 값이 들어가는 이유를 알아보고, 해결해야함.


1. 에러 코드

String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);  // 여기서 값을 제대로 받아오지 못함.

String phone_number = PhoneNumberUtils.formatNumber(incomingNumber); // 그래서 phone_number 가 null 값이 되고,

Log.d("phone call : ", incomingNumber); // 결국 Log가 null값을 찍어야하기 때문에 오류가 발생하는것!!



2. 해결방안


null 값이 들어가는 이유는, manifest에 permission.READ_PHONE_STATE 권한이 있기 때문!!!

permission.READ_PHONE_STATE 라는 권한에 대해서 기존의 포스트에서도 두 번 수신된다는 언급이 있었는데,

나는 그걸 간과하고 두 번 수신되는 것에 대한 코드를 처리하지 않았음.

처음에 수신되면 incomingNumber에 값이 들어가는데, 두번째 수신이 될 때는 비워져서 들어가므로

최종적으로는 null 값이 반환되었던 것...!


따라서, 두 번 수신되는 것에 대한 코드 처리를 추가해줘야함.

(두 번 수신되는 이유에 대해서는 알 수 없음...)


또한, permission.READ_PHONE_STATE에 대한 권한 뿐만 아니라, permission.READ_CALL_LOG 권한에 대해서도 마찬가지임.

이 두개의 권한을 사용한다면, 꼭 수신에 관란 코드를 처리해야함.



3. 코드 수정

 public void onReceive(Context context, Intent intent) {

String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);


if (state.equals(mLastState)) { return; } else { mLastState = state; } // <- 요부분!!!

if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {

String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
String phone_number = PhoneNumberUtils.formatNumber(incomingNumber);
Log.d("phone call : ", incomingNumber);


}







수정합니다.



기존 코드 : 

public class IncomingCallBroadcastReceiver extends BroadcastReceiver {


    private static String mLastState;


    public void onReceive(Context context, Intent intent) {


        String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);


        Log.d("state : ", state); // RINGING 반환


        if (state.equals(mLastState)) {

            return;

        } else {

            mLastState = state;

        }



        if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) {


            String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);

            String phone_number = PhoneNumberUtils.formatNumber(incomingNumber);


            Log.d("phone call : ", incomingNumber);


        }

    }




수정 코드 :


1) Manifest.xml


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

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

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



2) MainActivity.java


 public class MainActivity extends AppCompatActivity {


    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);


        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED

                || ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.SYSTEM_ALERT_WINDOW) != PackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(MainActivity.this,

                    new String[]{Manifest.permission.READ_CALL_LOG, Manifest.permission.SYSTEM_ALERT_WINDOW},

                    1);

        }


    }

}



3) IncomingCallBroadcastReceiver.java


 public class IncomingCallBroadcastReceiver extends BroadcastReceiver {


    public void onReceive(Context context, Intent intent) {


        if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {

            String savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");

        } else{

            String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);

            String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);

            int state = 0;


            if (stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)) {

                state = TelephonyManager.CALL_STATE_IDLE;

            } else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){

                state = TelephonyManager.CALL_STATE_OFFHOOK;

            } else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)){

                state = TelephonyManager.CALL_STATE_RINGING;

            }


            if (number != null && !number.isEmpty() && !number.equals("null")) {

                //onCallStateChanged(context, state, number);

                Log.d("TEST :","NUMBER =>"+number);

            }

        }

    }


}





결론:

Manifest 추가 & MainAvtivity에서 permission을 허가받아야함 & 새로운 receiver 코드





+ Recent posts