Working with System Permissions
네이버 D2
http://d2.naver.com/home
Android의 HTTP 클라이언트 라이브러리
사용자가 보는 화면 개발을 제외한다면 HTTP 클라이언트가 애플리케이션 개발의 중심이라고도 할 만하다.
Android 환경에서 HTTP 클라이언트를 개발하는 방식은 다양하다. Android SDK에서 제공하는 기능을 직접 사용하기도 하고, 이를 좀 더 편하게 사용하도록 도와주는 유틸리티 클래스를 프로젝트마다 개발하기도 한다. 오픈 소스 라이브러리를 활용한 애플리케이션도 있다.
SDK에서 제공하는 HTTP 클라이언트의 허점과 변경 사항
Android는 표준 JRE의 클래스와 동일한 형태인 HTTPURLConnection 클래스를 제공한다.
그리고 오픈 소스로 유명한 Apache HttpComponents의 HttpClient도 SDK에 포함되어 있다. (6.0부터 x)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public class NaverBookSearchService { //요청을 하기 위한 ID와 SECRET private static final String CLIENT_ID = ""; private static final String CLIENT_SECRET = ""; //요청할 URL private static final String URL ="https://openapi.naver.com/v1/search/book.xml"; //한번의 요청에서 받아올 아이템 갯수 private static final int DISPLAY_ITEM_COUNT = 10; //현재 페이지를 알기 위한 상태값 private int currentSkip = 1; //검색할 키워드 private String keyword; public NaverBookSearchService(String keyword) { this.keyword = keyword; } public void nextPage() { currentSkip += DISPLAY_ITEM_COUNT; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | public List<Book> search(){ List<Book> list = null; try { URL url; url = new URL(URL + "?query=" + URLEncoder.encode(keyword, "UTF-8") + "&display=" + DISPLAY_ITEM_COUNT + "&start="+ currentSkip); URLConnection urlConn = url.openConnection(); urlConn.setRequestProperty("X-Naver-Client-Id", CLIENT_ID); urlConn.setRequestProperty("X-Naver-Client-Secret", CLIENT_SECRET); XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser parser = factory.newPullParser(); parser.setInput( new InputStreamReader(urlConn.getInputStream())); int eventType = parser.getEventType(); Book b = null; while (eventType != XmlPullParser.END_DOCUMENT) { switch (eventType) { case XmlPullParser.END_DOCUMENT: // 문서의 끝 break; case XmlPullParser.START_DOCUMENT: list = new ArrayList<Book>(); break; case XmlPullParser.END_TAG: { String tag = parser.getName(); if(tag.equals("item")) { list.add(b); b = null; } } case XmlPullParser.START_TAG: { String tag = parser.getName(); switch (tag) { case "item": b = new Book(); break; case "title": if(b != null) b.setTitle(parser.nextText()); break; case "link": if(b != null) b.setLink(parser.nextText()); break; case "image": if(b != null) b.setImage(parser.nextText()); break; case "author": if(b != null) b.setAuthor(parser.nextText()); break; case "price": if(b != null) b.setPrice(parser.nextText()); break; case "discount": if(b != null) b.setDiscount(parser.nextText()); break; case "publisher": if(b != null) b.setPublisher(parser.nextText()); break; case "pubdate": if(b != null) b.setPubdate(parser.nextText()); break; case "isbn": if(b != null) b.setIsbn(parser.nextText()); break; case "description": if(b != null) b.setDescription(parser.nextText()); break; } } } eventType = parser.next(); } } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (XmlPullParserException e) { // TODO Auto-generated catch block e.printStackTrace(); } return list; } | cs |
1 2 | NaverBookSearchService service = new NaverBookSearchService(keyword); service.search(); | cs |
search메소드는 네트워크 통신을 사용하기 때문에 UI쓰레드에서 직접 호출할 수 없음, 파생쓰레드를 만들어서 호출해야 하고 파생쓰레드가 얻어낸 데이터를 UI쓰레드로 가져오려면 UI(메인)쓰레드의 핸들러가 필요하다.
UI(메인)쓰레드는 파생쓰레드가 받아온 데이터를 전달 받았을 때 UI에 반영하는 코드를 Handler클래스를 상속받아 handleMessage에 구현, 파생쓰레드는 네트워크 통신을 통해 얻은 데이터를 UI쓰레드에게 전달해주기 위해서 UI(메인)쓰레드의 Handler객체에 대한 참조 필요
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); //what이 1이면 NaverBookSearchThread가 보내는 데이터 인걸로 if(msg.what == 1) { //arg1이 100이면 처음 검색에 대한 결과를 갖다 준걸로 if(msg.arg1 == 10) { String result = ""; List<Book> data = (List<Book>)msg.obj; for(Book b : data) result += b + "\n"; Toast.makeText(MainActivity.this, result, 0).show(); } //arg1이 20이면 검색했던 결과에 대해 추가 아이템을 요청한걸로 else if(msg.arg1 == 20) { } } } }; | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public class NaverBookSerachThread extends Thread{ private NaverBookSearchService service; private Handler handler; public NaverBookSerachThread(NaverBookSearchService service, Handler handler) { this.service = service; this.handler = handler; } @Override public void run() { // TODO Auto-generated method stub super.run(); //service의 search메소드를 수행하고 결과를 핸들러를 통해 메인에게 전달 List<Book> data = service.search(); } } | cs |
1 2 3 4 5 | public int getCurrentSkip(){ return currentSkip; //nextPage함수가 한번이상 불려서 currentSkip이 1이 아니면 //처음 검색이 아니고 아이템 추가 } | c s |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public void run() { // TODO Auto-generated method stub super.run(); //service의 search메소드를 수행하고 결과를 핸들러를 통해 메인에게 전달 List<Book> data = service.search(); Message msg = handler.obtainMessage(); msg.what = 1; msg.obj = data; if(service.getCurrentSkip() == 1) msg.arg1 = 10; else //첫 검색인지 아닌지 구분 msg.arg1 = 20; handler.sendMessage(msg); } | cs |
1 2 3 4 5 6 7 8 9 10 | public void onClick(View v) { // TODO Auto-generated method stub String keyword = keywordEdt.getText().toString(); NaverBookSearchService service = new NaverBookSearchService(keyword); // service.search(); NaverBookSerachThread thread = new NaverBookSerachThread(service, handler); thread.start(); } }); | cs |
리스트뷰 작성
getView할일
1. 껍데기 인플레이션하기(convertView가 null이 아니면 재사용 가능)
2. 껍데기 내부의 위젯들 객체 얻어오기 (findViewByid)
3. 각 위젯에 데이터 바인딩하기
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | public class BookAdapter extends ArrayAdapter<Book>{ private Context context; private int resource; private List<Book> bookList; public BookAdapter(Context context, int resource, List<Book> bookList) { super(context, resource, bookList); this.context = context; this.resource = resource; this.bookList = bookList; } static class BookViewHolder{ public ImageView imageView; public TextView titleTv; public TextView priceNpub; public TextView authorNpubDate; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub // return super.getView(position, convertView, parent); //getView메소드는 리스트뷰의 한줄의 아이템을 그리기 위한 뷰를 만들어내는 함수이고 //한줄의 아이템에 대해서 UI를 인플레이션하고 그 객체를 리턴하면됨 BookViewHolder holder; if(convertView == null) { //이미 인플레이션 한 뷰가 있다면 매개변수 convertView에 들어와 재사용 가능하닌까 //convertView가 null일때만 인플레이션 해줌 LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.list_item, parent, false); //처음 인플레이션 될 때 홀더객체를 만들어서 홀더 셋트의 위젯 참조변수들에 findViewById holder = new BookViewHolder(); holder.imageView = (ImageView) convertView.findViewById(R.id.list_img); holder.titleTv = (TextView) convertView.findViewById(R.id.list_tv_title); holder.priceNpub = (TextView) convertView.findViewById(R.id.list_tv_price_and_publisher); holder.authorNpubDate = (TextView) convertView.findViewById(R.id.list_tv_author_and_pubdate); //holder객체는 각 위젯들의 findViewById한 결과들 집합이다. convertView.setTag(holder); } else { holder = (BookViewHolder) convertView.getTag(); } Book book = bookList.get(position); //여기까지 이제 홀더객체 안의 각 위젯에 book객체의 각 멤버변수값들이랑 바인딩하면 된다. holder.imageView.setImageResource(R.drawable.ic_launcher); holder.titleTv.setText(book.getTitle()); holder.priceNpub.setText(book.getPrice() +"원\t출판사 : "+book.getPublisher()); holder.authorNpubDate.setText("저자 : "+ book.getAuthor() + "\t출판일 : " + book.getPubdate()); return convertView; } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class MainActivity extends Activity { private EditText keywordEdt; private Button searchBtn; private ListView listView; private BookAdapter adapter; private List<Book> bookList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); keywordEdt = (EditText) findViewById(R.id.main_edt_search); searchBtn = (Button) findViewById(R.id.main_btn_search); listView = (ListView) findViewById(R.id.main_listView); bookList = new ArrayList<Book>(); adapter = new BookAdapter(this, R.layout.list_item,bookList); listView.setAdapter(adapter); | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); //what이 1이면 NaverBookSearchThread가 보내는 데이터 인걸로 if(msg.what == 1) { //arg1이 10이면 처음 검색에 대한 결과를 갖다 준걸로 if(msg.arg1 == 10) { // String result = ""; // List<Book> data = (List<Book>)msg.obj; // for(Book b : data) // result += b.getTitle() + "\n"; // Toast.makeText(MainActivity.this, result, 0).show(); bookList.clear(); bookList.addAll((List<Book>) msg.obj); adapter.notifyDataSetChanged(); } //arg1이 20이면 검색했던 결과에 대해 추가 아이템을 요청한걸로 else if(msg.arg1 == 20) { } } } }; | cs |
' IOT 기반 응용 SW과정 > Android, Arduino' 카테고리의 다른 글
Day103 (0) | 2016.08.17 |
---|---|
Day102 안드로이드 (0) | 2016.08.11 |
Day99 안드로이드 파일 복사 (0) | 2016.08.08 |
Day98_2 안드로이드 OpenHelper (0) | 2016.08.05 |
Day98 안드로이드 db Select문 (0) | 2016.08.05 |