python 이나, java 에서 소스를 이용해서 jsoup 파싱을 해 보기는 했으나, android 폰에서 구현하는 파싱은 이번이 처음이다.
예전에 lotto 당첨 결과를 얻어오는 앱을 만들어 본 적이 있는데,
그때는 정말 날코딩으로 html 페이지를 분석해서 쪼개여 왔는데, 이제 그 보다 쉬운 방법이 있다는 것이다.
동행복권 페이지에서 회차별 당첨 결과를 조회하는 페이지를 열어서 F12(개발자도구)을 이용해서 페이지에서 얻어와야 하는 html tag 을 찾아보자.
다음은 android studio 에서 새 프로젝트를 하나 만들고... 제일 먼저 그래드 설정에 다음과 같이 jsoup 사용을 위해 추가해 본다. (2021.06.30 기준 버전은 1.13.1)
dependencies {
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'org.jsoup:jsoup:1.13.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
그 다음은 manifast 파일을 열어서 인터넷 사용을 위한 권한 설정을 한다.
<uses-permission android:name="android.permission.INTERNET" />
그리고 다음은 화면을 그릴껀데, 이건 예제 이므로 단순하게 버튼 하나와 textView 하나만 담았다.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="@+id/button"
android:scrollbars="vertical"
android:text="" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginEnd="22dp"
android:layout_marginBottom="43dp"
android:text="HTML 가져오기" />
</RelativeLayout>
그리고 이번에는 MainActivity 구현을 해 본다.
소스에서 살펴볼 부분은 AsyncTask 을 이용해서 비동기 통신을 해야 한다는 것과 어떻게 하면 결과 숫자값만 뽑아올 수 있는 가 하는 부분이다. 위에 html 결과에서 span tag 을 값을 받아와야 하는 데 class 만 표시 되어 있어서 그 class 의 공통적인 종류를 이용해서 필요한 부분이 결과만 추출해 오면 된다.
package com........;
import androidx.appcompat.app.AppCompatActivity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.util.Arrays;
public class MainActivity extends AppCompatActivity {
private String drwNoUrl = "https://dhlottery.co.kr/gameResult.do?method=byWin";
private TextView textviewHtmlDocument;
private String htmlContentInStringFormat = "";
private String nowCnt = "" ;
String TAG = "Lotto" ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textviewHtmlDocument = (TextView) findViewById(R.id.textView);
textviewHtmlDocument.setMovementMethod(new ScrollingMovementMethod());
Button htmlTitleButton = (Button) findViewById(R.id.button);
htmlTitleButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
nowCnt = "969"; // 2021.06.30 기준 마지막 회차
JsoupAsyncTask jsoupAsyncTask = new JsoupAsyncTask();
jsoupAsyncTask.execute(drwNoUrl, nowCnt);
}
});
}
// 백그라운드 호출을 해야 하는 것은 실시간으로 답을 받아올 수 없기 때문에
private class JsoupAsyncTask extends AsyncTask<String, Void, Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Void doInBackground(String... params) {
Log.i(TAG, Arrays.toString(params));
try {
// 파라미터로 넘어온 값을 이용해서 url 와 회차를 설정한다.
String callUrl = params[0] + "&drwNo=" + params[1];
Document doc = Jsoup.connect(callUrl).get();
// 위의 html tag에서 결과숫자를 싸고 있는 span tag 을 class명을 이용함.
Elements links = doc.select(".ball_645");
Log.e(TAG, "links=" + links.size());
htmlContentInStringFormat += "회차=" + nowCnt ;
for(Element el : links) {
Log.e(TAG, el.text()) ;
htmlContentInStringFormat += " " + el.text() ;
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
textviewHtmlDocument.setText(htmlContentInStringFormat);
}
}
}
AsyncTask를 사용하면 UI 스레드를 적절하고 쉽게 사용할 수 있다. 이 클래스를 사용하면 스레드 및 / 또는 핸들러를 조작하지 않고도 백그라운드 작업을 수행하고 UI 스레드에 결과를 게시 할 수 있다.
AsyncTask는 Thread and Handler에 대한 도우미 클래스로 설계되었으며 일반적인 스레딩 프레임 워크를 구성하지 않는다. AsyncTasks는 짧은 작업 (최대 몇 초)에 이상적으로 사용되어야 한다.
화면의 결과가 초라해(?) 보이기는 해도 쉽게 그 결과를 얻어올 수 있었다.
살펴보고 궁금한 것이 있으시다면. 댓글을 달아 주세요.
'모바일 앱(안드로이드)' 카테고리의 다른 글
안드로이드 앱 만들기 random 한 수 그것도 중복이 없게 뽑아 볼 까 ? (0) | 2021.07.21 |
---|---|
안드로이드 다국적(?) 앱 만들어 보기 (feat 카카오 번역 API, python 활용) (2) | 2021.07.06 |
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo ... 오류가 발생 하다면. (0) | 2021.06.29 |
안드로이드 앱 만들기 구글 인앱 결제 쉽게 따라 하기... (2) | 2021.05.15 |
안드로이드 앱 만들기 API 연동을 위한 retrofit 구현 이야기. (0) | 2021.05.15 |