Android/기본스킬 | Posted by 덩치 2013. 12. 31. 11:19

핸들러(Handler) 사용하기

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO


기본적이지만 아주 중요한 Handler

주로 Thread와 함께 사용된다.

안드로이드는 Thread 내에서 UI작업이 불가능하다.

 만약 Thread 내에서 UI작업을 하게되면

CalledFromWrongThreadException 예외가 발생하게된다.

이를 해결하기 위해 핸들러를 이용해 다른 스레드에서 UI에 직접 접근하지 않고

핸들러를 거쳐 접근하여 UI작업을 처리해야한다.


두가지 사용법을 알아보자

1. post로 호출하여 사용하기

Handler handle = new Handler();
public Runnable callback = new Runnable() {
public void run() {
// 실행
}
};

호출하는법은
스래드 내에서 callback 안의 내용을 실행하고싶을 때 
handle.post(callback);
딜레이를 주고싶을 때는 handle.postDelayed(callback, 1000); (1초 뒤 실행)


2. message를 보내 호출하기

Handler handle = new Handler() {

public void handleMessage(Message msg) {

if (msg.waht==0x0001) {


}

else if (msg.what==1) {


}

}

};


호출은 handle.sendEmptyMessage(0x0001);  등으로 한다.

Android/기본스킬 | Posted by 덩치 2013. 12. 31. 10:33

자바/안드로이드 HashMap 사용법

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO

HashMap은 Map인터페이스의 한 종류로, key와 value 한 쌍을 데이터로 가진다.

쉽게 이해하려면 리스트 형태에 값을 키와 벨류로 가지고 있다고 생각하면 된다.

리스트와의 큰 차이점은 위에처럼 키값을 가진다는것이고, 또 순서를 보장하지 않는다는점이다.

순서대로 입,출력이 되고 순서에 의해 자료를 처리하는 작업에는 알맞지 않다.

입력된 key값을 이용해 value를 구하며(리스트에서 인덱스를 이용해 벨류를 구하는 이치)

key값은 중복되지 않으며 value는 중복 가능하다.


즉, key값으로 1을 5번 입력한다면 맨 처음의 key,value만 입력되고 나머지는 입력되지 않아

이 특성을 잘 이용하면 중복검사를 매우 편하게 할 수 있다.


HashMap의 기본적인 사용법을 알아보겠다.


HashMap<Integer, String> map = new HashMap<Integer, String>();


입력 -

map.put(1, "치킨");

map.put(2, "피자");

map.put(3, "탕수육");


출력 -

Iterator<Integer> iter = map.keySet().iterator();

while(iter.hasNext()) {

int key = iter.next();

String value = map.get(key);

Log.d("fureun", "key : " + key + ", value : " + value);

}

이렇게 하면 모든 키와 벨류 쌍이 다 출력된다.


다른 사용법으로는 map.get(1);을 하면 키 1에 대응하는 value "치킨"이 반환된다.


if(map.containsKey(1)) {


}

이렇게 하면 키값 1이 존재할 경우 true가 반환된다.


이외에도 활용법은 엄청 많으니, 공부를 통해 자신이 원하는 형태로 사용 할 수 있도록 노력하자.


Android/기본스킬 | Posted by 덩치 2013. 12. 30. 10:54

토스트(Toast) 메시지 띄우는법

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO

토스트메시지



이미지에 보이는 "토스트메시지입니다." 라는 문구가 적힌 저 네모난 박스가 토스트메시지이다.


주로 사용자에게 정보를 알려주는 용도로 사용되며, 잠시 나타났다 사라지기 때문에


직접적인 입력을 받지 않았을때 띄워주면 사용자가 보지 못할 가능성이 있어 


상황에 맞게 잘 사용하여야한다.


소스코드는 단 한줄로 매우 간단하다.


구성은 Toast.makeText (Context context, CharSequence text, int duration).show();


예제는 Toast.makeText(getApplicationContext(), "토스트메시지입니다.", int duration).show();

int duration에는 Toast.LENGTH_SHORT와 Toast.LENGTH_LONG가 있으며

SHORT는 2초, LONG는 4초간 출력한다.

직접 int값을 넣을 경우 밀리세컨드로 적용된다. (1000= 1초)


Android/구글맵 v2 | Posted by 덩치 2013. 12. 27. 16:38

구글맵(GoogleMap) v2 띄우기 (최신)

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO

작성일에 직접 만들어가면서 포스팅한것이기 때문에,

작성일 기준으로 가장 최신 자료입니다.


1. 맵 표시를 위해 SDK Manager를 이용해 Google Play Service 최신버전 업데이트 


작은 빨간네모안의 SDK Manager를 누르면 Android SDK Manager 창이 위와같이 뜬다.

휠을 내려서 Extras 를 찾아서 하위의 Google Play services 를 체크하고 Install packages... 를 누른다

(필자는 이미 최신버전이라 단추가 비활성화상태)


이까지 마친 뒤 SDK 폴더로 이동 한 다음,

sdk/extras/google/google_play_services/libproject/google-play-services_lib 파일을 import해 준다.

밑의 사진을 보고 따라한다.







이 그림은 필자와 약~간 다를건데 필자는 이미 라이브러리를 import 해놨기때문에 위와같이 나온다. 상관하지않는다.




그럼 이렇게 프로젝트가 생성되고,


생성된 프로젝트를 우클릭 > Properties 한 다음 설정을 위와 같이 맞춘다.

Build Target은 꼭 2.3.3 이 아니라도 상관 없다. (보다 낮은것은 추천하지 않는다.)



그리고 이제 지도를 띄울 프로젝트를 만들어 보겠다.


File > New > Android Application Project 순서로 실행 

(Android Application Project 가 없는사람은 당황하지 말고 Other... > Android > Android Activity 순으로 실행한다.



Next 한 다음 대충 다음 다음 Finish 해 주면 프로젝트 생성 완료.



만들어진 프로젝트에 우클릭 > Properties 을 해 주고,





Android 클릭, Add.. 클릭 , google-play-services_lib 클릭 후 ok > ok 해 준다.

아까와는 달리 Is Library는 체크하지 않는다.


이까지 했다면 이제 맵을 띄울 바탕은 끝났다. 본격적으로 맵을 띄워보자.



2. 구글맵 API Console 등록

우선 구글계정이 필수, 로그인 하였다면

https://code.google.com/apis/console로 접속한다.


보는바와 같이 APIs & auth의 APIs 카테고리에서

구글맵 서비스를 이용하기 위해 Google Maps Android API v2 를 OFF > ON 으로 바꿔준다. 필수



3. API Key 발급

맵을 띄우기 위해서는 자신만의 고유한 API Key를 발급받아야한다.


이를 발급받기 위해서는 컴퓨터의 디버그용 키스토어를 발급받아야하는데, 간단히 설명하자면

개발을 할 때는 디버그 키스토어라는것을 이용해 어플에 서명(자신을 각인)하여 개발하고,

상용할 때는 배포용 디버그 키스토어를 이용해 어플에 서명을 하고 배포해야 사용이 가능하다.

여기서는 디버그 키스토어를 사용하는데, 잘 이해가 안간다면 깊히 생각하지 않아도 된다.


시작 > 실행 > cmd 를 이용해 명령프롬프트창을 띄운다(단축키  윈도우키 + R 후 cmd 엔터)

디버그용 키스토어가 저장되는 위치로 이동하기 위해 본인의 운영체제에 따라 다음과 같이 입력한다. 

Windows XP : C:\Documents And Settings\사용자 계정\.android

Windows Vista/7 : C:\Users\사용자 계정\.android

OSX/Linux : ~/.android


필자는 윈7에 사용자계정은 fureun 이므로




엔터를 치면 경로가 이동하게 되고, 그 다음 위 사진과 같이

keytool -list -v -keystore debug.keystore -alias androiddebugkey -storepass android -keypass android

이렇게 입력후 엔터를 치면


이렇게 나오는데, 여기서 맵을 띄우기 위해 필요한것은 SHA1: 뒤의 16진수이다.

창을 닫기 전에 따로 메모장등에 적어서 보관해놓는다.


그리고 아까 API Console로 돌아가서



누르면 창이하나 뜨는데 Android를 선택 하고,


위와같이 입력한 뒤 Create Client ID 를 누른다.

큰 네모에는 아까 명령프롬프트에서 추출한 SHA1값;패키지명


드디어 API key가 나왔다.


위의 키값을 따로 저장한 뒤, 다시 프로젝트로 돌아가보겠다.


매니패스트를 켠 뒤 AndroidManifest.xml 에서

다음과 같이 빨간네모부분을 추가한다






맨밑의 android:value= 에는 조금전 발급받은 Api key를 입력하면 된다.

따라치기 귀찮으면 밑의 글 복붙


    <uses-feature

        android:glEsVersion="0x00020000"

        android:required="true" />

    

    <permission

        android:name="com.example.SearchMJ.permission.MAPS_RECEIVE"

        android:protectionLevel="signature" >

    </permission>


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

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

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

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

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

    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />

-------------------------------------------------

<meta-data

            android:name="com.google.android.maps.v2.API_KEY"

            android:value="Api key" />

<meta-data

            android:name="com.google.android.gms.version"

            android:value="@integer/google_play_services_version" />


그리고 메인액티비티의 레이아웃(res > layout > activity_main.xml)으로 이동해서


입력. 소스는

    <fragment

   android:id="@+id/map"

   android:name="com.example.GoogleMapVersion2.Fragment"

   android:layout_width="fill_parent"

   android:layout_height="fill_parent"

   class="com.google.android.gms.maps.SupportMapFragment" />




다음과 같이 MainActivity extends ActivityFragmentActivity 로 바꿔준다

그리고 실행 하면



짜잔 ~ 하고 맵이 나타난다.

최초 시작 위치나 카메라 줌 레벨 등은 동일 카테고리 내의 다른 포스팅을 참조하기 바란다.



혹시 에러사항이 있거나 문의사항이 있다면 댓글 남기면 친절히 답변 달아드리겠음

한참걸렸네 ..



Android/만들어보세요. | Posted by 덩치 2013. 12. 26. 15:03

과제 - 3. wifi 매니저

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO

(이 글은 초보자를 위한 학습용 과제입니다.)

근처 wifi 목록과 보안종류, 세기를 보여주는 어플


구성은 텍스트뷰와 버튼만 있으면 됨.


1. "체크" 버튼을 누르면 wifi 검색을 시작하고, 텍스트뷰에 와이파이의 SSID(이름), RSSI(파워), NetworkId(보안종류)를 출력한다.

내용은 이게 다임.


필요한 기술은

WifiManager와 WifiInfo가 핵심.


wifi를 다루기 위한 기본적인 내용은 이 과제를 만들다보면 다 익힐 수 있다.

응용한다면 보안설정이 안돼있는 와이파이에 자동으로 연결, 또는 연결해제 해줄 수 있겠다.


궁금한점은 댓글로 문의 또는 Wifi 카테고리의 글이나 Exam 카테고리의 wifi 관련 예제를 참고하면 된다.

Android/만들어보세요. | Posted by 덩치 2013. 12. 26. 14:34

과제 - 2. 스탑워치

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO


(이 글은 초보자를 위한 학습용 과제입니다.)

간단한 스탑워치를 만들어봅시다


레이아웃 구성은 화면 중앙에 시간이 표시되는 텍스트뷰 (24시간 00:00:00 형식으로 초단위까지 표시)

하단에 버튼으로 정지,일시정지,시작 버튼 배치


1. 시작 버튼을 누르면 1초단위로 증가하고, 분, 시단위로 넘어가게 구현

2. 일시정지를 누르면 해당 시간에서 일시정지. 시작버튼을 누르면 다시 카운트 업

3. 정지를 누르면 시간 초기화.

4. 어플을 종료했다가 다시실행시키면 종료했던 시점의 시간이 다시 표시되도록 설정


간단한 유틸어플입니다. 타마고에서 사용했던 기능중 대부분이 이어지는 형태

시간을 표현하기 위한 컨트롤이 제법 까다로울 수 있음


조금 응용한다면 증가가 아닌 감소기능도 구현하는걸로


질문사항은 댓글주세요

Android/만들어보세요. | Posted by 덩치 2013. 12. 26. 14:26

과제 - 1. 심플 타마고

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO

(이 글은 초보자를 위한 학습용 과제입니다.)

과제 - '심플 타마고'

시중에 출시된 어플중에 타마고 시리즈 어플이 많이 나와 있다.

화면에 계란같은걸 하나 띄워 놓고, 그걸 계속 터치하게되면 카운터가 올라가거나 깎이면서 알에 조금씩 금이 가는

오락성 어플이다. 


1. 화면 중앙에 이미지뷰 하나, 상단에 텍스트뷰 하나를 띄운다.

2. 최초 텍스트뷰의 숫자는 100으로 설정하며, 이미지뷰를 터치할 때 마다 1씩 감소한다.

3. 숫자가 70때 한번, 30때 한번, 0때 한번 이미지를 변경한다. (아무 이미지나 무관)

4. 0 이후 터치하면 다시 카운터는 100이 되고 이미지 초기화

5. 어플을 종료했다가 다시 실행시키면, 이전에 종료 전의 숫자와 이미지를 그대로 복구 (이어하기 기능)


관건은 5번. 데이터의 저장 방식은 여러가지가 있고, 이를 활용해야한다.


도중 막히거나 궁금한점 있으면 댓글로 물어보시길. 평일은 매일 확인하니 빠른 답변 가능합니다.


펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO

이 카테고리는 초보자를 위한 글로, 어느정도 기술력이 있다고 생각하시는분들은

해당사항이 없습니다.


무작정 책만 보고 따라하지 말고, 자신만의 과제를 정한 다음

과제를 수행하기 위한 기능들을 하나씩 검색 해 가면서 배우는것도 좋은 방법이라고 생각한다.


'뭘 만들어야할지 잘 모르겠다' 라는 경우를 위해 몇가지 간단한 유틸성 어플 과제를 제시하겠다.

'Android > 만들어보세요.' 카테고리의 다른 글

과제 - 3. wifi 매니저  (0) 2013.12.26
과제 - 2. 스탑워치  (1) 2013.12.26
과제 - 1. 심플 타마고  (2) 2013.12.26

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO

GoogleMap gmap = ((SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map)).getMap();

LatLng startingPoint = new LatLng(latitude값, longitude값);


gmap.moveCamera(CameraUpdateFactory.newLatLngZoom(startingPoint,16));

startingPoint는 시작 위치를 뒤의 숫자는 zoom level을 뜻한다.


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


팁으로 좌표 구하는 사이트 :

http://universimmedia.pagesperso-orange.fr/geo/loc.htm

한글로 검색 가능하며, 화면 중앙에 마커가 고정돼있고 그곳의 Lat, Lng값을 알려주는 사이트.

Android/View | Posted by 덩치 2013. 12. 24. 14:56

SurfaceView 구현 / 사용법

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO

SurfaceViewView를 상속받은 클래스로 Video Memory로 바로 접근하기 때문에 일반 View에서의 랜더링 

속도보다 빠르다.

일반 View는 많은 그리기 작업을 하면 메인 스레드의 자원을 다 잡아먹어버리기때문에 상당히 느려지게 되는데

이러한 단점을 보완하기 위한 클래스라고 보면 된다


우선 액티비티에 SurfaceHolder.Callback을 해 주고, add unimplemented methods를 해 준다.


public class DrawClass implements SurfaceHolder.Callback{


@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

}


@Override

public boolean onCreateOptionsMenu(Menu menu) {

getMenuInflater().inflate(R.menu.main, menu);

return true;

}


@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width,

int height) {

}


@Override

public void surfaceCreated(SurfaceHolder holder) {

}


@Override

public void surfaceDestroyed(SurfaceHolder holder) {

}

}


그럼 셋팅은 끝. 사용되는건 surfaceCreatedsurfaceDestoryed 정도가 되겠다.

surfaceCreated는 처음 서피스뷰가 생성될 때 호출되는데, 주의할점은 백그라운드 상태로 내려갔다가, 다시 올라오게 되면

surfaceview가 다시 created된다는점이다. created에서 thread를 실행시키는 작업을 할 경우

반드시 스레드가 동작중인지 여부를 먼저 확인해야한다. 그렇지않으면 익셉션 발생


surfaceChanged는 업데이트를 대비해 만들었다, 뭐라뭐라 하던데 잘 모르겠다. 사용하지않는듯하다.


이제 SurfaceView 구성은 하였고, 실시간으로 그리기를 실행하려면 Thread를 구동해야한다.


private Class PaintThread extends Thread {

public void run() {

while(!this.isInterrupted()){    //스레드가 인터럽트 될 때까지 반복 실행.

if (그리기 실행조건) {

//그리기 실행

doDraw();

}

}

}

}


나는 주로 드로우 관련부를 따로 만들어서 호출하는방식으로 사용한다.

비트맵을 그려보겠다. surfaceCreated에 다음과 같이 선언한다. (그 위에 Bitmap img, tempBitmap 전역변수로 선언해둔다)

팁 하나, 비트맵 이미지가 큰 경우 메모리를 상당히 많이 잡아먹어 종종 익셉션이 발생하게 되는데,

BitmapFactory.Options option = new BitmapFactory.Options();

option.inSampleSize = 1;

option.inPurgeable = true;

option.inDither = true;

이렇게 해 주면 비트맵이 먹는 메모리를 줄일 수 있다. 리사이클만으로는 감당이 안되는 경우가 생겨 찾다보니 이렇게 해주니 해결되더라. 이렇게 했을경우 단점은 잘 모르겠다. 고퀄리티를 요하는 작업이 아니었기때문에..

그리고 

tempBitmap = BitmapFactory.decodeResource(res, R.drawable.img30x30, option);

img = Bitmap.createScaledBitmap(tempBitmap, imgWidth, imgHeight, true);


private void doDraw() {

try {

canvas = mHolder.lockCanvas(); //그리기 준비

     int size = MainActivity.ARR_X.size();

     canvas.drawColor(Color.GRAY);  //배경색 설정

Paint p = new Paint();

p.setAntiAlias(true);

     canvas.drawBitmap(img, imgX, imgY, p);  //이미지를 X,Y위치에 그리기

catch (Exception e) {

}

finally {

mHolder.unlockCanvasAndPost(canvas); //그리기 종료

}

}


그리고 MainActivityxml에서


<패키지명.DrawClass

android:layout_width="500px"

android:layout_height="500px" />

와 같은식으로 호출한다.


여기까지가 SurfaceView 사용 방법이다.


참고로 위의 소스는 새로운 클래스를 만들어서 기존 액티비티에 영역추가하는식으로 사용한것이고

뷰와 마찬가지로 액티비티에서 바로 setContentView하여 적용 할 수도 있다.

문의점은 댓글 남겨주기바람