오늘 할 것은 유저가 URL을 입력했을때 사이트 메타데이터를 얻어와서 표시하는 작업이다.
아래처럼 유튜브 URL을 입력하면 저렇게 간단한 사진과, 내용이 보인다.

시작하기 전에...
Jsoup 라이브러리를 이용할것이니 build.gradle에implementation 'org.jsoup:jsoup:1.11.1'
한 줄을 추가!
1. Validator.java : URL 검사 클래스 만들기
URL 파싱에 앞서서 URL이 진짜 맞는 URL인지 검사하는 클래스인 Validator를 만든다.
Validator.isUrl()를 하면 URL이 맞는지 간단히 검사할 수 있다.
public class Validator { public static boolean isUrl(String text) { Pattern p = Pattern.compile("^(?:https?:\\/\\/)?(?:www\\.)?[a-zA-Z0-9./]+$"); Matcher m = p.matcher(text); if (m.matches()) return true; URL u = null; try { u = new URL(text); } catch (MalformedURLException e) { return false; } try { u.toURI(); } catch (URISyntaxException e) { return false; } return true; } }
2. Util.java : 텍스트에서 대표 URL을 추출하는 메소드와, URL에서 메타데이터를 추출하는 메소드를 가진 클래스
- 첫번째 extractUrlFromText에서는 일반 텍스트에서 대표 URL 하나 추출해낸다."안녕하세요 여기는https://naver.com에서 긁어왔어요 [https://google.com](https://google.com)ㅋㅋ"
라는 문자가 있다면 첫번째로 등장하는 유효한 URL인 https://naver.com
만을 반환한다.
- 두번째 getMetadataFromUrl에서는 웹에서 meta-data를 가져올 수 있도록 한다.
자세히보면 meta[property=og:title]
이라는 부분이있는데, 자신이가져올 항목을 정확히 알려면, 웹브라우저의 개발자도구로 가서 <head>
태그를 자세히 살펴보면 된다. 네이버의 경우 아래와 같다. Metadata는 내가 임의로 생성한 간단한 객체다.

public class Util { // URL에서 메타데이터를 추출하는 메소드 public static Metadata getMetadataFromUrl(String url) { try { Metadata metadata = new Metadata(); metadata.url = url; Document doc = Jsoup.connect(url).get(); metadata.title = doc.select("meta[property=og:title]").first().attr("content"); metadata.description = doc.select("meta[property=og:description]").get(0).attr("content"); metadata.imageUrl = doc.select("meta[property=og:image]").get(0).attr("content"); return metadata; } catch (Exception e) { e.printStackTrace(); return null; } } // 텍스트에서 대표 URL을 추출하는 메소드 public static String extractUrlFromText(String text) { String urlRegex = "((https?|ftp|gopher|telnet|file):((//)|(\\\\))+[\\w\\d:#@%/;$()~_?\\+-=\\\\\\.&]*)"; Pattern pattern = Pattern.compile(urlRegex, Pattern.CASE_INSENSITIVE); Matcher urlMatcher = pattern.matcher(text); ArrayList<String> urls = new ArrayList<>(); while (urlMatcher.find()) { urls.add(text.substring(urlMatcher.start(0), urlMatcher.end(0))); } String resultUrl = null; for (String url : urls) { if (Validator.isUrl(url)) { resultUrl = url; break; } } return resultUrl; } }
3. EditText 글자가 바뀔때마다 체크하고 URL이 있다면 저장 해두고, 메타데이터 정보를 가져와서 보여준다!
public class WritePungActivity extends AppCompatActivity { private String url; // metadata를 가져올 url private EditText etComment; protected void onCreate(...) { TextWatcher textWatcher = new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // 텍스트 변경시 URL이 있는지 체크 checkUrl(); } @Override public void afterTextChanged(Editable s) { } }; etComment.addTextChangedListener(textWatcher); } private void checkUrl() { String content = etComment.getText().toString(); url = Util.extractUrlFromText(content); if (url != null) { Metadata metadata = Util.getMetadataFromUrl(url); // TODO: 메타데이터를 가져왔으니 여기에 메타데이터를 보여주는 뷰 보이게! } } }
-
NetworkOnMainThreadException 에러를 피하기 위해서는?
public class MetadataTask extends AsyncTask<String, Metadata, Metadata> { private final PostAdapter.ViewHolder holder; public MetadataTask(PostAdapter.ViewHolder holder) { this.holder = holder; } @Override protected Metadata doInBackground(String... params) { return Util.getMetadataFromUrl(params[0]); } @Override protected void onPostExecute(Metadata metadata) { super.onPostExecute(metadata); // TODO ... 가져온 메타데이터로 뭘 할지 적어주면됨 Glide.with(context).load(metadata.imageUrl).into(holder.ivMetadataImage); holder.tvMetadataTitle.setText(metadata.shorten(metadata.title)); holder.tvMetadataUrl.setText(metadata.shorten(metadata.url)); holder.rlMetadata.setVisibility(View.VISIBLE); } }
'프로그래밍 > Android' 카테고리의 다른 글
안드로이드 Admob 종료 및 뒤로가기시 전면광고 추가하기 (6) | 2019.04.24 |
---|---|
안드로이드 인트로(스플래시) 화면을 만들어보자 (0) | 2019.04.24 |
[안드로이드] 이메일 인텐트 보내기 (Intent ACTION_SEND Email) (2) | 2019.03.25 |
[안드로이드] Admob 광고 게재가 중단: GOOGLE PLAY 삭제 해결방법 (1) | 2019.03.25 |
Fresco 이미지 wrap_content로 로딩하는 법 (0) | 2019.03.10 |