18. [네트워크 프로그래밍]

728x90

[18. 네트워크 프로그래밍]

[18-1. 스마트폰 정보 구하기]

[전화 상태 변화 감지]

-안드로이드12(API 31)에서 PhoneStateListenerdeprecated 되었고, 대신 TelephonyCallback 추가 됐다.

- 호환성 고려해야 하므로 두 방법 모두 학습한다.

   [PhoneStateListener 이용하는 방법]

  1) PhoneStateListener 상속받은 클래스 내부에 (상태 변화 감지 자동 호출) 함수 중 필요한 것만 재정의해서 작성

  2) TelephonyManager
객체를 getSystemService() 함수로 얻고,
이 객체의 listen() 함수에 PhoneStateListener 객체를 등록.

  3)
등록 시, listen()의 두 번째 매개변수에는 감지할 상태 상수값 지정.


  4)
상태 변화 감지 해제 시, listen()LISTEN_NONE 상수 지정함

           <PhoneStateListener의 자동 호출 함수>

-전화의 해당 상태 변화 시, 자동 호출되는 함수들임

onCallForwardingIndicatorChanged() 통화 전달 상태 변경
onCallStateChanged() 통화 상태 변경
onCellLocationChanged() 폰 기지국 위치 변경
onDataActivity() 데이터 송수신 활동
onDataConnctionStateChanged() 데이터 연결 상태 변경
onMessageWaitingIndicatorChanged() 메시지 대기 상태 변경
onServiceStateChanged() 단말기 서비스 상태 변경
onSignalStrengthsChanged() 신호 세기 변경

     [ onServiceStateChanged() 함수 ] : 단말기 서비스 상태 변화 시 자동 호출됨

-상태 변화 시 이 함수 호출되면서 이 함수의 매개변수인 ServiceState 객체의 state 바뀐 서비스 상태 상수’ 전달 

STATE_IN_SERVICE 서비스 가능 상태
STATE_EMERGENCY_ONLY 긴급 통화만 가능 상태
STATE_OUT_OF_SERVICE 서비스 불가 상태
STATE_POWER_OFF 전화 기능 꺼놓은 상태

      [ onCallStateChanged() 함수 ] : 전화 걸려오는 상태 감지 후 자동 호출됨

-상태 변화 시, 이 함수의 첫 번째 매개변수에 전화 걸려오는 상태 상수값 전달

CALL_STATE_IDLE 통화 대기 상태
CALL_STATE_RINGING 벨 울리는 상태
CALL_STATE_OFFHOOK 통화 중인 상태

           <TelephonyManagerlisten(). | ‘감지할 상태 상수’>

LISTEN_CALL_FORWARDING_INDICATOR 통화 전달 지시자
LISTEN_CALL_STATE 통화 상태
LISTEN_CELL_LOCATION 기지국 위치
LISTEN_DATA_ACTIVITY 데이터 송수신 활동
LISTEN_DATA_CONNECTION_STATE 데이터 연결 상태
LISTEN_MESSAGE_WAITING_INDICATOR 메시지 대기 지시자
LISTEN_SERVICE_STATE 단말기 서비스 상태
LISTEN_SIGNAL_STRENGTHS 신호 세기

   ② [ TelephonyCallback 이용하는 방법]

  1) TelephonyCallback 구현 객체를 registerTelephonyCallback() 함수 이용해서
                                                                            getSystemService()로 얻은 TelephonyManager에 등록함

  2)
등록 시, 상태에 따라 API 제공 인테피이스도 구현해야 할 수 있음


  3)
정상적인 전화 상태 감지 위해 퍼미션 등록

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

           <각종 상태 변화 감지 인터페이스>

TelephonyCallback.CellLocationListener (cell) 위치 변화 감지
TelephonyCallback.ServiceStateListener 서비스 상태 변화 감지
TelephonyCallback.SignalStrengthsListener 신호 세기 변화 감지
TelephonyCallback.DataActivityListener 데이터 송수신 상태 변화 감지
TelephonyCallback.DataConnectionStateListener 데이터 접속 상태 변화 감지
TelephonyCallback.CallStateListener 전화 상태 변화 감지

[TelephonyManager로 네트워크 제공 정보 얻기]

-이 객체로 네트워크 제공하는 (국가/사업자/전화번호) 정보 얻을 수 있다.

            , 스마트폰 전화번호 정보 추출 시에는 다음의 퍼미션 추가해야 함
              <uses-permission android:name = “android.permission.READ_PHONE_NUMBER”/>

           <이 객체가 제공하는 정보 반환 함수>

getNetworkCountryIso() 네트워크 제공 국가
getNetworkOperatorName() 네트워크 제공 사업자
getLine1Number() 스마트폰 전화번호

           <이 객체의 속성에 접근하여 정보 얻기>

예)  val countryIso = telephonyManager.networkCountryIso //이런 식으로 정보 얻음

networkCountryIso 속성 네트워크 제공 국가 정보
networkOperatorName 속성 네트워크 제공 사업자 정보
line1Number 속성 스마트폰 전화번호

[네트워크 접속 정보] : ConnectivityManager

-ConnectivityManager 이용하려면 다음의 네트워크 상태 접근 퍼미션선언 필요

<uses-permission android:name = “android.permission.ACCESS_NETWORK_STATE/>

  [getActivityNetwork() 함수 이용하여 정보 얻는 방법]

  1) ConnectivityManagergetActivityNetwork() 함수로 ‘Network’ 객체 얻기

  2) <
네트워크 접속 가능 여부 얻기>

- Network 객체의 activityNetwork 정보가 null 인 경우 -> 접속 불가능 상태


3) <현재 접속 중인 네트워크 정보 얻기>
- getNetworkCapabilities() 함수의 매개변수에 Network 객체의 activityNetwork 정보를 지정
- 이 함수의 반환값은 ‘NetworkCapabilities 객체인데,이 객체에 hasTransport() 이용

                           -> NetworkCapabilities.TRANSPORT_WIFI // 와이파이 접속 중인 상태
                           -> NetworkCapabilities.TRANSPORT_CELLULAR // 이동 통신망 접속 중인 상태

 [requestNetwork() 함수 이용하여 정보 얻는 방법]

-함수 이용하려면 다음의 퍼미션 선언 필요

<uses-permission android:name = “android.permission.CHANGE_NETWORK_STATE”/>

  <requestNetwork() 함수의 정의>
requestNetwork (NetworkRequest request, ConnectivityManager.NetworkCallbacknetworkCallback)
                       // 네트워크 타입 담는 객체                           //설정한 네트워크 타입을 지정

            <네트워크 타입 설정>

  1) 첫 번째 매개변수인 NetworkRequest 객체에 접근하여 타입 지정 가능 O
                                         이 객체의 addCapability() / addTransportType() 함수에 상수값 넣어서 타입 지정
  2) 위에서 설정한 네트워크 타입을 두 번째 매개변수로 지정
                    -그러면 콜백 함수가 자동 호출되는데 호출된 함수 종류에 따라.
                                             -> onAvaliable() 함수 호출되면 지정한 타입의 네트워크 가능하다는 의미
                                             -> onUnavailable() 함수 호출되면 지정한 타입의 네트워크 불가능하다는 의미

                 + ) addCapability() / addTransportType()의 매개변수<지정 가능 상수값 종류>

NET_CAPABILITY_INTERNET 일반적인 데이터 통신
TRANSPORT_CELLULAR 이동 통신망
TRANSPORT_WIFI 와이파이

[18-2, HTTP 통신]

[HTTP 통신 준비]

    1) 인터넷 퍼미션 선언

<uses-permission android:name = “android.permission.INTERNET”/>

     2) [HTTP 통신 허용]

  [일부 도메인 서버와의 HTTP 통신 허용]

-등록한 특정 도메인만 통신 허용

XML 파일 속 <domain>태그에 통신 허용할 서버 IP or 도메인 작성


매니페스트의 <application> 태그networkSecurityConfig 속성에 XML 파일 등록

  ▶ [모든 도메인 서버와 HTTP 통신 허용]

-앱 전체에서 모든 도메인 서버와 HTTP 통신 허용함

매니페스트의 <application> 태그에 usesCleartextTraffic 속성을 true 설정

[안드로이드 앱 네트워크 프로그래밍 돕는 라이브러리]

   [Volley 라이브러리]

-구글 제공 공개 라이브러리. 앱에서 HTTP 통신 더 쉽게 구현 도움

-라이브러리 사용 위해 build.gradle 파일 속 의존 추가

implemetation ‘com.android.volley:volley:1.2.1’

        <Volley의 핵심 클래스>

RequestQueue 서버에 요청 보내는 역할
XXXXRequest 서버와의 요청 상호작용에서 데이터 타입에 따라 요청 정보 담는 역할 

      ⇒ [StringRequest] : 문자열 데이터 요청

-서버에 문자열 데이터 요청 시 담는 역할

-생성자 (HTTP 메소드/서버URL/서버로부터 결과받을 때 호출 콜백/서버연동 실패 시 호출 콜백)

-생성자의 세 번째 매개변수  ( , 서버로부터 결과 데이터 받는 순간 호출할 콜백) 에는
     Response.Listener 구현 객체가 들어가는데
    이 객체의 onResponse() 함수가 자동 호출되어 매개변수로 서버 데이터 전달받는 것.

          <StringRequest 에 담은 정보대로 서버 요청>

- Volley.newRequestQueue(this)RequestQueue 객체 얻고,

                   이 객체의 add() 함수에 정의한 RequestString 객체 담으면 서버에 요청 보내짐

           [+ 서버 요청 시 데이터 함께 전달]

-> GET 방식에서는 URL 뒤에 추가,

-> POST 
방식에서는 StringRequest 상속받은 클래스 속에 getParams() 재정의하고

                              이 함수 반환 타입인 MutableMap 전달할 데이터 담아서 반환하면 서버 요청 시 함께 전달됨

 

      [ImageRequest] : 이미지 데이터 요청

-생성자의 두 번째 매개변수. 콜백함수

Response.Listener<Bitmap> 타입으로 지정되어 있으므로 Bitmap 이미지로 받음

< ImageRequest의 생성자 >

  ImageRequest( 서버URL/ 결과콜백/ 이미지너비/이미지높이/scale타입/이미지형식지정/오류 콜백)

 

      [NetworkImageView] : 화면 출력용 이미지 데이터 요청

<사용법>

액티비티 화면 구성 레이아웃 XML 안에 <com.android.volley.toolbox.NetworkImageView> 작성 후
                        이 객체의 setImageUrl() 함수 호출 시 자동으로 데이터 요청, 출력 O

                      <서버 연동. 서버에 요청하기>

            방법 1) RequestQueueadd() 호출하는 방법 [기본]
            방법 2) setImageUrl() 함수의 두 번째 매개변수에 ImageLoader의 하위 클래스 객체 지정 자동으로 서버 연동됨

                     <setImageUrl() 서버 연동 작동 방식>

       -두 번째 매개변수에 ImageLoader 객체 지정 시 서버 이미지 가져오기 전. 이 객체 내부의 getBitmap() 자동 호출

 getBitmap() 의 반환값

     반환값이 null 인 경우 -> 서버에 요청 보냄

            -요청 후 서버로부터 이미지 가져오면 다시 내부의 putBitmap() 함수 자동 호출되어
                                                                      서버 이미지를 putBitmap()의 두 번째 매개변수로 전달됨

     반환값이 Bitmap 객체이면 -> 해당 Bitmap 객체 그대로를 NetworkIageView에 출력

 

       [JsonObjectRequest ] : JSON 데이터 요청

-이 객체 이용 시 자동으로 JSON 데이터 파싱한 JSONObject 객체가 콜백함수에 전달됨

<JsonObjectRequest의 생성자>
JsonObjectRequest (HTTP 메소드/ 서버URL/ JSONObject /결과 콜백/에러 콜백)

- 세 번째 매개변수 JSONObject서버 요청 시 전송할 데이터담을 수 O

- 네 번째 매개변수 콜백에는 서버로부터 넘어오는 JSON 파싱한 JSONObject 객체 전달됨.                                                              이 객체에 접근하여 getter() 함수로 가져올 데이터 킷값 명시 후 JSON 데이터 가져옴

 

       [JsonArrayRequest] : JSON 배열 요청

<JsonArrayRequest 의 생성자>

 JsonArrayRequest (URL/ JSONArray/ 결과 콜백/에러 콜백)

   [Retrofit 라이브러리]

-스퀘어에서 만든 HTTP 통신 간편하게 돕는 라이브러리

[Retrofit 동작 방식]

통신용 함수 선언한 서비스 인터페이스작성
Retrofit에 인터페이스 전달
Retrofit이 통신용 서비스 객체 반환
서비스 객체의 통신용 함수 호출 시, Call 객체 반환
Call 객체의 enqueue() 함수 호출 즉시 네트워크 통신 수행

     <사용 준비>

[라이브러리 선언] : build.gradledependencies 항목에 라이브러리 등록

implementation ‘com.squareup.retrofit2:retrofit:2.9.0’ //필수 등록

[파싱 라이브러리 등록]

-Retrofit은 기본적으로 JSON이나 XML 데이터를 모델(VO클래스) 객체로 변환해주기 때문에                                                                                                         JSON, XML을 파싱하는 라이브러리 필요함

implementtation ‘com.google.code.gson:gson:2.8.6’ //파싱 라이브러리

[converter 라이브러리 등록]

-파싱 라이브러리에 맞춰서 converter 라이브러리 등록

           <Retrofit 제공 converter 라이브러리 >

Gson com.squreup.retrofit2:converter-gson
Jackson com.squreup.retrofit2:converter-jackson
Moshi com.squreup.retrofit2:converter-moshi
Protobuf com.squreup.retrofit2:converter-protobuf
Wire com.squreup.retrofit2:converter-wire
Simple XML com.squreup.retrofit2:converter-simplexml
JAXB com.squreup.retrofit2:converter-jaxb
Scalars com.squreup.retrofit2:converter-scalars

[모델 클래스 선언] : VO 클래스

-서버와 주고받는 데이터 표현 클래스
-JSON, XML 데이터 파싱해서 모델 객체에 담는 것을 자동화 해줌
     -<기본 규칙> : 데이터 키-프로퍼티 이름 매칭
     -<이름 다를 때> : @SerializedName 으로 이름 명시
-서버 데이터와 상관없는 프로퍼티 선언 가능O
-서버 데이터 복잡할 때, 모든 데이터를 여러 클래스로 분리 후 조합하여 사용O

     <통신 준비>

[서비스 인터페이스 정의]

이 인터페이스 내부의 함수에 선언한 @ 애너테이션을 보고 해당 정보대로 네트워크 통신 가능 코드 자동으로 만들어 줌

interface INetworkService {
  @GET(“api/users”)
  fun doGetUserList(@Query(“page”) page:String) : Call<UserListModel> 
  @GET
  fun getAvatarImage(@Url url : String) :Call<ResponseBody>
}

[Retrofit 객체 생성]

-Retrofit 객체 생성 코드는 초기 설정한 번만 생성해주면 됨

-baseUrl()URL 설정 후, 이 뒤에 올 경로만 지정해서 서버 연동O

-addConverterFactory() 함수로 데이터 파싱하여 모델 객체에 담는 역할자지정 O

val retrofit : Retrofit
   get() = Retrofit.Builder()
         .baseUrl(“https://reqres.in/”)
         .addConverterFactory(GsonConverterFactory.create())
         .build()

[Retrofit 객체로 서비스 인터페이스 구현 객체 얻기]

-Retrofitcreate() 함수에 서비스 인터페이스 타입전달하면 이 함수가 해당 타입의 인터페이스 구현한 서비스 객체를 반환해줌

var networkService : INetworkService = retrofit.create(INetworkService::class.java)

     <네트워크 통신>

[네트워크 통신 시도]

-Retrofit 객체로 얻은 서비스 객체의 함수 호출 시 Call 객체 반환됨

-Call 객체의 enqueue() 함수 호출 순간 실제 통신이루어 진다.

-이때, enqueue() 함수의 매개변수로 지정한 Callback 객체의 함수가 자동 호출되는데

통신 성공 시, onResponse() 함수 자동 호출
통신 실패 시, onFailure() 함수 자동 호출

[Retrofit @애너테이션]

[@GET/@POST/@PUT/@DELETE/@HEAD]

-HTTP 메서드 정의하는 애너테이션

[@Path]

-URL 경로 동적 지정하는 애너테이션

[@Query]

-경로에 ? 이용 -> 서버에 전달할 데이터 지정

[@QueryMap]

-서버에 전송할 데이터 -> 이 애너테이션으로 전송할 데이터 Map 타입 매개변수로 받음

[@Body]

-서버에 전송할 데이터를 모델 객체로 지정하고 싶을 때 사용

-@POST와 함께 사용 (@GET 과 사용 불가)

-@Body로 지정한 모델 데이터는 객체 내용을 JSON 문자열로 만들고 데이터 스트림으로 서버에 전송

[@FormUrlEncoded @Field]

-@FormUrlEncoded는 데이터를 URL 인코딩 형태로 만들어 전송 시 사용

-서버 전송 데이터를 -형태의 URL 인코딩으로 전송. POST 방식에섬나 사용 O

-@Field 는 모델 객체에 사용 불가능

[@Header]

-서버 요청에서 헤더값 조정 원할 때 사용

[@Url]

-baseUrl 무시하고 전혀 다른 URL 지정 원할 때 사용


[18-3. 이미지 처리-Glide 라이브러리]

[Glide 라이브러리]

-서버에서 이미지 내려받을 때 쉽게 빠르게 개발 O 라이브러리

-모든 종류의 이미지 빠르게 가져와서 사용O

   <사용 등록>

implementation ‘com.gitgub.bumptech.glide:glide:4.12.0’

[이미지 가져와 출력]

  1) ‘리소스 이미지를 이미지 뷰에 출력

- load() 함수에 리소스 전달 후, into() 함수에 출력될 이미지 뷰 지정

  2) ‘파일 이미지를 이미지 뷰에 출력

갤러리 앱 목록 화면에서 사용자가 선택한 사진 파일 경로를 load() 함수에 지정 후, into() 함수에 출력될 이미지 뷰 지정

  3) ‘서버 이미지를 이미지 뷰에 출력

load() 함수에 이미지 URL을 문자열로 지정하면 자동으로 서버에서 이미지 데이터를 읽어 into() 함수에 지정한 이미지 뷰에 출력한다.


[이미지 크기 조절]

-앞장에서는 이미지 크기가 커서 발생하는 OOM 문제를 고려하여 크기를 직접 줄인 뒤 출력

-Glide는 이미지 뷰의 크기에 맞춰서 자동 크기 줄여 불러오므로 OOM 신경 X

-만약 특정 크기로 이미지 줄이고 싶다면 override() 함수 사용


[로딩 이미지/ 오류 이미지 출력]

-placeholder() 에 지정 이미지 넣어놓고 불러오는 데 실패 시 error() 에 지정한 이미지출력


[이미지 데이터 사용]

-into() 함수에 이미지 데이터 받을 객체로 CustomerTarget 하위 객체 지정

-이 객체는 CustomTarget를 상속받고, 내부에 onResourceReady()/onLoadCleared() 함수 재정의하여 사용해야 함                                 -> ‘Drawable’ 타입 이미지 데이터

-만약 Bitmap 타입 이미지 데이터 받고 싶으면 asBitmap() 함수 사용

[참고] : Do It 안드로이드 앱 프로그래밍 with 코틀린 

728x90