안드로이드 개발 질문/답변
(글 수 45,052)
제가 YouTube 어플처럼 실행하면 리스트뷰로 동영상들을 띄워주고
리스트뷰를 누르면 해당 YouTube 동영상 재생해주고 또 검색 가능한 어플을 구현하려고 하는데
여기저기 정보를 검색하던중 네이버 개발카페에서 어떤분이 gdata말고 데이터를 파싱해서 구현하신 소스가 있더라구요
소스를 실행해서 좀 참고좀 하려고 하는데 실행이 안되네요 왜 안될까요??
얘기치 않게 중단되었다고 뜨는데요 기본소스와 XML 첨부합니다
Source package com.google.YouTube;
import android.app.Activity; import android.app.ListActivity; import android.net.Uri; import android.os.Bundle;
import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List;
import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException;
import android.util.Xml; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup;
import android.content.Context; import android.content.Intent; import android.webkit.WebView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView;
public class YouTube extends ListActivity // 이부분은 ListActivity { /** Called when the activity is first created. */ private HttpClient mClient; private HttpGet mGetMethod; List<String> title = new ArrayList<String>(); // 리스트를 만들기 위한 준비 List<String> thumbnailUrl = new ArrayList<String>(); // 썸네일 URL 들을 순서대로 저장하기 위한 객체 List<String> userId = new ArrayList<String>(); // 동영상을 올린이의 ID 를 순서대로 저장 List<String> videoUrl = new ArrayList<String>(); // 재생을 위한 동영상 URL 을 순서대로 저장 List<String> description = new ArrayList<String>(); // 올린이가 동영상에 대한 설명글을 저장 List<String> Duration = new ArrayList<String>(); // 재생 시간을 순서대로 저장
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); GetYoutubeData(); CMyArrayAdapter aa = new CMyArrayAdapter(this, title); // 리스트에 들어갈 각 row 를 꾸미기 위한 adapter 객체 setListAdapter(aa); // 리스트에 adapter 객체를 적용한다. }
private void GetYoutubeData() { String keyword = "검색할 내용"; String encodeKeyword = ""; // EditText01 try { encodeKeyword = URLEncoder.encode(keyword, "UTF-8"); // 위의 keyword 를 유튜브로 보내기 위해 utf-8 로 인코딩 } catch (UnsupportedEncodingException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } // YouTube String uri = "http://gdata.youtube.com/feeds/api/videos?vq=" + encodeKeyword; // 인코딩한 검색어 결합 mClient = new DefaultHttpClient(); mGetMethod = new HttpGet(); HttpResponse resp = null; try { // Request mGetMethod.setURI(new URI(uri)); // 유튜브에 검색을 요청하기 위한 URI 준비 } catch (URISyntaxException e) { // TODO e.printStackTrace(); } try { // METHOD GET Request resp = mClient.execute(mGetMethod); // 유튜브로 검색을 요청(request) } catch (ClientProtocolException e) { // TODO catch e.printStackTrace(); } catch (IOException e) { // TODO e.printStackTrace(); } // Request if (resp.getStatusLine().getStatusCode() == 200) { try { InputStream is = resp.getEntity().getContent(); // 검색결과를 받아옴 try { GetYouTubeEntries(is); // 받아온 결과 파싱 (기능 밑에서 설명) } catch (XmlPullParserException e) { // TODO Auto-generated catch block e.printStackTrace(); } is.close();
} catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } private void GetYouTubeEntries(InputStream is) throws XmlPullParserException, IOException { String nameSpace = null; String parserName = null; // XML 문서에서 각 부분들의 이름 String value; // XML 문서에서 각 부분들의 값 Integer depth = 0; XmlPullParser parser = Xml.newPullParser(); parser.setInput(new InputStreamReader(is)); // boolean bThumbnail = false; String szTempTitle = null; String szOrigTitle = null; for (int e = parser.getEventType(); e != parser.END_DOCUMENT; e = parser.next()) { depth = parser.getDepth(); // xml 문서에서 뎁스 가져옴 switch(e) { case XmlPullParser.START_TAG: // START_TAG 부분일 경우 parserName = parser.getName(); if (depth == 4) { if (parserName == "thumbnail") // 썸네일이 나왔네요. 이 썸네일은 동영상 한개당 3~4장 정도 있습니다. 때문
// 에 썸네일을 최초 1장만 저장하고 나머지는 무시하는것이 필요합니다. { if(szTempTitle != szOrigTitle) // 최초의 썸네일만 저장하고, 동영상의 타이틀이 바뀌지 않으면 즉 같은 동영상
// 이라면 썸네일을 저장하지 않고 넘어갑니다. { szTempTitle = szOrigTitle; // 이 안에 들어왔다면 최초의 썸네일이란 뜻이므로 이 두 변수를 같게합니다. String url = parser.getAttributeValue(nameSpace, "url"); // 썸네일 주소를 받아서 thumbnailUrl.add(url); // 썸네일 List 에 저장합니다. } } else if (parserName == "player") { String url = parser.getAttributeValue(nameSpace, "url"); // 동영상주소 videoUrl.add(url); } else if (parserName == "duration") { String duration = parser.getAttributeValue(nameSpace, "seconds"); // 동영상시간 Duration.add(duration); } } break; case XmlPullParser.TEXT: // XML 에서 동영상 정보 가 아닌 텍스트 부분들 value = null; value = parser.getText(); if (depth == 3) { // if (parserName == "published") // 잘 모르겠네요;; // {
// int a = 0; // } // else if (parserName == "updated") // 올라간 날짜 // { // int a = 0; // } if (parserName == "title") // 동영상 제목 { szOrigTitle = value; title.add(value); } // else if (parserName == "content") // 컨텐츠의 종류 예: 영화, 드라마 등 // { // //entry.setContent(value); // int a = 0; // } // else if (parserName == "recorded") // 누가 녹화 했는가 뭐 그런것 이었던듯 // { // int a = 0; // //entry.setRecorded(value); // } } else if (depth == 4) { if (parserName == "name") // 게시자 ID { userId.add(value); } else if (parserName == "uri") // 유져에 대한 정보를 보여주는 uri 별 필요 없습니다 { int a = 0; } // else if (parserName == "category") // 카테고리 분류 // { // int a = 0; // //mediaCategory.setValue(value); // } else if (parserName == "description") // 글 내용 { description.add(value); } // else if (parserName == "keywords") // 동영상의 키워드 // { // int a = 0; // //media.setKeywords(value); // }
} break; case XmlPullParser.END_TAG: parserName = parser.getName(); if (parserName.equals("entry")) { //retEntries.add(entry); } break; } } }
private class CMyArrayAdapter extends ArrayAdapter<Object> { Context context; CMyArrayAdapter(Context context, List titles) // 클래스의 생성자 { super(context, R.layout.row, titles); // 어뎁터를 row.xml 레이아웃으로 지정하고, titles 의 리스트가 끝날때
// 까지 리스트를 구성하게 됩니다. this.context = context; } @Override public View getView(int position, View convertView, ViewGroup parent) // 리스트를 한개한개 만들때마다 자동으로 호 { // 출되는 getView 입니다. 각 row의 안을
// 채운다고 생각하시면 됩니다. LayoutInflater inflater = ((Activity)context).getLayoutInflater(); View row = (View)inflater.inflate(R.layout.row, null); TextView titleView = (TextView)row.findViewById(R.id.title); // 타이틀 textview 객체 TextView durationView = (TextView)row.findViewById(R.id.duration); // 시간 textview 객체 WebView thumbnailView = (WebView)row.findViewById(R.id.thumbnail); // 섬네일 webview 객체 thumbnailView.setFocusable(false); // 주의!! 안드로이드의 버그로, ListView 안에 클릭 가능한 객체 (예:버튼, 웹뷰)
// 가 있으면 ListView 를 클릭했을때 호출되는 onListItemClick 이 호출되지 않습니다. 그래서 webView 의 focusable 을
// false 로 만들어 주어야 합니다. 웃기는건 레이아웃 에서 설정해도 소용이 없고, 반드시 코드상에서 위처럼 해야 합니다.
// 참고하세요.
String szThumbnailUrl = (String)thumbnailUrl.get(position); // position 에 리스트의 인덱스가 있습니다. String szTitle = (String)title.get(position); String szDuration = (String)Duration.get(position); int nDuration = Integer.parseInt(szDuration); if(nDuration > 60) // duration 이 초단위 만 있으므로 분과 초로 나눠줍니다. { int nMinute = nDuration/60; int nSecond = nDuration%60; szDuration = nMinute+"분 "+nSecond+"초"; } else { szDuration = nDuration+"초"; } titleView.setText(szTitle); // 이제 타이틀뷰에 타이틀 을 넣고 durationView.setText(szDuration); // 시간을 넣고 thumbnailView.loadUrl("szThumbnailUrl); // 웹뷰 썸네일을 넣으면 끝~~ return row; } }
}
main XML
<?xml version="1.0" encoding="utf-8"?> <LinearLayout android:id="@+id/LinearLayout01" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <ListView android:id="@id/android:list" android:layout_width="fill_parent" android:layout_height="fill_parent"/> <TextView android:id="@id/android:empty" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="No Item" />
</LinearLayout>
row XML
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="80px" android:orientation="horizontal"> <WebView android:id="@+id/thumbnail" android:layout_width="120px" android:layout_height="90px" android:layout_gravity="center_vertical" android:scrollbars="none"
android:clickable="false"
android:focusable="false"> </WebView> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <TextView android:id="@+id/title" android:layout_width="fill_parent" android:layout_height="55px" android:textSize="14px"
android:layout_marginLeft="10px"
android:layout_marginTop="10px"
android:clickable="false"
android:focusable="false"> </TextView> <TextView android:id="@+id/duration" android:layout_width="fill_parent" android:layout_height="15px" android:textSize="10px"
android:gravity="right"
android:layout_marginRight="20px"
android:clickable="false"
android:focusable="false"> </TextView> </LinearLayout> </LinearLayout>