최종 업데이트 20.09.25
HttpURLConnection 을 이용하여 웹페이지의 내용(html) 을 읽어오는 예제
0. 먼저 Manifest.xml 에 권한을 추가한다.
<uses-permission android:name="android.permission.INTERNET"/>
1. 웹페이지의 내용을 뿌려줄 화면 레이아웃을 구성한다.
editText에 있는 링크에 접속해서 textView에 내용 뿌려주는 뷰로 구성되어있다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Button" />
<EditText
android:id="@+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:inputType="textPersonName"
android:text="https://m.naver.com" />
</LinearLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_blue_dark">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>
</LinearLayout>
2. 웹페이지에 연결할 Thread 클래스를 만든다.
스레드를 따로 만들어야하는 이유는, 작업시간이 오래걸릴 수 있는 IO 작업(서버통신)을 메인스레드에서 작업할 경우 블로킹이 발생할 수 있기때문에 안드로이드 자체적으로 익셉션이 발생한다. 따라서 IO 작업은 백그라운드 스레드로 수행해야한다.
class RequestThread extends Thread {
public void run(){
try {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
if (conn != null){
conn.setConnectTimeout(10000); // 10초 대기 후 응답이 없으면 끝
conn.setRequestMethod("GET");
conn.setDoInput(true); // 서버에서 받기 가능
conn.setDoOutput(true); // 서버에 보내기 가능
int resCode = conn.getResponseCode(); // 서버에 연결 시도
// reader는 바이트 배열이 아니라, 문자열로 처리할 수 있음
// BufferedReader는 한줄씩 읽어들임
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = null;
while (true) {
line = reader.readLine();
if (line == null) break;
println(line);
}
reader.close();
conn.disconnect();
}
} catch(Exception e){
e.printStackTrace();
}
}
}
public void println(final String data){
handler.post(new Runnable() {
@Override
public void run() {
textView.append(data + "\n");
}
});
}
백그라운드 스레드에서 실행한 작업 결과를 바로 textView 에 뿌리려고하면 익셉션이 발생한다. 안드로이드 뷰에 접근할 수 있는 스레드는 메인스레드로 한정되어있기 때문이다. 따라서 메인스레드로 작업 결과물을 패스할 수 있도록 핸들러를 이용해 메인스레드 작업큐로 보내야한다.
위처럼 해야하는 이유가 궁금하다면 여기를 읽어보길 바란다. 오래된 아티클이지만 안드로이드가 백그라운드를 다루는 개념을 쉽게 이해할 수 있을 것이다.
# 메인액티비티 전체코드
public class MainActivity extends AppCompatActivity {
EditText editText;
TextView textView;
Handler handler = new Handler();
String urlStr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = findViewById(R.id.editText);
textView = findViewById(R.id.textView);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
urlStr = editText.getText().toString();
RequestThread thread = new RequestThread();
thread.start();
}
});
}
class RequestThread extends Thread {
public void run(){
try {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
if(conn != null){
conn.setConnectTimeout(10000); // 10초 대기 후 응답이 없으면 끝
conn.setRequestMethod("GET");
conn.setDoInput(true); // 서버에서 받기 가능
conn.setDoOutput(true); // 서버에 보내기 가능
int resCode = conn.getResponseCode(); // 서버에 연결 시도
// reader는 바이트 배열이 아니라, 문자열로 처리할 수 있음
// BufferedReader는 한줄씩 읽어들임
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = null;
while(true){
line = reader.readLine();
if(line == null) break;
println(line);
}
reader.close();
conn.disconnect();
}
} catch(Exception e){
e.printStackTrace();
}
}
}
public void println(final String data){
handler.post(new Runnable() {
@Override
public void run() {
textView.append(data + "\n");
}
});
}
}
사실 스레드 클래스를 위처럼 짜면 메모리 릭 위험성이 존재하므로 그대로 따라하면 안된다. 왜 메모리릭이 발생하는지 모른다면 스스로 공부해보길 바란다 ^.'
'Android > Basic' 카테고리의 다른 글
[Android] Gson을 이용한 JSON 변환 (0) | 2018.07.07 |
---|---|
[Android] Volley 라이브러리를 활용한 서버 통신 (0) | 2018.07.07 |
[Android] Socket 통신 예제 (0) | 2018.07.07 |
[Android] AsyncTask (0) | 2018.07.06 |
[Android] Thread와 handler 그리고 Runnable (0) | 2018.07.06 |