ping을 통해서 네트워크 연결 상태 체크하기 - 안드로이드 소스 코드에서


Runtime runTime = Runtime.getRuntime();


String host = "192.168.0.13";

String cmd = "ping -c 1 -W 10 "+host; //-c 1은 반복 횟수를 1번만 날린다는 뜻

Process proc = null;


try {

proc = runTime.exec(cmd);

} catch(IOException ie){

Log.d("runtime.exec()", ie.getMessage());

}


try {

proc.waitFor();

} catch(InterruptedException ie){

Log.d("proc.waitFor", ie.getMessage());

}


//여기서 반환되는 ping 테스트의 결과 값은 0, 1, 2 중 하나이다.

// 0 : 성공, 1 : fail, 2 : error이다.

int result = proc.exitValue();


if (result == 0) {

Log.d("ping test 결과", "네트워크 연결 상태 양호");

} else {

Log.d("ping test 결과", "연결되어 있지 않습니다.");

}



※ ping 명령어 옵션들


-4, -6 Force IPv4 or IPv6 hostname resolution

-c CNT Send only CNT pings

-s SIZE Send SIZE data bytes in packets (default=56)

-I iface/IP Use interface or IP address as source

-W timeout Seconds to wait for the first response (default:10)

                (after all -c CNT packets are sent)

-w deadline Seconds until ping exits (default:infinite)

                (can exit earlier with -c CNT)

-q               Quiet, only displays output at start and when finished


안드로이드의 기반이 리눅스이기 때문에 DOS에서의 ping 명령어 옵션과는 약간의 차이가 있다.


-c 옵션은 ping을 날릴 횟수이다.

-W 옵션은 ping을 날린 이후 리턴 결과를 기다릴 timeout 시간 값이다. 연결 상태가 끊겼거나 연결 상태가 좋지 않을때 이 대기 시간 동안 응답이 없으면 연결 실패로 간주한다.


위의 옵션들은 대소문자를 구분한다.

따라서 ping -C xxx.xxx.x.x는 잘못된 사용법이다.







안드로이드 앱에서 구글, 네이버, 다음의 검색 기능을 이용한 웹 검색하는 기능은 Intent를 이용해서 구현할 수 있다.


Intent의 action 가운데 Intent.ACTION_WEB_SEARCH가 이 기능을 안드로이드 시스템에 요청하는 action이다.

이 action을 Intent에 담아서 startActivity로 날리면 안드로이드 시스템은 웹 search를 위한 동작을 수행하게 된다.

기본적으로는 구글 검색을 수행하지만 만일 디바이스(폰)에 네이버 앱이나, 다음 앱이 설치되어 있다면 이들 셋 중에서 선택하는 창이 뜨고 이 창에서 구글, 네이버, 다음의 검색 기능을 이용해서 특정 웹 검색을 수행할 수 있다.




이때 검색할 단어(내용)을 설정하는 것은 Intent의 extra에 담아서 수행하면 된다.

이때 putExtra에 사용할 key를 안드로이드 시스템에서 미리 설정해 두고 있다. 

그것이 SearchManager.QUERY라는 key값이다.

구글(네이버, 다음...)의 웹 검색 창에서 무엇을 검색할지를 안드로이드 시스템에게

알리는데 key 값이다.


Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);

intent.putExtra(SearchManager.QUERY, "검색할 단어");


if (intent.resolveActivity(getPackageManager()) != null) {

     startActivity(intent);

} else {

     String msg = "Sorry, there is no web browser available"; 

     Toast.makeText(this, msg, Toast.LENGTH_LONG).show();

}


Context 클래스의 메소드인 getPackgaeManager() 메소드는 다음과 같다.


public abstract PackageManager getPackageManager () 

⇒ Return PackageManager instance to find global package information.


디바이스에 있는 전 패키지 정보를 획득하기 위한 PackageManger 객체를 반환해 주는 메소드이다.


public ComponentName resolveActivity (PackageManager pm) : Intent 클래스의 메소드

⇒ Return the Activity component that should be used to handle this intent. 


resolveActivity() 메소드는 Intent를 수행할 Activity를 반환한다. 만일 수행할 Activity가 없으면 null을 반환한다.

이럴때 startActivity()를 수행하면 앱이 강제종료를 먹게된다.


그런데 아래 코드의 경우 웹 검색할 앱(Activity)가 구글, 네이버, 다음이 폰에 설치되어 있다면

아래 코드에서는 com.android.internal.app.ResolverActivity가 반환이 된다.

ResolverActivity는 안드로이드 API reference에서 search를 해도 보이지 않는다.

통상적인 클래스들은 API reference에서 search를 하면 자동완성 기능으로 제시가 되는데

ResolverActivity는 표시가 안된다. 

결론적으로 ResolverActivity는 여러개의 Activity가 Intent에 매칭될때 이를 관리하는

클래스이다.




현재 시간을 24시간제로 표시하고자 한다면 android.text.format.DateFormat라는 클래스를 이요하면 된다.

이 클래스가 제공하는 메소드 중에서 다음 메소드가 이 기능을 제공한다.


public static CharSequence format (CharSequence inFormat, long  inTimeInMillis)


첫 번째 매개인자 inFormat에 사용되는 형식은 아래 표의 규칙대로 하면된다

(http://developer.android.com/reference/java/text/SimpleDateFormat.html 참조)


SymbolMeaningKindExample
Dday in year(Number)189
Eday of week(Text)E/EE/EEE:Tue, EEEE:Tuesday, EEEEE:T
Fday of week in month(Number)(2nd Wed in July)
Gera designator(Text)AD
Hhour in day (0-23)(Number)0
Khour in am/pm (0-11)(Number)0
Lstand-alone month(Text)L:1 LL:01 LLL:Jan LLLL:January LLLLL:J
Mmonth in year(Text)M:1 MM:01 MMM:Jan MMMM:January MMMMM:J
Sfractional seconds(Number)978
Wweek in month(Number)2
Ztime zone (RFC 822)(Time Zone)Z/ZZ/ZZZ:-0800 ZZZZ:GMT-08:00 ZZZZZ:-08:00
aam/pm marker(Text)PM
cstand-alone day of week(Text)c/cc/ccc:Tue, cccc:Tuesday, ccccc:T
dday in month(Number)10
hhour in am/pm (1-12)(Number)12
khour in day (1-24)(Number)24
mminute in hour(Number)30
ssecond in minute(Number)55
wweek in year(Number)27
yyear(Number)yy:10 y/yyy/yyyy:2010
ztime zone(Time Zone)z/zz/zzz:PST zzzz:Pacific Standard Time
'escape for text(Delimiter)'Date=':Date=
''single quote(Literal)'o''clock':o'clock

예를들면


MM : 11, 10과 같이 월 표시를 두 자리 숫자로 표현

MMM : Nov, Oct...와 같이 월 표시를 영문 약어로. 

          한글 폰에서는 그냥 '월'이라는 글자로 표시


MMMM : November, October...와 같이 월 표시를 영문 full name으로 표시


yyyy-MM-dd h:mm => 2013-11-25 3:25


yyyy-MM-dd h:mm a => 2013-11-25 3:25 pm


yyyy-MM-dd k:mm => 2013-11-25 15:25 (24시간제로 표시)



예제 소스는...


String crrTime = System.currentTimeMillis().toString();

String now = DateFormat.format("yyyy MMM dd k:mm", crrTime);

        

TextView txt = (TextView)findViewById(R.id.txt);

txt.setText(now);


여기서 DateFormat은 자바의 DateFormat(

java.text.DateFormat)이 아니라 안드로이드의 DateFormat이다. 

클래스 이름이 동일한 DateFormat은 자바에도 있고 안드로이드에도 있다.


android.text.format.DateFormat;





TextView txt = (TextView)findViewById(R.id.txt);

txt.setLinksClickable(true);

txt.setMovementMethod(LinkMovementMethod.getInstance());

String urlNaver = "<a href='http://www.naver.com'>네 이 버</a><br>";

String urlGoogle = "<a href='http://www.google.com'>구 글</a>";


txt.setText(Html.fromHtml(urlNaver));

txt.append(Html.fromHtml(urlGoogle));





안드로이드 SQLite에 대해서 주의해야 할 사항


SQLiteOpenHelp 클래스의 두 abastract 메소드인 onCreate()와 onUpgrade()가 호출되는 시점에 대해서 주의해야 할, 그리고 알아야 할 사항이 있다.

여기서 MyDB는 SQLiteOpenHelper 클래스를 상속받은 클래스라고 할 경우

(class MyDB extends SQLiteOpenHelper)


 MyDB dbHelp = new MyDB(this);

  ⇒ 이 단계에서는 SQLiteOpenHelper를 상속 받은 MyDB의 생성자만 호출이
      되고 MyDB의 onCreate()는 아직 호출이 안된다.


      SQLiteDatabase db = dbHelp.getReadableDatabase() 혹은  
      dbHelp.getWritableDatabase()가 호출 될 때 비로소

      MyDB의 onCreate()가 호출되서 테이블이 생성이 된다. 


      getReadableDatabase()하는 시점에서 테이블이 없으면

      테이블이 새롭게 생성이 되고 기존 존재하면 그것을 Radable이나 Writable 중
      하나로 open한다.


 MyDB의 onUpgrade()가 호출되는 시점

  ⇒ super(context,"Test.db", null, 2); 의 맨 마지막 인자인 DB의
      version 값이 상향 조정될 때 호출된다.





아래와 같은 에러를 만나면 원인은 쓰레드 안에 쓰레드를 사용하였기 때문에 

오류가 발생하였다.


java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()


해결 방법은 쓰레드 안에 Handler를 새로 선언하여 사용하면 된다.


View.OnClickListener clickSomeThing = new View.OnClickListener(){

@Override

public void onClick(View v){

Handler mHandler = new Handler(Looper.getMainLooper());

mHandler.postDelayed(new Runnable(){

@Override

public void run() {

doSomeMethod(); //쓰레드 안에서 실행되는 쓰레드

}, 0);

}

};



EditText로 입력을 받을 때 숫자만 입력 받고 문자가 포함되었을 경우 다시 
입력받도록 하기위한 간단한 코드이다.


xml layout이 다음과 같을 경우 
inputType="number"로하면 오직 양의 정수만 입력 가능하다. 
키보드에 특수 문자나 +, -, 소수점이 표시되더라도 오직 양의 정수만 입력
가능하다.

그리고 maxLength="4"로하면 4개의 숫자만 입력이 가능하다.
xml layout 파일을 아래와 같이 설정함을 통해서 숫자만 입력되도록 할수 있다.

    <EditText 
        android:id="@+id/editPhoneNum"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/txtPhoneNum"
        android:inputType="number"
        android:maxLength="4"
        android:textSize="40sp"/>

xml layout을 이용하거나 혹은 소스 상에서 체크할려면 다음과 같이 하는 방법도 
가능하다.

EditText editPhone = (EditText)findViewById(R.id.editPhoneNum);
try {
String str = editPhone.getText().toString().trim();

//아래 str에 숫자만 있을 경우는 NumberFormatException이 
                //발생치 않으나 숫자 이외의 어떤 문자가 포함되면 
                //NumberFormatException이 발생한다.
//따라서 이 Exception이 발생하면 숫자 이외의 값이 입력되었다고 
                //판단하고 재 입력 받도록 처리하면된다.

int rt = Integer.parseInt(str);
Toast.makeText(this, "RT : "+rt, 1).show();
} catch(NumberFormatException e){
Toast.makeText(this, "숫자만 입력하세요", 1).show();
}

한 마디로

Integer.parseInt()를 이용하되 NumberFormatException을 이용해서 
처리할 수 있다.


Context에 대한 이해

  • Context를 이해하는 걸 다들 어려워 한다. 질문글에 답을 달다가 갑자기 정리가 깔끔하게 되서....

    하나의 application이 실행되기 위해서는 그 밑바탕에 깔려져야 하는 많은 정보들과 환경들이 필요하다. 
    그 정보들과 환경들을 안드로이드 시스템이 제공해 준다.
    application 실행을 위해 밑바탕에 깔려져 있는 정보들과 환경들을 Context라 한다.
    따라서 이 Context에는 안드로이 시스템이 제공해주는 유용한 많은 정보들이 있다.
    따라서 이 Context를 통해서 안드로이드 시스템이 제공해주는 많은 유용한 정보들을 
    꺼집어 낼수 있다(getSystemService() 메소드로).

    근데 Context를 필요로하는 곳에 Activity 객체인 this를 념길수 있는 이유는  
    Activity가  Context를 상속 받았기 때문에 Activity는 Context의 모든 정보를 가지고 있는 것이이다. 
    그래서 Context를 필요로 하는 곳에서 Activity의 객체를 넘길수 있는 것이다.

    Context를 얻을 수 있는 몇 가지 방법
    -. Activity 객체를 통해서. Activity 객체 자체가 Context이기도 하기 때문에 Context를   
       필요로하는 곳에 Activity 객체인 this를 사용하면 된다.
    -. View의 객체가 있으면 View의 getContext()를 통해서. View의 객체가 없는 상황이면 
       View v = new View(activity.this);로 만들면된다. 이때 View를 전역적으로 선언하면
       된다.
    -. Context 클래스의 getApplicationContext()를 통해서
    이정도면 Context를 못 구할 일이 별로 없을 것이다.



+ Recent posts