반응형

네트워크를 통해서 HTTP 통신 후 Request 로 응답처리까지 처음하는 사람의 경우 어려울 수도 있어서 정리함

 

코드는 간단하게 정리해서 공유드리겠음

 

클래스는 2개를 추가해야한다.

RequestHttpConnection.java 와 NetworkTask.java 클래스 2개를 생성한다.

 

SMALL

 

1. RequestHttpConnection.java

   HTTP 연결 및 데이터 전달을 위한 클래스, 방식은 POST

public class RequestHttpConnection {
    public String request(String _url, ContentValues _params){

        // HttpURLConnection 참조 변수.
        HttpURLConnection urlConn = null;
        // URL 뒤에 붙여서 보낼 파라미터.
        StringBuilder sbParams = new StringBuilder();

        /**
         * 1. StringBuffer에 파라미터 연결
         * */
        // 보낼 데이터가 없으면 파라미터를 비운다.
        if (_params == null)
            sbParams.append("");
            // 보낼 데이터가 있으면 파라미터를 채운다.
        else {
            // 파라미터가 2개 이상이면 파라미터 연결에 &가 필요하므로 스위칭할 변수 생성.
            boolean isAnd = false;
            // 파라미터 키와 값.
            String key;
            String value;

            for(Map.Entry<String, Object> parameter : _params.valueSet()){
                key = parameter.getKey();
                value = parameter.getValue().toString();

                // 파라미터가 두개 이상일때, 파라미터 사이에 &를 붙인다.
                if (isAnd)
                    sbParams.append("&");

                sbParams.append(key).append("=").append(value);

                // 파라미터가 2개 이상이면 isAnd를 true로 바꾸고 다음 루프부터 &를 붙인다.
                if (!isAnd)
                    if (_params.size() >= 2)
                        isAnd = true;
            }
        }

        /**
         * 2. HttpURLConnection을 통해 web의 데이터를 가져온다.
         * */
        try{
            URL url = new URL(_url);
            urlConn = (HttpURLConnection) url.openConnection();
            urlConn.setConnectTimeout(HTTP_TIMEOUT_m);
            urlConn.setReadTimeout(HTTP_TIMEOUT_m);

            // [2-1]. urlConn 설정.
            urlConn.setRequestMethod("POST"); // URL 요청에 대한 메소드 설정 : POST.
            urlConn.setRequestProperty("Accept-Charset", "UTF-8"); // Accept-Charset 설정.
            urlConn.setRequestProperty("Context_Type", "application/x-www-form-urlencoded;cahrset=UTF-8");

            // [2-2]. parameter 전달 및 데이터 읽어오기.
            String strParams = sbParams.toString(); //sbParams에 정리한 파라미터들을 스트링으로 저장. 예)id=id1&pw=123;
            OutputStream os = urlConn.getOutputStream();
            os.write(strParams.getBytes(StandardCharsets.UTF_8)); // 출력 스트림에 출력.
            os.flush(); // 출력 스트림을 플러시(비운다)하고 버퍼링 된 모든 출력 바이트를 강제 실행.
            os.close(); // 출력 스트림을 닫고 모든 시스템 자원을 해제.

            // [2-3]. 연결 요청 확인.
            // 실패 시 null을 리턴하고 메서드를 종료.
            if (urlConn.getResponseCode() != HttpURLConnection.HTTP_OK) {
                Log.e("RequestHttpConnection : Err[2-3] " + urlConn.getResponseCode());
                return null;
            }

            // [2-4]. 읽어온 결과물 리턴.
            // 요청한 URL의 출력물을 BufferedReader로 받는다.
            BufferedReader reader = new BufferedReader(new InputStreamReader(urlConn.getInputStream(), StandardCharsets.UTF_8));

            // 출력물의 라인과 그 합에 대한 변수.
            String line;
            StringBuilder page = new StringBuilder();

            // 라인을 받아와 합친다.
            while ((line = reader.readLine()) != null){
                page.append(line);
            }

            return page.toString();

        } catch (IOException e) { // for URL.
            e.printStackTrace();
        }// for openConnection().
        finally {
            if (urlConn != null)
                urlConn.disconnect();
        }

        Log.e("RequestHttpConnection :  Err[END]");

        return null;

    }
}
반응형

2. NetworkTask.java

   AsyncTask 로 네트워크 Request 를 호출하여 처리할 수 있도록 함

public class NetworkTask extends AsyncTask<Void, Void, String> {

    private final String url;
    private final ContentValues values;
    private final Handler receiveHandler;  // 리턴 메세지를 반환할 Handler

    public NetworkTask(String url, ContentValues values, Handler receiveHandler) {
        this.url = url;
        this.values = values;
        this.receiveHandler = receiveHandler;
    }

    @Override
    protected String doInBackground(Void... params) {

        Log.d("URL : " + url );

        String result; // 요청 결과를 저장할 변수.
        RequestHttpConnection requestHttpURLConnection = new RequestHttpConnection();
        result = requestHttpURLConnection.request(url, values); // 해당 URL로 부터 결과물을 얻어온다.

        return result;
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);

        //doInBackground()로 부터 리턴된 값이 onPostExecute()의 매개변수로 넘어오므로 s를 메세지에 담아 리턴한다.
        try {
            Log.d("onPostExecute : " + s );
            Message msg = receiveHandler.obtainMessage(SEND_WEB_RETURN);
            Bundle data = new Bundle();
            data.putString("WEB_RETURN", s);
            msg.setData(data);
            receiveHandler.sendMessage(msg);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

 

위 클래스를 작성하였다면 이젠 사용하는 방법만 익히면 가능함

 

3. 호출하여 사용

    메인에서 호출을 진행한다고 하는 경우

    아래처럼
    1) POST 데이터를 ContentValues 클래스로 삽입 

    2) 리턴 값을 처리 할 Handler 를 생성

    3) 변수들을 삽입 후 실행~!!

    4) 리턴으로 돌아온 값을 처리하면 끝~!!

//POST 데이터를 삽입
ContentValues value = new ContentValues();
value.put("DATA1", data1);
value.put("DATA2", data2);

// 데이터 리턴값을 처리할 Handler
Handler receive_handler = new Handler(msg -> {
    if(msg.what == SEND_WEB_RETURN){
        String data = msg.getData().getString("WEB_RETURN");
        if(!data.equals("null")){
            try {
                Log.d("RecvData", data);
                JSONObject object = new JSONObject(data);  //JSON 파싱
                ... //그 이후 응답 데이터 처리 진행
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }
    return true;
});

NetworkTask HTTP_REQ = new NetworkTask("URL 주소", value, receive_handler);
HTTP_REQ.execute();

 

복잡해 보이지만 RequestHttpConnection.java 와 NetworkTask.java 는 한번 만들어 두면 변경할 필요없이 계속 사용 가능하다.

 

그럼 오늘도 모두들 화이팅 하세요 ㅎㅎ 

반응형
반응형

안드로이드 개발을 하다보면 단말기의 Bluetooth Log 를 확인해야하는 경우가 발생

 

해당 내용을 간략하게 공유함

 

아래 스샷처럼 [개발자 옵션] -> [블루투스 HCI 스누프 로그 사용] 을 사용으로 변경해주면 된다.

참고. 개발자 모드 스크린샷

로그 사용을 켰다면 블루투스를 한번 껐다 켜주는게 좋다

 

그리고 시험하려는 단말기와 블루투스 통신을 진행한 뒤 .....

 

이제 로그를 추출해야함

SMALL

 

1. Android Studio 를 실행!!

   [Android Studio 다운로드]

 

Download Android Studio and SDK tools  |  Android Developers

<!-- hide description -->

developer.android.com

2. 폰을 USB 연결!!

3. CMD 창에서 ADB.exe 가 있는 곳으로 이동

cd C:\Users\USER\AppData\Local\Android\Sdk\platform-tools
C:\Users\USER\AppData\Local\Android\Sdk\platform-tools>adb bugreport test.zip
/data/user_de/0/com.android.shell/files/bugreports/bugreport-2021-11-18-14-27-54.zip: 1 file pulled, 0 skipped. 24.9 MB/s (9181748 bytes in 0.351s)
Bug report copied to test.zip

4. 3번에서 adb bugreport test.zip 을 입력하면 전체 버그 리포트가 추출된다

5. Android Studio 에서 File Explorer 를 클릭한다 보통 화면 우측 하단에 존재함

참고. 화면 우측 하단 File Explorer 위치

반응형

6. 버그리포트는 bugreports 라는 폴더에 존재함

참고. bugreport 파일 위치

7. 해당 파일 우클릭 -> Save As 로 내 PC로 저장하면 됨. 그리고 압축 해제!! 

8. FS/data/log/bt 에 btsnoop_hci.log 파일이 존재 확인

9. Wireshark 라는 프로그램으로 해당 파일을 열면 완료!!

  [Wireshark 다운로드]

 

Wireshark · Download

Download Wireshark The current stable release of Wireshark is 3.4.10. It supersedes all previous releases. You can also download the latest development release (3.6.0rc3) and documentation.

www.wireshark.org

참고. Wireshark 로 btsnoop_hci.log 검색

10. 로그 분석 시작 ㅎㅎ 수고하세요 ㅎㅎ 

반응형
반응형
  • 목차
    1. 메세지(Message) 란?
    2. 메세지(Message) 특징
    3. 메세지(Message) 송신 및 수신



  1. 메세지(Message) 란?
    메세지(Message)란 안드로이드에서 많이 쓰이는 데이터 전달 Class 임.
    자세한 내용은 구글(https://developer.android.com/reference/android/os/Message) 에서 확인가능
    지금 이 글을 보는 사람은 초보라 생각하고 설명함

    메세지는 쓰레드(Thread) 와 핸들러(Handler) 를 이용해서 사용한다는 내용은 많이 있는데 정작 어떤경우 사용해야 좋은지 초보자인 경우 잘 모르는 상황이 많음. 그런걸 간단하게 공유해보고자 함



  2. 메세지(Message) 특징
    메세지도 Thread 특징을 그대로 이어받아 사용하기 때문에 코드가 동작 중 로딩으로 인해 버벅거리는 경우는 없음
    UI 변경도 간섭을 할 수 있음 ( Thread 내부에서 UI 변경을 하려고 하면 [ Only the original thread that created a view hierarchy can touch its views ] 라는 내용의 에러 발생 확인 가능함 ) 
    물론 Activity.runOnUiThread( new Runnable() { ... } ) 함수를 이용할 수도 있지만 이런 방식도 가능하다는 것을 알았으면 함


    반응형
  3. 메세지(Message) 송신 및 수신
    기본적인 구조는 다음과 같음

    . 데이터가 공백이거나 Null 인 경우(code_0 는 int 형으로 알맞은 숫자를 선언해주면 가능)

    송신부 A 
    mhandler.sendEmptyMessage(code_0);

    수신부 A
    Handler mhandler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            switch(msg.whar){
                case code_0 :
                    break;
            }
        }
    }



    . 데이터( 정수 0) 존재하며 키값( 문자열 : DATA0 ) 지정하여 보내는 경우
      데이터는 정수, 실수, Byte, Char, String 배열 등등 다양한 변수를 담을 수 있음
      또한 데이터 개수가 증가할 때는 bundle 에 형식과 키값, 데이터를 실어주면 전달이 가능함

    송신부 B
    Message message = mhandler.obtainMessage(code_0);
    Bundle bundle = new Bundle();
    bundle.putInt("DATA0", 0);
    message.setData(data_value);
    mhandler.sendMessage(message);

    수신부 B
    Handler mhandler = new Handler(){
        @Override 
        public void handleMessage(@NonNull Message msg) { 
            super.handleMessage(msg);
            switch(msg.whar){
                case code_0 :
                Log.d("Message Data", msg.getInt("DATA0"));
                break;
            }
        }
    }​



    . 간단한 데이터 전달을 하는 경우
      형식을 정하지 않고 해당 메세지에 데이터만 실어 보냈기 때문에 수신부에서는 형변환이 필요함
      해당 방식을 이용하면 간단한 데이터를 Bundle 을 사용하지 않고 한줄에 데이터 전송이 가능
    송신부 C
    mhandler.sendMessage(Message.obtain(mhandler, code_0, "DATA"));

    수신부 C
    Handler mhandler = new Handler(){
        @Override 
        public void handleMessage(@NonNull Message msg) { 
            super.handleMessage(msg);
            switch(msg.whar){
                case code_0 :
                Log.d("Message Data", (String) msg.obj);
                break;
            }
        }
    }​

 

 

기본적인 메세지(Message) 송수신 방식에 대하여 설명해 봤다.

 

초심자가 보기에 복잡한 내용보다는 간단하고 바로 써먹을 수 있는 내용 위주로 작성하다 보니 자세한 설명은 빠져있을 수도 있다. 자세한 내용은 구글 다큐먼트를 참고 하거나 다른 블로그에도 내용이 많으니 참고하길 바람

 

메세지를 이용하는 다른 방안이나 좋은 의견있다면 언제든지 댓글로 부탁합니다. 

 

오늘도 코딩 화이팅~!!

반응형

+ Recent posts