java.lang.IllegalArgumentException: view must not be null




환경 : dialog를 띄워야하는 상황


오류원인 : view가 null 값으로 들어감


해결방안 : view를 명시해준다.


기존코드

  LayoutInflater layoutInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);

  layoutInflater.inflate(R.layout.calling_window_pop, null);

  ButterKnife.bind(this, view);



수정코드


  View view;


  ...


  LayoutInflater layoutInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);

  view = layoutInflater.inflate(R.layout.calling_window_pop, null);

  ButterKnife.bind(this, view);




java.util.concurrent.TimeoutException: Timed out waiting for Task




환경 : 전화가 온 상태에서 다이얼로그를 띄워야함


오류 원인 : 다이얼로그를 띄우는 과정에서 에러가 발생하여 다이얼로그를 결국 띄우지 못하고 앱이 죽음. 전화가 온 상태에서 다이얼로그를 띄우려고 한 것 이기 때문에 다이얼로그를 계속 호출함. 그런데 오류로 인해 띄우지 못하고 있으니, TimeoutException 예외가 발생함.



Microsoft .Net : TimeoutException 클래스

https://docs.microsoft.com/ko-kr/dotnet/api/system.timeoutexception?view=netcore-3.1

java.lang.NullPointerException: println needs a message



환경 : Log를 찍어보고 있는 상황.


오류원인 : Log에 찍겠다고 선언한 메세지가 null 값임.


해결방안 : 만약, 메세지가 null로 나와야하는 경우라면 null일때도 출력 가능하게끔 코드를 짠다거나, Log를 다른 방법으로 찍을 수 있도록 해야함. 하지만, 그런 경우가 아니라 null 값이 들어가는게 아니라 특정한 값이 나와야하는 경우라면, null 값이 찍힌 메세지구문을 디버깅해보고 구글링 해보면서 null 값이 나오는 이유를 알아야함.





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 코드





 

※ 위 글을 uipath forum 에서 스크랩 해온 게시물 입니다. 저작권은 제작자에게 있습니다. ※ 

 

HttpAgilityPack을 이용한 웹 크롤링 샘플입니다.
UiPath의 기본 액티비티로 작업하는 것보다는 복잡하지만 기본만 알면 비교적 간단하게 효과적으로 데이터를 가져 올 수 있습니다. 참고하세요.
대상 사이트 : 하나은행 환율/외화예금 금리
사용 액티비티 : 웹 패키지 HttpRequest, HtmlAgilityPack
HtmlAgilityPack 사용법

  1. 패키지 설치후 NameSpace에 HtmlAgilityPack 추가
  2. HtmlDocument 변수 생성
  3. HttpRequest를 이용하여 Html 소스 읽어오기
  4. Method Invoke를 이용하여 읽어온 Html 소스를 Document에 Load(LoadHtml 메소드)
  5. HtmlDocument의 DocumentNode의 SelectNodes 함수 이용 원하는 노드 읽어오기(XPath 이용)
  6. 읽어온 Nodes에서 원하는 Node를 추출하여 DataTable에 저장

아래 링크의 파일을 다운받아 테스트 해보세요.

 

https://forum.uipath.com/t/agilitypack/219567/2

 

AgilityPack을 이용한 웹 크롤링

와 이렇게 좋은 정보를~ 감사합니다^^

forum.uipath.com

 

'프로그래밍 > RPA' 카테고리의 다른 글

Project Organization : State Machine  (0) 2020.05.20
Mail Activity : POP3(Get POP3 Mail Messages)  (0) 2020.05.19
IS 와 Equals의 차이점  (2) 2020.04.16
Orchestrator / Queue / SLA  (0) 2020.04.08
Error and Exception handling  (0) 2020.04.08

 

Log.d(TAG, "정다실버")   <-  보통 이런 방식으로 많이 사용함 !

 

Log.e(String, String)   (ERROR)

Log.w(String, String)   (WARNING)

Log.i(String, String)   (INFO)

Log.d(String, String)   (DEBUG)

Log.v(String, String)   (VERBOSE)

Log.wtf(String, String) (ASSERT)

 

 

jxl.read.biff.BiffException: Unable to recognize OLE stream

 

환경 : jxl 을 사용하여 엑셀 파일을 읽어와 리스트에 값을 출력함.

오류 원인 : Cuase 부분을 더 살펴본 결과 NullPointException이 있었음. 즉 파일이 잘 들어가지 않았다는 것. 파일 확장자를 보니 '.xlsx'로 되어 있었어서 인식이 안되었던 것. '.xls' 확장자만 허용. 바로 '.xls'로 바꿨는데도 실행이 안됐음. 그래서 엑셀 프로그램을 켜서 확장자를 '.xls'로 바꿔서 다른 이름으로 저장을 하면 데이터의 유실 없이 저장할 수 있기 때문에 그 다음부터 실행이 되었음. 즉 엑셀 파일에 문제가 있었던 것.

.xls-> 97~2003 엑셀 버전의 파일 확장자
.xlsx-> 최신 엑셀 버전의 파일 확장자

 

 

이놈의 다이얼로그 생각 보다 정말 많이 쓰이는데..

그냥 기본 설정으로 쓰는 곳이 단 하나도 없다는게...

그래서 어플을 만들때 다이얼로그는 커스텀해서 사용하는 경우가 아마 대부분일거다.

 

그래서 커스텀 다이얼로그를 공부하다가 가장 간단한 방법으로 사용할 수 있는 방법을 포스팅해보려고한다.

다음과 같은 순서로 진행한다.

 

* 커스텀 다이얼로그 만들기

1. 다이얼로그 디자인 -> xml

2. 메인 xml에서 다이얼로그가 나올 수 있는 버튼 만들기

3. 메인 java에서 버튼 클릭 이벤트로 다이얼로그 띄우기

 

간단히 설명하자면 개념은 이러하다.

일반적으로 다이얼로그는 기본 셋팅에 있는대로 속성을 줘서 바로 클릭 이벤트와 같은 곳에 띄우도록 한다.

그런데 커스텀 다이얼로그는 일단 커스텀이기 때문에 보여질 화면을 작업해야하고, 화면을 가지고서 다이얼로그를 띄울 수 있도록 클릭 이벤트에 설정해줘서 띄우도록 해야한다.

그럼 만들어보쟈

 

 

1. 다이얼로그 화면 디자인

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

    <LinearLayout
        android:gravity="center"
        android:orientation="vertical"
        android:layout_marginVertical="50sp"
        android:layout_marginHorizontal="55sp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:text="삭제하시겠습니까?"
            android:textSize="23sp"
            android:gravity="center"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>

        <LinearLayout
            android:orientation="horizontal"
            android:layout_marginTop="40sp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <Button
                android:id="@+id/deleteBtn"
                android:text="삭제"
                android:textSize="18sp"
                android:textColor="@color/colorRed"
                android:background="@color/colorNothing"
                android:layout_weight="1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
            <Button
                android:id="@+id/cancelBtn"
                android:text="취소"
                android:textSize="18sp"
                android:textColor="@color/colorAccent"
                android:background="@color/colorNothing"
                android:layout_weight="1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
        </LinearLayout>
    </LinearLayout>

</LinearLayout>

 

2. 메인 화면 디자인

<RelativeLayout
        android:layout_alignParentTop="true"
        android:background="@color/colorGray"
        android:layout_width="match_parent"
        android:layout_height="85sp">
        <ImageView
            android:id="@+id/deleteDataBtn"
            android:src="@drawable/ic_cancel"
            android:layout_alignParentRight="true"
            android:layout_marginRight="20sp"
            android:layout_width="25sp"
            android:layout_height="wrap_content"/>
    </RelativeLayout>

 

3. 메인 자바 코딩

public class CustomDialogEx extends AppCompatActivity {

    ImageView deleteDataBtn;

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

        // 사용할 액티비티 선언
        deleteDataBtn= findViewById(R.id.deleteDataBtn);

        // 삭제하기 버튼 -> 커스텀 다이얼로그 생성
        deleteDataBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                DleteAlertDialog();
            }
        });


    }

    private void DleteAlertDialog() {
        LayoutInflater dialog = LayoutInflater.from(this);
        final View deleteDialogLayout = dialog.inflate(R.layout.dialog_delete, null);
        final Dialog deleteDialog = new Dialog(this);

        deleteDialog.setContentView(deleteDialogLayout);
        deleteDialog.show();

        Button deleteBtn = (Button) deleteDialogLayout.findViewById(R.id.deleteBtn);
        Button cancelBtn = (Button) deleteDialogLayout.findViewById(R.id.cancelBtn);

        deleteBtn.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                // 삭제 버튼 누르면 할거
                Toast.makeText(getApplicationContext(), "버튼을 누를시 데이터를 삭제합니다.", Toast.LENGTH_LONG).show();
            }
        });

        cancelBtn.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
            	// 취소 버튼 누르면 할거
                //deleteDialog.cancel();
                //deleteDialog.dismiss();
                Toast.makeText(getApplicationContext(), "취소합니다.", Toast.LENGTH_LONG).show();
            }
        });
    }

}

 

 

위와 같이 하면 된다.

지금 내가 작업중인 파일이라서 클래스명을 좀 바꾸고 필요없는건 빼서

그대로 복붙해서 실행될지는 모르겠지만, 이와 같은 방법으로 진행하면 된다.

 

+ Recent posts