2014년 10월 25일 토요일

디아블로 전정실 안드로이드앱으로 html 파싱해서 보자(영웅들 목록)어플제작

영웅들 목록과 영웅들 얼굴들을 나타낼 차례입니다.
해야 할 것들을 정리해 보자면 다음과 같습니다.

1. Network으로 접속해서 영웅 목록 html 가져오기
2. Network으로 접속할때 캐쉬 사용하기(캐쉬에 있다면 접속하지 않기)
3. 영웅들을 파싱해서 List 에 보여주기 (Custom list 사용)
4. 영웅들 이미지를 List에 추가하기(영웅 이미지도 캐쉬 사용하기)
5. refresh 구현(캐쉬 지우는 조건)(이건 이번에 작업하지 않았습니다.)

이전 내용보다는 많지 않습니다.
완성된 모습입니다.


thread를 이용하여 network 접속하는 소스 입니다.

Thread nthread = new Thread(new Runnable() {
     public void run() {
      try {
       heroInfo = obj_itemDetails.getFromNetwork(context);
       if( heroInfo != null ) {
        dialog.dismiss();
        startActivity(intent);
       }else{
        dialog.dismiss();
           AlertDialog.Builder alt_bld = new AlertDialog.Builder(context);
           alt_bld.setMessage("Net work error").setCancelable(false).setNeutralButton("OK",
               new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                   dialog.cancel();
               }
               });
           AlertDialog alert = alt_bld.create();
           // Title for AlertDialog
           //alert.setTitle("Title");
           // Icon for AlertDialog
           //alert.setIcon(R.drawable.icon);
           alert.show();
       }
      } catch (Throwable ex) {
       ex.printStackTrace();
       Log.d(TAG,"ERROR"+ex);
      }
     }
    });


핵심 소스는 getFromNetwork(context); 입니다. 저장하는 위치는 context.getCacheDir()함수로 정합니다. 이렇게 하면 /data/data/패키지명/cache 폴더 위치를 얻을 수 있습니다.
모든 처리가 제대로 된다면 영웅들 데이터가 들어있는 arraylist를 반환합니다.
career로 정보가 있는 html을 읽어 heroInfo.executeGetHeros()함수를 호출하면 영웅들의 목록이 올라오게되고 영웅 목록으로 부터 heros.get(i).executeGetHero(hdata); 함수를 호출하여 영웅의 이미지 및 하드코어 여부 레벨등을 가져오게 됩니다.

 public HeroInfo getFromNetwork(Context context) {
  // career 붙어있는 경로는 전체 목록을 획득할때 사용한다.
  String url = getProfileURL()+"/career";
  // 캐쉬경로를 저장 경로로 설정한다.
  String career = context.getCacheDir()+"/"+getProfileStr()+Utils.getMD5String(url)+"career.html";
  // 캐쉬에 저장된 파일이 있는지 검사 없으면 읽어옴
  Log.d(TAG,"savename:"+career);
  if( !Utils.checkFileExists(career) ){
   
   GetHttp html = new GetHttp();
   // 네트워크 에러 처리
   if( html.execute(url) ){
    Utils.fileWriteByte(career, html.getByte());
   } else {
    return null;
   }
  }
  String data = Utils.readFile(career);
  if( data == null ) return null;
  HeroInfo heroInfo;
  heroInfo = new HeroInfo(data);
  heroInfo.executeGetHeros();
  
  ArrayList<Hero> heros = heroInfo.getHeros();
  if( heros.size() == 0 ) {
   return null;
  }

  for(int i=0 ; i < heros.size() ; i++ ) {
   ///d3/ko/profile/donarts-3994/hero/30559318
   String hurl = getProfileURL()+"/hero/"+heros.get(i).getId();
   String hinfo = context.getCacheDir()+"/"+getProfileStr()+Utils.getMD5String(hurl)+"hero.html";
   Log.d(TAG,"strt:"+hurl);
   if( !Utils.checkFileExists(hinfo) ){
    GetHttp html = new GetHttp();
    // 네트워크 에러 처리
    if( html.execute(hurl) ){
     Utils.fileWriteByte(hinfo, html.getByte());
    } else {
     return null;
    }
   }
   String hdata = Utils.readFile(hinfo);
   if( hdata == null ) return null;
   // 하나의 hero 정보만을 가져온다. png 위치 및 정확한 class 등등
   heros.get(i).executeGetHero(hdata);
   
   // 이후 구한 png 경로로 부터 다시 네트워크 처리를 한다
   String furl = heros.get(i).getFaceURL();
   String finfo = context.getCacheDir()+"/"+"common_"+Utils.getMD5String(furl)+".png";
   heros.get(i).setFaceLocalPath(finfo);
   
   if( !Utils.checkFileExists(finfo) ){
    GetHttp html = new GetHttp();
    // 네트워크 에러 처리
    if( html.execute(furl) ){
     Utils.fileWriteByte(finfo, html.getByte());
    } else {
     return null;
    }
   }
  }
  return heroInfo;
 }

heros.get(i).executeGetHero(hdata);의 특징은 StringTokenizer의 두번째 인자가 조금씩 바뀐다는 것입니다. 이것은 html 데이터를 보고 어떤값을 가져올지 봐서 적당한 값으로 설정합니다.

public void executeGetHero(String data) {
  // TODO Auto-generated method stub
  StringTokenizer st = new StringTokenizer(data," \t\r\n,'=[{}];()<>\"");
  boolean getd = false;
  while(st.hasMoreTokens()){
   String temp = st.nextToken();
   if(temp!=null && !temp.isEmpty() && temp.equals("class")){
    temp = st.nextToken();
    //System.out.println("["+temp+"]");
    if(temp!=null && !temp.isEmpty() && temp.equals("paragon-level")){
     // Get paragon-level
     temp = st.nextToken();
     this.setParagonLevel(Integer.parseInt(temp)); 
     //System.out.println(" "+temp);
     temp = st.nextToken();
     if(temp!=null && !temp.isEmpty() && temp.equals("/span")){
      temp = st.nextToken();
      if(temp!=null && !temp.isEmpty() && temp.equals("/strong")){
       // Get local class
       temp = st.nextToken();
       setLocalCls(temp);
       //System.out.println(" "+temp);
       while(st.hasMoreTokens()){
        temp = st.nextToken();
        if(temp!=null && !temp.isEmpty() && temp.equals("/a")){
         break;
        } else if(temp!=null && !temp.isEmpty() && temp.equals("d3-color-hardcore")){
         setHardCore(true);
         break;
        }
       }
      }
     }
    }
   }else if(temp!=null && !temp.isEmpty() && temp.equals("og:image") && !getd ){
    temp = st.nextToken();
    //System.out.println("1 "+temp);
    if(temp!=null && !temp.isEmpty() && temp.equals("content")){
     // Get Image
     temp = st.nextToken();
     //System.out.println("2 "+temp);
     getd = true;
     setFaceURL(temp);
    }
   }
  }
 }

작업소스

댓글 없음:

댓글 쓰기