네이버 지식인 질문에 있는 예제를 거의 그대로 테스트한 걸 적어둔다.
volley 라이브러리를 사용해서 하려고 했더니 Jsoup 자체가 네트웍 통신을 하는 기능이 있는거 같다.
단지 AsyncTask 를 이용하여 백그라운드 처리만 하도록 해주면 OK다.
더 간단하게는 PHP 에서 파싱처리한 결과를 Android 에서 JSON으로 가져오는 것도 방법일 거 같다.
테스트한 소스코드 파일
수정 일자 : 2020.2.29
AndroidManifest.xml
파싱과는 무관한 권한도 추가되어 있는데
위험권한 설정하는 라이브러리를 이용하는 법 알려주려고 추가한 것이다.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.link2me.android.jsoup"> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:usesCleartextTraffic="true" <!-- 안드로이드 9에서는 https 통신이 기본이라 http 통신 가능하게--> android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> |
앱 build.gradle
apply plugin: 'com.android.application' android { compileSdkVersion 29 buildToolsVersion "29.0.3" defaultConfig { applicationId "com.link2me.android.jsoup" minSdkVersion 21 targetSdkVersion 29 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.recyclerview:recyclerview:1.0.0' // ListView 개선 버전 implementation 'androidx.cardview:cardview:1.0.0' implementation 'org.jsoup:jsoup:1.11.3' implementation 'gun0912.ted:tedpermission:2.0.0' } |
recyclerview 는 실제 사용을 하지는 않았지만, androidx 에서 버전 표기를 찾기 쉽게 적어둔다.
Layout : activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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/weather_rs1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.057" /> <TextView android:id="@+id/weather_rs2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.127" /> </androidx.constraintlayout.widget.ConstraintLayout> |
MainActivity.java
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import android.content.Context; import android.content.DialogInterface; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.widget.TextView; import android.widget.Toast; import com.gun0912.tedpermission.PermissionListener; import com.gun0912.tedpermission.TedPermission; 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.ArrayList; public class MainActivity extends AppCompatActivity { Context context; TextView textView1, textView2; PermissionListener permissionlistener = new PermissionListener() { @Override public void onPermissionGranted() { initView(); } @Override public void onPermissionDenied(ArrayList<String> deniedPermissions) { Toast.makeText(MainActivity.this, "권한 허용을 하지 않으면 서비스를 이용할 수 없습니다.", Toast.LENGTH_SHORT).show(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); context = MainActivity.this; // 네트워크 연결상태 체크 if (NetworkConnection() == false) NotConnected_showAlert(); checkPermissions(); } private void checkPermissions() { if (Build.VERSION.SDK_INT >= 23) { // 마시멜로(안드로이드 6.0) 이상 권한 체크 TedPermission.with(context) .setPermissionListener(permissionlistener) .setRationaleMessage("앱을 이용하기 위해서는 접근 권한이 필요합니다") .setDeniedMessage("앱에서 요구하는 권한설정이 필요합니다...\n [설정] > [권한] 에서 사용으로 활성화해주세요.") .setPermissions(new String[]{ android.Manifest.permission.WRITE_CONTACTS, // 주소록 액세스 권한 android.Manifest.permission.READ_EXTERNAL_STORAGE, android.Manifest.permission.WRITE_EXTERNAL_STORAGE // 기기, 사진, 미디어, 파일 엑세스 권한 }) .check(); } else { initView(); } } private void initView() { textView1 = findViewById(R.id.weather_rs1); textView2 = findViewById(R.id.weather_rs2); String path1 = "https://weather.naver.com/rgn/cityWetrCity.nhn?cityRgnCd=CT007007"; String path2 = "https://weather.naver.com/rgn/cityWetrCity.nhn?cityRgnCd=CT008008"; new getData1().execute(path1); new getData2().execute(path2); } private class getData1 extends AsyncTask<String, Void, String> { // String 으로 값을 전달받은 값을 처리하고, Boolean 으로 doInBackground 결과를 넘겨준다. @Override protected String doInBackground(String... params) { try { Document document = Jsoup.connect(params[0].toString()).get(); // Web에서 내용을 가져온다. Elements elements = document.select("em"); // 내용중에서 원하는 부분을 가져온다. Element targetElement1 = elements.get(1);//1.현시간 2.온도 3.미세먼지 Element targetElement2 = elements.get(2);//1.현시간 2.온도 3.미세먼지 Element targetElement3 = elements.get(3);//1.현시간 2.온도 3.미세먼지 String text1 = targetElement1.text(); String text2 = targetElement2.text(); String text3 = targetElement3.text(); String text = "시간 : "+text1 + " ,날씨 : " + text2 + " ,미세먼지 : " + text3; System.out.println("대구날씨 : "+text); return text; } catch (IOException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(String result) { textView1.setText("대구 : "+result); } } private class getData2 extends AsyncTask<String, Void, String> { // String 으로 값을 전달받은 값을 처리하고, Boolean 으로 doInBackground 결과를 넘겨준다. @Override protected String doInBackground(String... params) { try { Document document = Jsoup.connect(params[0].toString()).get(); Elements elements = document.select("em"); Element targetElement1 = elements.get(1);//1.현시간 2.온도 3.미세먼지 Element targetElement2 = elements.get(2);//1.현시간 2.온도 3.미세먼지 Element targetElement3 = elements.get(3);//1.현시간 2.온도 3.미세먼지 String text1 = targetElement1.text(); String text2 = targetElement2.text(); String text3 = targetElement3.text(); String text = "시간 : "+text1 + " ,날씨 : " + text2 + " ,미세먼지 : " + text3; System.out.println("부산날씨 : "+text); return text; } catch (IOException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(String result) { textView2.setText("부산 : "+result); } } private void NotConnected_showAlert() { AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setTitle("네트워크 연결 오류"); builder.setMessage("사용 가능한 무선네트워크가 없습니다.\n" + "먼저 무선네트워크 연결상태를 확인해 주세요.") .setCancelable(false) .setPositiveButton("확인", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { finish(); // exit //application 프로세스를 강제 종료 android.os.Process.killProcess(android.os.Process.myPid()); } }); AlertDialog alert = builder.create(); alert.show(); } private boolean NetworkConnection() { int[] networkTypes = {ConnectivityManager.TYPE_MOBILE, ConnectivityManager.TYPE_WIFI}; try { ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); for (int networkType : networkTypes) { NetworkInfo activeNetwork = manager.getActiveNetworkInfo(); if (activeNetwork != null && activeNetwork.getType() == networkType) { return true; } } } catch (Exception e) { return false; } return false; } } |
https://partnerjun.tistory.com/42 에 Jsoup 설명이 잘 되어 있는 편이다.
PHP 를 활용한 파싱 코드는 https://link2me.tistory.com/1604 참조하라.
'안드로이드 > Android 파싱' 카테고리의 다른 글
경기버스 도착정보 조회 파싱 예제 (0) | 2018.10.05 |
---|---|
[안드로이드 스튜디오] Gson 라이브러리 사용 비교 (0) | 2017.11.13 |
안드로이드 XMLPullParser (0) | 2017.05.21 |
[안드로이드 스튜디오] 내부 XML 파싱 - 2 (0) | 2017.05.21 |
[안드로이드 스튜디오] 내부 XML 파싱 - 1 (0) | 2017.05.21 |