Wearable Device에서 adb logcat을 확인하기 위해서는 shell에 다음 명령어를 입력하자. 

간단하게 설명하면 하나의 host를 만들고, 그 host에 wearable을 붙여서 logcat을 확인하는 내용이다. 


adb connect localhost:4444 
adb forward tcp:4444 localabstract:/adb-hub 
adb -s localhost:4444 logcat


앞서 사용하는 방법을 설명했고, 이제는 실전이다. 

무한도전의 회차 정보를 가져오는 내용을 해보았고, 페이지에서 전체 내가 원하는 회차 프로그램 정보를 가져오는 방법을 설명하겠다. 


일단 무한도전의 회차 정보를 가져오기 위해서 확인해본 결과 아래와 같은 구조를 가지고 있었다.










<div class="brcs_thumb"> .... </div>는 이미지의 URL을 담고 있었고,

<div class="brcs_detail" id="brcs_detail"> ... </div> 에는 회차정보인 택스트 정보를 담고 있었다. 


안에를 자세하게 살펴보면




소스코드 


Elements image = doc.select("div.brcs_thumb");
for (Element e : image) {
	// System.out.println(e);
	for (Element k : e.children()) {
		// System.out.println(k);
		for (Element y : k.children()) {
//			System.out.println(y);
			Elements i = y.getElementsByTag("img");
			for (Element j : i) {
				System.out.println(j.data() +", " + j.tag() +", " +j.attributes()+ ", " + j.attr("src"));
				System.out.println(j.attr("src"));
			}
		}
	}
}







이 부분에서는 <img src의 내용이 필요했고, 무한도전 이미지





소스코드 


Elements contents = doc.select("dl.nomar");

for (Element e : contents) {
	Elements children = e.children();

	Elements k = e.select("dt.dss_h_episode_intro dd a href");
	for (Element e2 : k) {
		System.out.println("child " + e2.tagName() + ", " + e2.className() + ", " + e2.text());
	}

	for (Element e1 : children) {
		Elements links = e1.getElementsByTag("a");
		for (Element link : links) {
			String linkHref = link.attr("href");
			String linkText = link.text();
			// https://search.naver.com/search.naver
			System.out.println(linkHref + ", " + linkText);
		}
		System.out.println("child " + e1.tagName() + ", " + e1.className() + ", " + e1.text());
	}
	System.out.println(e.tagName() + ", " + e.className() + ", " + e.text());
}




public class Application {
	public static void main(String[] args) throws IOException {

		String url = "https://search.naver.com/search.naver?sm=tab_hty.top&where=nexearch&ie=utf8&query=무한도전+20160423";
		Document doc = Jsoup.connect(url)
				.header("content-type", "multipart/form-data; boundary=---011000010111000001101001")
				.header("authorization", "Basic ZmJfMTY2MTUzMDc0NzQ2MTk5NDox").header("cache-control", "no-cache")
				.get();
		
		// thumb image 가져오기
		Elements brcsThumbElements = doc.select("div.brcs_thumb");
		// System.out.println(brcsThumbElements);
		System.out.println(brcsThumbElements.select("a").get(0).getElementsByTag("img").attr("src"));

		// broadcast info 가져오기
		Elements brcsDetailElements = doc.select("div.brcs_detail");
		// System.out.println(brcsDetailElements);
		Elements dlNomarElements = brcsDetailElements.select("dl.nomar");
		Elements infoElements = dlNomarElements.get(0).children();
		ArrayList infos = new ArrayList<>();
		String[] row = new String[2];
		for (Element infoElement : infoElements) {
			if (infoElement.tagName().equals("dt")) {
				row = new String[2];
				row[0] = infoElement.text();
			} else if (infoElement.tagName().equals("dd")) {
				row[1] = infoElement.text();
				infos.add(row);
			}
		}
		for (String[] r : infos) {
			System.out.println(r[0] + " : " + r[1]);
		}
	}
}












  1. 2017.07.01 17:17

    비밀댓글입니다

  2. 2017.07.02 21:46

    비밀댓글입니다


들어가며


  웹페이지에서 내가 필요한 부분을 가져오고 싶을 경우가 있다. 예를 들면 날씨 정보나, 주식정보 등이 될 수 있다. 이번 포스팅에서는 Java의 라이브러리인 jsoup을 이용해 웹페이지 파싱하는 방법에 대해서 설명한다. 


Jsoup

공식 홈페이지 주소 [바로가기] 


Document doc = Jsoup.connect("http://en.wikipedia.org/").get();
Elements newsHeadlines = doc.select("#mp-itn b a");


예제 코드를 보기 위해서는 coobook을 참고하면 된다. [바로가기]


웹페이지

  예를 들어서 네이버에 있는 사이트 일부분을 가져오는 코드를 설명해 보겠다. 아래 검색 결과에서 '무한도전 - 477회 이전희' 의 색칠한 내용을 가져오는 코드입니다. 






페이지 소스보기

  페이지 소스를 보면 아래와 같다. 무한도전 477회는 <div class='title_bar'>의 HTML 태그로 묶여있는 것을 볼 수 있습니다. 




소스코드

  <div class='title_bar'>의 내용을 가져오면 되기 때문에, select를 이용해서 가져오시면 됩니다. 자세한 함수 내용은 사이트를 확인하시면 됩니다. 거의 대부분 웹페이지 가져오는 Jsoup.connect(url)과 해당 페이지에서 내가 원하는 태그내용을 가져오는 select를 사용하기 때문에 아래 내용만 알아도 충분히 가져올 수 있습니다. 여기서 div.title_bar라고 표현하는 이유는 .은 class를 나타내고 있기 때문엡니다. div class --> div.  (class=.)로 표현한다고 생각하시면 쉽습니다. 그 외에도 div id --> div# (id=#)으로 표현합니다. 


String url = "https://search.naver.com/search.naver?sm=tab_hty.top&where=nexearch&ie=utf8&query=무한도전+20160423";
Document doc = Jsoup.connect(url)
		.header("content-type", "multipart/form-data; boundary=---011000010111000001101001")
		.header("authorization", "Basic ZmJfMTY2MTUzMDc0NzQ2MTk5NDox").header("cache-control", "no-cache")
		.get();

Elements title = doc.select("div.title_bar");
for (Element e : title) {
	System.out.println(e.text());
}









  1. 대학생 2017.05.08 10:06

    출력문이 안드로이드가 아니라 JAVA로 되어있는데
    안드로이드에서 텍스트뷰나 리스트뷰등으로 띄울때는 어떻게하는지에 대해서 궁금하네요

    • 2017.05.08 13:55

      비밀댓글입니다

    • 대학생 2017.05.11 04:46

      비로그인 상태로 단 댓글이라..
      비밀댓글 다신것을 확인할수가 없네요...

    • 쌍쌍바나나 2017.05.11 09:21 신고

      화면에 출력하려면, View를 만들고 .setText 하면 되겠네요^^

  2. 보신소탕 2017.08.18 13:29

    예제 잘 봤습니다. 도움이 많이 됐어요! 한가지 궁굼한게 있는데 질문 해도 될까요?
    예제에서 보면 div.title_bar의 내용을 가져오셨는데 꼭 이렇게 해야만 원하는 결과를 얻어낼 수 있나요? 그 밑에 class인 title padr3의 내용을 빼와도 똑같은 결과일 것 같은 생각이 들어서요. 이렇게 하는 특별한 이유가 있는지 궁굼해서 여쭤봅니다! 감사합니다

  3. Bemore 2018.02.09 01:44

    좋은 글 감사합니다

    jsoup를 이용해서 사이트 크롤링은 잘되는데요

    디시인사이드라는 곳에 게시판을 긁어오고 싶은데 jsoup로 안되더라고요

    같은 코드로는 다른 사이트 게시판은 전부 다 되는데 유독 디시인사이드 게시판만 크롤링이 안됩니다

    디시인사이드 메인페이지는 또 되는데 게시판만 안되네요

    이럴경우 어떻게 접근을 해야될까요?

    저는 안드로이드에서 jsoup를 긁어오려합니다

    • 2018.02.09 10:03

      비밀댓글입니다

  4. 원신 2019.01.09 12:29

    안녕하세요. 해당 글에서 크롤링하여 긁어오면 결과값이 무한도전 477회 가 되는건가요?
    그거 textview로 띄우고싶은데 가능 한가요..?

    • 쌍쌍바나나 2019.01.16 10:04 신고

      네네 가능합니다~ 데이터값 받아오고 파싱해서 textview에 셋하면 가능해요!

안드로이드를 하면서 mp3파일을 열거나, image파일을 기존에 설치되어 있는 앱들 중에서 선택해서 열고 싶을때가 있다. 




구현하기


File videoFile2Play = new File("/sdcard/banana.mpeg");
Intent i = new Intent();
i.setAction(android.content.Intent.ACTION_VIEW);
i.setDataAndType(Uri.fromFile(videoFile2Play), "video/mpeg");
startActivity(i);
File musicFile2Play = new File("/sdcard/banana.mp3");
Intent i2 = new Intent();
i2.setAction(android.content.Intent.ACTION_VIEW);
i2.setDataAndType(Uri.fromFile(musicFile2Play), "audio/mp3");
startActivity(i2);

만약 video 모든 확장자의 파일을 사용하기 위해서는 (video/*)


File videoFile2Play2 = new File("/sdcard/nice_movie2.mp4");
i.setDataAndType(Uri.fromFile(videoFile2Play2), "video/*");
startActivity(i);


[참고] 파일 타입과 그에 대한 MIME Type을 나타낸 테이블 


Extension

MIME Type

Android Application

.apkapplication/vnd.android.package-archive

Text

.txttext/plain

.csv

text/csv
.xmltext/xml

Web related

.htmtext/html
.htmltext/html
.phptext/php

Image

.pngimage/png
.gifimage/gif
.jpgimage/jpg
.jpegimage/jpeg
.bmpimage/bmp

Audio

.mp3audio/mp3
.wavaudio/wav
.oggaudio/x-ogg
.midaudio/mid
.midiaudio/midi
.amraudio/AMR

Video

.mpegvideo/mpeg
.3gpvideo/3gpp

Package

.jarapplication/java-archive
.zipapplication/zip
.rarapplication/x-rar-compressed
.gzapplication/gzip


안드로이드에서 파일 삭제하는 소스코드

일단 Manifest에 파일 읽는 권한 추가하고 아래와 같이 구현하면 된다.


 
 File f = File(filePath);
 if (f.delete()) {
     Log.i("banana", "file remove = " + f.getName() + ", 삭제 성공");
 } else {
     Log.i("banana", "file remove = " + f.getName() + ", 삭제 실패");
 } 


들어가며

안드로이드 ListActivity에 Download폴더 내부에 있는 파일의 리스트를 보여주는 예제 입니다.


Manifest에 파일 읽는 권한을 추가합니다.

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>


구현하기


public class FileList extends ListActivity 
{
private File file;
private List myList;

public void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);

    myList = new ArrayList();   

    String rootSD = Environment.getExternalStorageDirectory().toString();
    file = new File( rootSD + "/Download" ) ;       
    File list[] = file.listFiles();

    for( int i=0; i<list.length; i++)
    {
            myList.add( list[i].getName() );
    }

    setListAdapter(new ArrayAdapter(this,
            android.R.layout.simple_list_item_1, myList ));

}

protected void onListItemClick(ListView l, View v, int position, long id) 
{
    super.onListItemClick(l, v, position, id);

    File temp_file = new File( file, myList.get( position ) );  

    if( !temp_file.isFile())        
    {
        file = new File( file, myList.get( position ));
        File list[] = file.listFiles();

        myList.clear();

        for( int i=0; i< list.length; i++)
        {
            myList.add( list[i].getName() );
        }
        Toast.makeText(getApplicationContext(), file.toString(), Toast.LENGTH_LONG).show(); 
        setListAdapter(new ArrayAdapter(this,
                android.R.layout.simple_list_item_1, myList ));

    }

}


@Override
public void onBackPressed() {
            String parent = file.getParent().toString();
            file = new File( parent ) ;         
            File list[] = file.listFiles();

            myList.clear();

            for( int i=0; i< list.length; i++)
            {
                myList.add( list[i].getName() );
            }
            Toast.makeText(getApplicationContext(), parent,          Toast.LENGTH_LONG).show(); 
            setListAdapter(new ArrayAdapter(this,
                    android.R.layout.simple_list_item_1, myList ));


    }
}


  1. 힐냥 2017.03.21 00:23

    simple_list_item_1에는 무슨 내용이 들어 있나요??

    • 2017.03.21 19:57

      비밀댓글입니다

  2. yjjang 2018.04.20 04:00

    혹시 <.디렉토리명> 과 같은 숨김 폴터도 리스트로 가져올 수 있을까요?

들어가며

  안드로이드 코딩을 하다보면, 전체 화면을 사용하고 싶을 때가 있다. 전체 화면을 사용하기 위해서는 상태바(Status Bar)와 액션바(Action Bar)를 숨기면 가능하다. 상태바 에 대해서 설명을 하면, 현재 노티, 시간, 배터리 레벨 등 현재 상태를 나타내는 바(bar)이다.  항상 우리에게 스마트폰의 현재 상태를 알려주고 있는 참 고마운 bar 이다. 뭔가... 바라고 쓰니까 어색하다. 액션바는 해당 앱의 이름이나, 버튼을 넣는데 사용한다.  그렇다면 게임, 미디어 재생시에는 상태바, 액션바를 볼 필요도 없고, 보고 싶지도 않다 나를 방해하는 요소가 있으면 집중을 떨어뜨리지... 자 그렇다면 현재 상태바, 액션바를 제거하려면 어떻게 해야할까?

구현하기

상태바를 제거하기 위해서는 버전에 따라 맞게 구현을 해줘야 한다. 
안드로이드 4.0을 포함한 그 아래의 버전에서는 아래와 같이 구현한다.

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // If the Android version is lower than Jellybean, use this call to hide
        // the status bar.
        if (Build.VERSION.SDK_INT < 16) {
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                    WindowManager.LayoutParams.FLAG_FULLSCREEN);
        }
        setContentView(R.layout.activity_main);
    }
    ...
}


안드로이드 4.1을 포함한 그 이상의 버전에서는 아래와 같이 구현한다.

View decorView = getWindow().getDecorView();
// Hide the status bar.
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
// Remember that you should never show the action bar if the
// status bar is hidden, so hide that too if necessary.
ActionBar actionBar = getActionBar();
actionBar.hide();

* 만약 actionBar가 Null Exception이 발생하면 getSupportActionBar()를 사용하면 된다.


실행결과


[그림 1] 상태바, 액션바가 포함 된 화면

[그림 2] 전체화면 사용하기 - 상태바, 액션바가 제거된 화면

[참고 사이트]
http://developer.android.com/intl/ko/training/system-ui/status.html#41

  1. 개발꿈나무 2017.04.25 12:32

    좋은 지식 얻어갑니다. 감사합니다.

들어가며

  HTTP는 Server와 통신하는데 가장 modern한 방식 중 하나이다. 서버에 GET, POST, PUT, DELETE 요청을 통해 데이터를 주고 받는 방법에 대해서 설명한다. 오픈 소스인 OkHttp를 설치하고, HTTP요청 방법에 대해서 설명하겠습니다.

설치하기

  설치하는 방법은 총 3가지이다. jar파일 다운 또는 Maven, Gradle 추가이다.

  • v3.2.0 Jar [다운로드]
  • Gradle
    compile 'com.squareup.okhttp3:okhttp:3.2.0'
  • Maven
      com.squareup.okhttp3
      okhttp
      3.2.0
    
    

GET

package okhttp3.guide;
import java.io.IOException;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class GetExample {
  OkHttpClient client = new OkHttpClient();

  String run(String url) throws IOException {
    Request request = new Request.Builder()
        .url(url)
        .build();

    Response response = client.newCall(request).execute();
    return response.body().string();
  }

  public static void main(String[] args) throws IOException {
    GetExample example = new GetExample();
    String response = example.run("https://raw.github.com/square/okhttp/master/README.md");
    System.out.println(response);
  }
}

POST, PUT, DELETE

Request의 객체를 만들때 post를 put, delete로 변경하면 POST, PUT, DELETE 요청을 할 수 있다.
package okhttp3.guide;

import java.io.IOException;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class PostExample {
  public static final MediaType JSON
      = MediaType.parse("application/json; charset=utf-8");

  OkHttpClient client = new OkHttpClient();

  String post(String url, String json) throws IOException {
    RequestBody body = RequestBody.create(JSON, json);
    Request request = new Request.Builder()
        .url(url)
        .post(body)
        .build();
    Response response = client.newCall(request).execute();
    return response.body().string();
  }

  String bowlingJson(String player1, String player2) {
    return "{'winCondition':'HIGH_SCORE',"
        + "'name':'Bowling',"
        + "'round':4,"
        + "'lastSaved':1367702411696,"
        + "'dateStarted':1367702378785,"
        + "'players':["
        + "{'name':'" + player1 + "','history':[10,8,6,7,8],'color':-13388315,'total':39},"
        + "{'name':'" + player2 + "','history':[6,10,5,10,10],'color':-48060,'total':41}"
        + "]}";
  }

  public static void main(String[] args) throws IOException {
    PostExample example = new PostExample();
    String json = example.bowlingJson("Jesse", "Jake");
    String response = example.post("http://www.roundsapp.com/post", json);
    System.out.println(response);
  }
}


[참고] http://square.github.io/okhttp/




들어가며

  안드로이드에서 코딩을 하다보면 앱이 종료되도 값을 저장해 유지해야 할때가 많습니다. 만약 앞으로 설명해야 할 SharedPreference가 없다면, 파일입출력을 통해서 데이터를 저장을 해야하는 번거로움이 있습니다. 파일 입출력 없이 간단한 데이터를 Key, Value로 저장할 수 있다면 쓰기/읽기가 수월할 것입니다. 사용 예로는 안드로이드에서 Setting값을 항상 내가 설정한 값으로 유지해야하는 경우가 있는데, 이때 SharedPreference를 사용하면 문제를 쉽게 해결 할 수 있습니다. 하지만 앱을 제거 후 새로 설치되면 SharedPreference의 값은 초기화가 됩니다.

사용방법

  SharedPreferences는 안드로이드에서 제공하고 있습니다. Context를 통해서 값을 가져올 수 있습니다. 만약에 Activity에서 한다면 바로 getSharedPreferences를 통해서 가져올 수 있습니다. 첫번째 파라미터는 SharedPreference 의 이름을 정해줍니다. 이름은 파일 입출력에서는 파일 이름이라고 생각하면 쉽습니다. 두번째는 Mode를 설정할 수 있습니다.

Mode는 총 3가지를 지원합니다.

  • MODE_PRIVATE
  • MODE_WORLD_READABLE
  • MODE_WORLD_WRITEABLE
  Mode는 접근 권한이라고 생각하시면 됩니다. PRIVATE은 해당 앱에서만 접근을 가능하게 해주고, 나머지 WORLD의 Keyword가 속해 있는 MODE는 다른 앱에서 접근이 가능합니다. 만약 다른 앱에서 sharedPreference의 값을 쓰고, 읽는다면 보안상에 문제가 있을 수도 있으니 잘 선택해서 사용하시면 됩니다.

  SharedPreference를 쓰기/읽기를 할때마다 아래 예제 코드를 작성하면 코드의 중복이 많기 때문에, 저같은 경우에는 PreferenceHelper.java를 생성해서 쓰기/읽기를 관리하는 클래스를 만들어서 사용합니다. 참고해서 사용하세요.

쓰기

SharedPreferences prefs = context.getSharedPreferences("PrefName", context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(token, text);
editor.commit();

읽기

SharedPreferences prefs = context.getSharedPreferences("PrefName", context.MODE_PRIVATE);
String text = prefs.getString(token, "") 


들어가며

프로젝트 IDE로 IntelliJ를 사용하는 개발자들은 많을 것이다. 

갑자기 'cannot resolve symbol'  이라는 에러와 함께 import가 되지 않는 현상이 나왔습니다.  


'File size exceeds configured limit' 의 에러는 코드 사이즈가 제한을 초과했다는 말을 나타냅니다. 
저 같은 경우에는 Google Protobuf에서 자동으로 생성되는 코드의 용량이 너무 커서 생겼습니다.  

해결방법

문제를 해결하기 위해서는 android-studio/bin/idea.properties에 
idea.max.intellisense.filesize=25000로 수정하면 된다. (default는 2500)

+ Recent posts