오늘 할 것은 유저가 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 |