티스토리 뷰
Jsoup : HTML 파싱 자바 라이브러리
Jsoup은 웹 사이트의 내용을 쉽게 파싱하여 가져올 수 있도록 만들어진 자바 라이브러리이다.
Jsoup을 이용하여 로또 당첨사이트의 당첨 번호와 이미지를 가져오는 예제를 실습해보았다.
http://www.nlotto.co.kr/common.do?method=main 에서
이것과 비슷하게 만들어보았다.
레이아웃 만들기
<?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:gravity="center"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.ktds.jmj.mybeaconapplication.CouponActivity">
<TextView
android:id="@+id/tvLatestLotto"
android:gravity="center"
android:textSize="30dp"
android:textStyle="bold"
android:textColor="#0054FF"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingTop="20dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/ivNumber1"
android:layout_width="40dp"
android:layout_height="40dp" />
<ImageView
android:id="@+id/ivNumber2"
android:layout_width="40dp"
android:layout_height="40dp" />
<ImageView
android:id="@+id/ivNumber3"
android:layout_width="40dp"
android:layout_height="40dp" />
<ImageView
android:id="@+id/ivNumber4"
android:layout_width="40dp"
android:layout_height="40dp" />
<ImageView
android:id="@+id/ivNumber5"
android:layout_width="40dp"
android:layout_height="40dp" />
<ImageView
android:id="@+id/ivNumber6"
android:layout_width="40dp"
android:layout_height="40dp" />
<TextView
android:text=" + "
android:textSize="30dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/ivNumber7"
android:layout_width="40dp"
android:layout_height="40dp" />
</LinearLayout>
<TextView
android:id="@+id/tvWinGameCount"
android:gravity="center"
android:paddingTop="20dp"
android:textSize="18dp"
android:textStyle="bold"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tvWinGameMoney"
android:gravity="center"
android:paddingTop="20dp"
android:textSize="18dp"
android:textStyle="bold"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
인터넷 권한
인터넷 권한을 얻기 위해 AndroidManifest.xml 에 INTERNET permission 코드를 추가한다.
<uses-permission android:name="android.permission.INTERNET" />
인터넷권한을 위한 PermissionRequester 클래스 파일 만들기
package com.ktds.jmj.mybeaconapplication;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
/**
* Created by Minchang Jang on 2016-06-12.
*/
public class PermissionRequester {
/**
* 요청 AndroidOS의 버젼이 마쉬멜로우 이상 버젼이 아닐 경우
*/
public static final int NOT_SUPPORT_VERSION = 2;
/**
* 요청 권한을 이미 가지고 있을 경우
*/
public static final int ALREADY_GRANTED = -1;
/**
* 권한을 System에게 요청한 경우
* Activity의 onRequestPermissionsResult() 로 결과 리턴됨.
*/
public static final int REQUEST_PERMISSION = 0;
private Activity context;
private Builder builder;
private void setBuilder(Builder builder) {
this.builder = builder;
}
private PermissionRequester(Activity context) {
this.context = context;
}
public int request(final String permission, final int requestCode, final OnClickDenyButtonListener denyAction) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
/*
* 해당 App이 특정 권한을 가지고 있는지 검사함.
* 리턴결과는 PackageManager.PERMISSION_DENIED 와 PackageManager.PERMISSION_GRANTED로 나눠짐.
* PackageManager.PERMISSION_DENIED : 권한이 없음
* PackageManager.PERMISSION_GRANTED : 권한이 있음.
*/
int permissionCheck = ContextCompat.checkSelfPermission(context, permission);
/*
* 해당 권한이 없을 경우 처리 방법
*/
if (permissionCheck == PackageManager.PERMISSION_DENIED) {
/*
* 권한을 취득할 때 사용자로부터 확인을 받아야 하는지 확인
* 여기서 true가 나올 경우는 해당 앱에서 한번이라도 권한을 Deny한 경우일 때 말고는 없음.
* 권한에 대해서 허가하지 않은 경우 다시 한번 권한의 취득을 위해 사용자에게 이유를 고지해야 함.
* Marshmellow 버젼 이상부터 사용가능함.
*/
if (context.shouldShowRequestPermissionRationale(permission)) {
/*
* 권한 취득해야 하는 이유를 Dialog 등을 통해서 알린다.
*/
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
dialog.setTitle(builder.getTitle())
.setMessage(builder.getMessage())
.setPositiveButton(builder.getPositiveButtonName(), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
/*
* 권한의 취득을 요청한다.
* 취득하고자 하는 권한을 배열에 넣고 요청한다.
* 뒤에 들어가는 파라미터(requestCode)는 onRequestPermissionsResult() 에서 권한 취득 결과에서 사용된다.
* startActiviryForResult의 Request Code와 유사함.
*/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
context.requestPermissions(new String[]{permission}, requestCode);
}
}
})
.setNegativeButton(builder.getNegativeButtonName(), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
denyAction.onClick(context);
}
}).create().show();
return REQUEST_PERMISSION;
} else {
/*
* 권한의 취득 요청을 처음 할 때
* 권한의 취득을 요청한다.
* 취득하고자 하는 권한을 배열에 넣고 요청한다.
* 뒤에 들어가는 파라미터(1000)는 onRequestPermissionsResult() 에서 권한 취득 결과에서 사용된다.
* startActiviryForResult의 Request Code와 유사함.
*/
context.requestPermissions(new String[]{permission}, requestCode);
return REQUEST_PERMISSION;
}
} else {
/*
* 이미 권한을 가지고 있을 경우
* 해야할 일을 수행한다.
*/
return ALREADY_GRANTED;
}
}
return NOT_SUPPORT_VERSION;
}
public static class Builder {
private PermissionRequester requester;
public Builder(Activity context) {
requester = new PermissionRequester(context);
}
private String title = "권한 요청";
private String message = "기능의 사용을 위해 권한이 필요합니다.";
private String positiveButtonName = "네";
private String negativeButtonName = "아니요";
public String getTitle() {
return title;
}
public Builder setTitle(String title) {
this.title = title;
return this;
}
public String getMessage() {
return message;
}
public Builder setMessage(String message) {
this.message = message;
return this;
}
public String getPositiveButtonName() {
return positiveButtonName;
}
public Builder setPositiveButtonName(String positiveButtonName) {
this.positiveButtonName = positiveButtonName;
return this;
}
public String getNegativeButtonName() {
return negativeButtonName;
}
public Builder setNegativeButtonName(String negativeButtonName) {
this.negativeButtonName = negativeButtonName;
return this;
}
public PermissionRequester create() {
this.requester.setBuilder(this);
return this.requester;
}
}
public interface OnClickDenyButtonListener {
public void onClick(Activity activity);
}
}
Jsoup Dependency 추가하기
Jsoup을 사용하기 위해 Gradle Scripts 에서 build.gradle 에 Jsoup Dependency 를 추가한다.
compile 'org.jsoup:jsoup:1.9.2'
MainActivity에 TextView, ImageView 선언하기
private TextView tvLatestLotto;
private ImageView ivNumber1;
private ImageView ivNumber2;
private ImageView ivNumber3;
private ImageView ivNumber4;
private ImageView ivNumber5;
private ImageView ivNumber6;
private ImageView ivNumber7;
private TextView tvWinGameCount;
private TextView tvWinGameMoney;
또한 위에서 생성한 PermissionRequester 클래스를 이용하여 인터넷 권한을 요청하는 코드를 작성한다.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_coupon);
PermissionRequester.Builder request = new PermissionRequester.Builder(this);
request.create().request(Manifest.permission.INTERNET, 10000, new PermissionRequester.OnClickDenyButtonListener() {
@Override
public void onClick(Activity activity) {
Toast.makeText(activity, "인터넷 권한이 필요합니다.", Toast.LENGTH_SHORT).show();
activity.finish();
}
});
tvLatestLotto = (TextView) findViewById(R.id.tvLatestLotto);
tvWinGameCount = (TextView) findViewById(R.id.tvWinGameCount);
tvWinGameMoney = (TextView) findViewById(R.id.tvWinGameMoney);
ivNumber1 = (ImageView) findViewById(R.id.ivNumber1);
ivNumber2 = (ImageView) findViewById(R.id.ivNumber2);
ivNumber3 = (ImageView) findViewById(R.id.ivNumber3);
ivNumber4 = (ImageView) findViewById(R.id.ivNumber4);
ivNumber5 = (ImageView) findViewById(R.id.ivNumber5);
ivNumber6 = (ImageView) findViewById(R.id.ivNumber6);
ivNumber7 = (ImageView) findViewById(R.id.ivNumber7);
}
AsyncTask를 이용하여 웹으로 접근
먼저 로또 번호를 가져오는 AsyncTask
private class GetLottoNumberTask extends AsyncTask<Void, Void, Map<String,String>> {
@Override
protected Map<String, String> doInBackground(Void... params) {
Map<String,String> result = new HashMap<String,String>();
try {
Document document = Jsoup.connect("http://nlotto.co.kr/common.do?method=main").get();
Elements elements = document.select(".lotto_area #lottoDrwNo");
result.put("latestLottoCount", elements.text());
for( int i = 1; i < 7; i++ ) {
elements = document.select(".lotto_area #numView #drwtNo" + i );
result.put("number" + i, elements.attr("src"));
}
elements = document.select(".lotto_area #numView #bnusNo");
result.put("number7", elements.attr("src"));
elements = document.select(".lotto_area .winner_num #lottoNo1Su");
result.put("winGameCount", elements.text());
elements = document.select(".lotto_area .winner_money #lottoNo1SuAmount");
result.put("winGameMoney", elements.text());
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
@Override
protected void onPostExecute(Map<String, String> map) {
tvLatestLotto.setText(map.get("latestLottoCount") + " 회 당첨번호");
tvWinGameCount.setText("총 " + map.get("winGameCount") + " 게임 당첨");
tvWinGameMoney.setText("1등 : " + map.get("winGameMoney") + " 원");
for( int i = 1; i < 8; i++) {
GetImageTask task1 = new GetImageTask();
task1.execute(map.get("number" + i), "number" + i);
}
}
}
로또번호 이미지를 가져오는 AsyncTask
private class GetImageTask extends AsyncTask<String, Void, Bitmap> {
private String numberType;
@Override
protected Bitmap doInBackground(String... params) {
numberType = params[1];
Bitmap bitmap = null;
try {
URL url = new URL("http://www.nlotto.co.kr" + params[0]);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.connect();
bitmap = BitmapFactory.decodeStream(conn.getInputStream());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if ( numberType.equals("number1")) {
ivNumber1.setImageBitmap(bitmap);
}
else if (numberType.equals("number2")){
ivNumber2.setImageBitmap(bitmap);
}
else if (numberType.equals("number3")){
ivNumber3.setImageBitmap(bitmap);
}
else if (numberType.equals("number4")){
ivNumber4.setImageBitmap(bitmap);
}
else if (numberType.equals("number5")){
ivNumber5.setImageBitmap(bitmap);
}
else if (numberType.equals("number6")){
ivNumber6.setImageBitmap(bitmap);
}
else if (numberType.equals("number7")){
ivNumber7.setImageBitmap(bitmap);
}
}
}
생성한 AsycnTask를 onResume에서 실행하기
@Override
protected void onResume() {
super.onResume();
GetLottoNumberTask task = new GetLottoNumberTask();
task.execute();
}
MainAcitivty.java 전체 코드
package com.ktds.jmj.mybeaconapplication;
import android.Manifest;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
public class CouponActivity extends AppCompatActivity {
private TextView tvLatestLotto;
private ImageView ivNumber1;
private ImageView ivNumber2;
private ImageView ivNumber3;
private ImageView ivNumber4;
private ImageView ivNumber5;
private ImageView ivNumber6;
private ImageView ivNumber7;
private TextView tvWinGameCount;
private TextView tvWinGameMoney;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_coupon);
PermissionRequester.Builder request = new PermissionRequester.Builder(this);
request.create().request(Manifest.permission.INTERNET, 10000, new PermissionRequester.OnClickDenyButtonListener() {
@Override
public void onClick(Activity activity) {
Toast.makeText(activity, "인터넷 권한이 필요합니다.", Toast.LENGTH_SHORT).show();
activity.finish();
}
});
tvLatestLotto = (TextView) findViewById(R.id.tvLatestLotto);
tvWinGameCount = (TextView) findViewById(R.id.tvWinGameCount);
tvWinGameMoney = (TextView) findViewById(R.id.tvWinGameMoney);
ivNumber1 = (ImageView) findViewById(R.id.ivNumber1);
ivNumber2 = (ImageView) findViewById(R.id.ivNumber2);
ivNumber3 = (ImageView) findViewById(R.id.ivNumber3);
ivNumber4 = (ImageView) findViewById(R.id.ivNumber4);
ivNumber5 = (ImageView) findViewById(R.id.ivNumber5);
ivNumber6 = (ImageView) findViewById(R.id.ivNumber6);
ivNumber7 = (ImageView) findViewById(R.id.ivNumber7);
}
@Override
protected void onResume() {
super.onResume();
GetLottoNumberTask task = new GetLottoNumberTask();
task.execute();
}
private class GetLottoNumberTask extends AsyncTask<Void, Void, Map<String,String>> {
@Override
protected Map<String, String> doInBackground(Void... params) {
Map<String,String> result = new HashMap<String,String>();
try {
Document document = Jsoup.connect("http://nlotto.co.kr/common.do?method=main").get();
Elements elements = document.select(".lotto_area #lottoDrwNo");
result.put("latestLottoCount", elements.text());
for( int i = 1; i < 7; i++ ) {
elements = document.select(".lotto_area #numView #drwtNo" + i );
result.put("number" + i, elements.attr("src"));
}
elements = document.select(".lotto_area #numView #bnusNo");
result.put("number7", elements.attr("src"));
elements = document.select(".lotto_area .winner_num #lottoNo1Su");
result.put("winGameCount", elements.text());
elements = document.select(".lotto_area .winner_money #lottoNo1SuAmount");
result.put("winGameMoney", elements.text());
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
@Override
protected void onPostExecute(Map<String, String> map) {
tvLatestLotto.setText(map.get("latestLottoCount") + " 회 당첨번호");
tvWinGameCount.setText("총 " + map.get("winGameCount") + " 게임 당첨");
tvWinGameMoney.setText("1등 : " + map.get("winGameMoney") + " 원");
for( int i = 1; i < 8; i++) {
GetImageTask task1 = new GetImageTask();
task1.execute(map.get("number" + i), "number" + i);
}
}
}
private class GetImageTask extends AsyncTask<String, Void, Bitmap> {
private String numberType;
@Override
protected Bitmap doInBackground(String... params) {
numberType = params[1];
Bitmap bitmap = null;
try {
URL url = new URL("http://www.nlotto.co.kr" + params[0]);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.connect();
bitmap = BitmapFactory.decodeStream(conn.getInputStream());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if ( numberType.equals("number1")) {
ivNumber1.setImageBitmap(bitmap);
}
else if (numberType.equals("number2")){
ivNumber2.setImageBitmap(bitmap);
}
else if (numberType.equals("number3")){
ivNumber3.setImageBitmap(bitmap);
}
else if (numberType.equals("number4")){
ivNumber4.setImageBitmap(bitmap);
}
else if (numberType.equals("number5")){
ivNumber5.setImageBitmap(bitmap);
}
else if (numberType.equals("number6")){
ivNumber6.setImageBitmap(bitmap);
}
else if (numberType.equals("number7")){
ivNumber7.setImageBitmap(bitmap);
}
}
}
}
결과화면
'Android' 카테고리의 다른 글
[Android] 비콘(Beacon) (2) | 2016.08.11 |
---|---|
[Android] SplashActivity ( 로딩화면 ) (1) | 2016.08.10 |
[Android] 페이스북 타임라인에 포스팅하기, 글 검색하기 (0) | 2016.08.08 |
[Android] 페이스북 글 가져오기 (3) | 2016.08.07 |
[Android] Android Landscape (가로모드) (1) | 2016.08.05 |
- Total
- Today
- Yesterday
- indexOf
- 이클립스
- onBackPressed
- restfb
- RequestMapping
- boj
- 안드로이드 스튜디오
- java
- REDIRECT
- table
- maven
- DFS
- AlertDialog.Builder
- sort
- 예외처리
- onPostExecute
- DP
- order by
- list
- jsp
- Baekjoon Online Judege
- 자바
- Spring
- mybatis
- 안드로이드 비콘
- algorithm
- INSERT
- controller
- BFS
- servlet
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |