[18. 네트워크 프로그래밍]
[18-1. 스마트폰 정보 구하기]
[전화 상태 변화 감지]
-안드로이드12(API 31)에서 PhoneStateListener은 deprecated 되었고, 대신 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 | 통화 중인 상태 |
<TelephonyManager의 listen(). | ‘감지할 상태 상수’>
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) ConnectivityManager의 getActivityNetwork() 함수로 ‘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) RequestQueue의 add() 호출하는 방법 [기본] 방법 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.gradle의 dependencies 항목에 라이브러리 등록
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 객체로 서비스 인터페이스 구현 객체 얻기]
-Retrofit의 create() 함수에 ’서비스 인터페이스 타입‘ 전달하면 이 함수가 해당 타입의 인터페이스 구현한 ’서비스 객체‘를 반환해줌
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 코틀린 |
'App(앱)_관련 공부 모음 > [교재] Andorid App_Kotlin 기반' 카테고리의 다른 글
20. [파이어베이스 연동과 인증 기능] (0) | 2022.03.31 |
---|---|
19. [위치 정보 활용] (0) | 2022.03.30 |
17. [저장소에 데이터 보관] (0) | 2022.03.25 |
16. [콘텐츠 프로바이더 컴포넌트] (0) | 2022.03.24 |
15. [서비스 컴포넌트] (0) | 2022.03.24 |