회사는 정말 싫어욧

JTBC의 RSS 서비스 링크

http://news.jtbc.joins.com/Etc/RssService.aspx


<RSS 서비스 메인>


<속보 RSS xml>


Jsoup을 이용해 rss 서비스 주소와 이름을 가져오고 이걸로 안드로이드에 Tab layout(탭)으로 만든다

원하는 메뉴(속보, 정치, 경제, 사회, 국제, 문화, 연예, 스포츠, 풀영상, 뉴스랭킹, 뉴스룸, 아침&, 뉴스현장, 정치부회의)를 누르면

해당 서비스 주소에 나오는 뉴스를 ListView(리스트)로 보여준다


실행 결과 화면




프로젝트 파일 구조



[XML 파일]


1. activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".MainActivity">

<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/appbar_padding_top"
android:theme="@style/AppTheme.AppBarOverlay">

<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_weight="1"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppTheme.PopupOverlay"
app:title="@string/app_name">

</android.support.v7.widget.Toolbar>

<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.design.widget.AppBarLayout>

<android.support.v4.view.ViewPager
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</android.support.design.widget.CoordinatorLayout>

2. fragment_jtbc.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
tools:context=".JTBCFragment">

<ListView
android:id="@+id/NewsList"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>

</FrameLayout>

3. news_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>

<TextView
android:id="@+id/titleTV"
android:layout_alignParentLeft="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:textSize="10pt"
android:text="뉴스 제목"/>

<TextView
android:id="@+id/dateTV"
android:layout_alignParentRight="true"
android:layout_alignBottom="@+id/titleTV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="10dp"
android:textSize="6pt"
android:text="뉴스 날짜"/>


</RelativeLayout>
<TextView
android:id="@+id/descTV"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="25dp"
android:textSize="8pt"
android:text="뉴스 간략 설명"/>

<View
android:layout_width="match_parent"
android:layout_height="3dp"
android:layout_gravity="center"
android:background="#cad8e6"/>

</LinearLayout>

[JAVA 파일]

코드만 붙여넣기 할 경우 맨 위에 package로 시작하는 한줄만 남겨놓고 그 밑에 내용 전체를 이 코드로 변경해준다


1. MainActivity

import android.os.AsyncTask;
import android.support.design.widget.TabLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;

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.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
private ViewPager mViewPager;
private TabLayout tabLayout;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

mViewPager = (ViewPager) findViewById(R.id.container);
tabLayout = (TabLayout) findViewById(R.id.tabs);

tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);

//어플이 실행되면 RSS서비스 메인 주소에 접근한다
String rssURL = "http://news.jtbc.joins.com/Etc/RssService.aspx";
new CategoryTask().execute(rssURL);

}


class CategoryTask extends AsyncTask<String,Void,Void> {
List<Category> categories; //읽어온 데이터를 리스트로 저장

//실제 CategoryTask의 주요 작업
@Override
protected Void doInBackground(String... strings) {
String rssURL = strings[0];

try {
Document document = Jsoup.connect(rssURL).get();
Elements elements = document.select("table.common_table tbody tr");
Category category;

//한줄씩 가져와서 Category에 저장
for (Element element : elements) {
//title
category = new Category();
category.setTitle(element.select("th").get(0).text());
category.setUrl(element.select("a").get(0).text());

//한줄을 다 읽었으면 categories에 다시 보관
categories.add(category);
}

Log.d("목록 다 읽었는지 찍어볼게요",categories.toString());
} catch (IOException e) {
e.printStackTrace();
}

return null;
}

//가장 먼저 실행
@Override
protected void onPreExecute() {
super.onPreExecute();

categories = new ArrayList<>();
}

//doInBackground가 끝나면 실행
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);

//Category 개수만큼 반복
for (Category c : categories) {
tabLayout.addTab(tabLayout.newTab());
}

TabPagerAdapter adapter = new TabPagerAdapter
(getSupportFragmentManager(),tabLayout.getTabCount(),categories);

mViewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(mViewPager);


}
}

}

2. Category

public class Category {
private String title;
private String url;

//Getter&Setter 추가
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getUrl() { return url; }
public void setUrl(String url) { this.url = url; }

//toString 추가(생략 가능)
@Override
public String toString() { return title+": "+url; }
}


3. TabPagerAdapter

import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;

import java.util.List;

public class TabPagerAdapter extends FragmentStatePagerAdapter {
private int tabCount;
private List<Category> categories;

public TabPagerAdapter(FragmentManager fm, int tabCount, List<Category> categories) {
super(fm);
this.tabCount = tabCount;
this.categories = categories;
}

@Override
public Fragment getItem(int position) {
Category category = categories.get(position);
Fragment fragment = JTBCFragment.newInstance(category.getTitle(),category.getUrl());
return fragment;
}

@Override
public int getCount() {
return tabCount;
}

@Nullable
@Override
public CharSequence getPageTitle(int position) {
return categories.get(position).getTitle();
}
}

4. JTBCFragment

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;

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;
import java.util.List;

public class JTBCFragment extends Fragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private String mParam1;
private String mParam2;

private ListView listView;

public JTBCFragment() {
}

public static JTBCFragment newInstance(String param1, String param2) {
JTBCFragment fragment = new JTBCFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);

return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {

View view = inflater.inflate(R.layout.fragment_jtbc, container, false);

listView = view.findViewById(R.id.NewsList);

new NewsTask().execute();

return view;


}

class NewsTask extends AsyncTask<Void,Void,Void>{
List<NewsDTO> newsList;

@Override
protected Void doInBackground(Void... voids) {

try {
Document document = Jsoup.connect(mParam2).get();
Elements elements = document.select("item");
for (Element element : elements) {
NewsDTO data = new NewsDTO();

Elements e = element.select("title");
if (e != null && e.size()>0)
data.setTitle(e.get(0).text());

e = element.select("link");
if (e != null && e.size()>0)
data.setLink(e.get(0).text());

e = element.select("description");
if (e != null && e.size()>0)
data.setDescription(e.get(0).text());

e = element.select("pubDate");
if (e != null && e.size()>0)
data.setPubDate(e.get(0).text());

newsList.add(data);
}
Log.d("뉴스 다 읽었는지 찍어볼게요",newsList.toString());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

@Override
protected void onPreExecute() {
super.onPreExecute();
newsList = new ArrayList<>();
}

@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
NewsAdapter adapter = new NewsAdapter(getContext(),newsList);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(newsList.get(position).getLink()));
startActivity(intent);
}
});
}


}

}

5. NewsDTO

public class NewsDTO {
private String title;
private String link;
private String description;
private String pubDate;

public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getLink() { return link; }
public void setLink(String link) { this.link = link; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public String getPubDate() { return pubDate; }
public void setPubDate(String pubDate) { this.pubDate = pubDate; }

@Override
public String toString() {
return "뉴스제목" + title + " " + pubDate + " 발행일";
}
}


6. NewsView

import android.content.Context;
import android.view.LayoutInflater;
import android.widget.LinearLayout;
import android.widget.TextView;

public class NewsView extends LinearLayout {
//뉴스 1개 보여질 xml에서 사용하는 요소
TextView titleTV, dateTV, descTV;


public NewsView(Context context, NewsDTO data) {
super(context);

LayoutInflater inflater = (LayoutInflater) context.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.news_item,this,true);

titleTV = findViewById(R.id.titleTV);
dateTV = findViewById(R.id.dateTV);
descTV = findViewById(R.id.descTV);

setNews(data);


}

public void setNews(NewsDTO data) {
//titleTV 세팅
if(data.getTitle()!=null && data.getTitle().trim().length()>0)
titleTV.setText(data.getTitle());
else
titleTV.setText("");

//dateTV 세팅
if(data.getPubDate()!=null && data.getPubDate().trim().length()>0)
dateTV.setText(data.getPubDate());
else
dateTV.setText("");

//descTV 세팅
if(data.getDescription()!=null && data.getDescription().trim().length()>0)
descTV.setText(data.getDescription());
else
descTV.setText("");
}
}


7. NewsAdapter

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

import java.util.List;

public class NewsAdapter extends BaseAdapter {
private Context context;
private List<NewsDTO> list;

public NewsAdapter(Context context, List<NewsDTO> list) {
this.context = context;
this.list = list;
}

@Override
public int getCount() {
return list.size();
}

@Override
public Object getItem(int position) {
return list.get(position);
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
NewsDTO data = list.get(position);
NewsView view = null;

//이전에 만들어 놓은 View가 없으면
if (convertView == null) {
//NewsView모양으로 새로 만들고
view = new NewsView(context, data);

//이전에 만들어 놓은 View가 있으면
} else {
//만들어놨던 View(convertView)를 재활용해서 내용만 바꾼다
view = (NewsView) convertView;
view.setNews(data);
}
return view;
}
}