Android/NFC | Posted by 덩치 2014. 9. 26. 17:02

NFC 태그 쓰기(Write)

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

이전 포스팅 NFC 태그 읽기 에 이어서 쓰기에 대해 알아보자


NFCWrite하기 위해서는 NDEF Message를 구성해야한다. (참고 : http://biig.tistory.com/77)


참고 글을 봤다면 NDEF Message가 어떻게 구성되는지는 다 알것이고 설명은 생략하겠다.



우선, NFC 관련 객체를 생성한다.


public static final int TYPE_TEXT = 1;

public static final int TYPE_URI = 2;


EditText mWriteText;

NfcAdapter mNfcAdapter;

PendingIntent mPendingIntent;


protected void onCreate(Bundle saveInstanceState) {


mWriteText = (EditText) findViewById(R.id.et_write);

mNfcAdapter = NfcAdapter.getDefaultAdapter(this);

Intent inent = new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

mPendingIntent = PendingIntent.getActivity(this,0,intent,0);


}


다음, 이전 글에서 설명했듯이 태그를 인식하게되면 onNewIntent 메소드가 호출된다.


onNewIntent가 호출되면 태그에 실제로 값을 Write하는 작업을 수행해야한다.


@Override

protected void onNewIntent(Intent intent) {

super.onNewIntent(intent);

if (intent == null)

return;


Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

writeTag(getTextAsNdef(), detectedTag);


}


private NdefMessage getTextAsNdef() { 


byte[] textBytes = mWriteText.getText().toString().getBytes();


NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, 

"text/plain".getBytes(),

new byte[] {}, 

textBytes);

return new NdefMessage(new NdefRecord[] {textRecord});

}


private NdefMessage getUriAsNdef() { 


byte[] textBytes = mWriteText.getText().toString().getBytes();


NdefRecord record1 = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,

new String("U").getBytes(Charset.forName("US-ASCII")),

new byte[0],

textBytes) ;

return new NdefMessage(new NdefRecord[] {textRecord});

}


private void toast(String text) {

Log.i("fureun","toast");

Toast.makeText(this, text, Toast.LENGTH_SHORT).show();

}


이렇게 하면 기본적인 Write가 완료가 된다. 이후 Read를 하게되면 자신이 입력한 태그의 정보를 확인할 수 있다.



'Android > NFC' 카테고리의 다른 글

NFC 태그 읽기(Read)  (0) 2014.09.26
NFC란 ?  (0) 2014.09.25
Android/View | Posted by 덩치 2014. 4. 3. 16:21

나인패치 (9patch) 이미지 만드는 방법

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

나인패치 이미지란


(http://developer.android.com/tools/help/draw9patch.html) <- 디벨로퍼사이트의 나인패치에 대한 설명


해상도가 다른 단말기에서 아이콘 등이 확대 될 때, 확대 되는 영역을 특정지어서 확대되서


픽셀이 깨지는 (라운드,그라데이션) 현상 없이 확대되는 이미지.


확대되도록 설정한 영역 이외의 부분은 확대가 되지 않는다.


쉽게말해 말풍선 같은 이미지를 네 모서리와 하단 꼭짓점 크기는 고정시키고 안의 크기만 늘려주며,


고정된 해상도라기 보다 어떤 해상도로 늘어나더라도 이미지가 깨지지 않도록 하는 방식이다.


다음 이미지를 보자




위 이미지가 나인패치 이미지이다. 확장자가 .9.png로 특이한 형태를 취하고 있으며,


풍선 주위에 검은색 선은 확장 영역과 콘텐츠 영역을 표시하는것으로, 실제 이미지가 적용되면 나타나지 않는다.


나인패치 사용법에 앞서 우선 위의 이미지가 어떻게 확장되는지 설명을 하자면


다음 이미지를 보며 설명해주겠다.




왼쪽변의 검은 선은 세로로 확장되는 영역, 상단변의 짧은 선 두개는 각각 세로로 확장되는 영역이며,


우측변의 검은 선은 콘텐츠(텍스트 등)가 들어가는 세로영역, 하단의 변은 마찬가지 콘텐츠가 들어가는 가로 영역이다.


분홍색 기둥 두개가 보일텐데, 간단히 말해 저 두개의 영역이 확대,축소되며 이미지를 표시한다.


즉, 노란부분과 분홍색 막대 상,하단, 왼쪽분홍막대 좌측, 오른쪽 분홍막대 우측 영역은


이미지 크기가 불변한다. (돼지꼬리)


분홍색 막대만이 가로,세로로 확장되고 축소되며 전체 이미지가 커지거나 작아지는것처럼 표시된다.


그렇기때문에 작은 해상도에서는 라운드가 엄청 커보이지만, 큰 해상도에서는 라운드가 작아보이게 되고


엄청 커지면 라운드는 거의 없는것처럼 보이게 된다.


밑의 말풍선 꼬리 영역도 마찬가지로 크기가 변하지 않는다.


위 이미지처럼 라운드가 있거나, 또는 그라데이션이 있어서 그라데이션 영역은 확장하지 않고, 이외의 부분만


확장될 수 있을 때, 나인패치 이미지를 사용한다.


나인패치의 한계는 하트모양이나 동그라미처럼 특정 영역만 확대하면 모양이 이상해져버리는 


도형에는 사용할 수 없다는것이다.


나인패치를 만드는법을 알아보자. 우선 이미지를 준비한다. 포토샵으로 그려도 되고 기존의 이미지를 사용해도 된다.



나는 간단하게 아래의 이미지로 실습을 해 보겠다.




다음은 나인패치 이미지를 만들 수 있는 툴을 실행시킨다.

(툴은 안드로이드 sdk에 있으며, 툴이 없는 경우 포토샵으로 맨처음 이미지처럼 만들고, 확장자를 name.9.png 식으로 저장하여도 된다.)


나의 경로는

adt-bundle-windows-x86_64-20130522 -> sdk -> tools -> draw9patch.bat


draw9patch.bat 파일을 실행시키면 잠시후 다음과 같은 창이 나타나는데,




이미지를 드래그해서 위 창에 드랍시킨다.




그럼 이렇게 표시된다. 우측은 미리보기이고..


상하좌우 맨 마지막 1픽셀을 마우스로 클릭하여 드래그하면 검은색 선이 생기는데,


이런 방식으로 영역을 설정 해 준다.


일반적으로.콘텐츠영역은 확대되는 영역의 최대 영역으로 설정한다.


영역 취소는 시프트를 누르고 클릭 하여 드래그하면 된다.




(이런식으로 색상이 구분되는것은 하단에 show patches 를 체크해 주면 된다.)


분홍색 부분이 확대되는 영역, 초록색과 붉은부분이 확대되지 않는 영역이며


우측을 보면 확대를 엄청 했을경우 미리보기인데, 라운드부분은 확대되지 않아서 상대적으로 작아보인다.


하지만 이런 특성 덕분에 라운드가 깨져보일 염려는 없다.




나름대로 알아듣기 쉽게 설명하기 위해 노력했는데 잘 전달 되었는지 모르겠습니다.


문의사항은 댓글 남겨주세요



펌 환영. 출처만 남겨주세요



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

안드로이드에서 데이터 관리를 할 수 있는 방법에는 여러가지가 있다.

SQLite DB를 이용한 데이터 관리, 서버를 거친 DB에 의한 관리, Input,OutputStreamReader를 이용한 관리,

SharedPreferences를 이용한 관리 등이 있으며, 여기서는 SharedPreferences를 이용한 방법에 대해

알아보겠다.


SharedPreferences키와 벨류로 이루어진 파일 형식으로 데이터를 저장하는 방법으로,

Boolean, Float, Int, Long, String 형태로 데이터를 저장할 수 있다.

어플의 설정값, 사용자 설정 정보등을 저장하는데 적합하며 사용법은 다음과 같다.


선언

SharedPreferences mPref = PreferenceManager.getDefaultSharedPreferences(context);


데이터 저장

SharedPreferences.Editor editor = mPref.edit();

editor.putString("key", "value");

editor.commit();


데이터 호출

String callValue = mPref.getString("key", "default value");

*호출하는 키에 대응하는 값이 없을 경우 디폴트로 설정한 데이터가 출력된다.


데이터 삭제

SharedPreferences.Editor editor = mPref.edit();

editor.remove("key"); or editor.clear();

editor.commit();



주의할점은 만약 기존 데이터의 형을 변경시키고싶다면

반드시 클리어를 한 다음 변경사항을 적용시킨다. 그렇지않으면 예외가 발생하게된다.


SharedPreferences의 장점은 심플한 사용과 관리가 아닐까 한다.



'Android > 입/출력' 카테고리의 다른 글

기본적인 JSONObject, JSONArray 사용법  (3) 2014.03.21
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
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하여 적용 할 수도 있다.

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