[펌]http://kaludin.egloos.com/2653125

AIDL이란?

 

http://developer.android.com/guide/developing/tools/aidl.html

 


 

http://www.androidpub.com/8013

AIDL 쉽게 설명할 수 있는 부분은 아닙니다만 간단하게 정리를 해보겠습니다.

AIDL은 Android Interface description language의 약자입니다. 말그대로 인터페이스를 정의하는 언어입니다. AIDL파일을 열어보면 Java에서와 비슷하게 Method를 정의하는 코드를 볼 수 있습니다. Corba의 IDL과 같은 것을 Android에서 사용한다고 생각하면 됩니다. AIDL Tool은 AIDL파일에 적합한 Java Code를 자동으로 생성시켜주는 툴입니다. (Corba는 Java의 RMI와 비슷한 역할을 하는 표준이라고 생각하시면 됩니다.)

IDL은 보통 RPC(Remote Procedure Call)에서 많이 사용됩니다. 서로 다른 프로세스 혹은 네트워크간에 함수를 호출하기 위해서는 인터페이스가 바뀔때마다 언어와 구조에 맞는 코드를 생성해주어야 하는데. 실제 코드를 생성하는 부분은 툴에 맞기고 프로그래머는 IDL만 정의하도록 구성됩니다.

AIDL은 Android에서 사용되는 IPC (Inter process communication), 안드로이드 구조를 이야기할때 Binder라고 일컬어지는 부분을 사용하기 위해서 정의합니다. Remote Service 라는 것은 같은 프로세스가 아니라 다른 프로세스에서 오는 함수 호출을 처리하는 Service이고 그것을 연결해주는데 Binder가 사용되고 있습니다. 그 Binder를 사용하는 코드를 자동으로 생성시켜주는 것이 AIDL이지요.

Binder가 Android 프레임워크의 근간이되는 중요한 역할을 하고 있습니다만 머 실제 어플리케이션에서 그 존재를 알아야할일은 많이 없습니다.

APIDemos 예제에서 메시지가 뜨는 과정이 중요한 것이지 그 메시지가 보여지는 것이 중요한 것은 아닙니다. RemoteService는 다른 어플리케이션 혹은 다른 프로세스에서 호출될 수 있는 서비스를 생성할때 사용한다고 이해하시면 됩니다.

 

http://www.androidpub.com/6167

2) Service에는 두가지 라이프사이클이 있을수 있는데 하나가 onStart와 onStop이고 하나가 onBind와 onUnbind되는 경우가 있습니다. onStart의 경우 그냥 서비스를 실행시키고 Intent에 전달된 Data만 처리하는 경우이지만, onBind의 경우 연결이 생성되고 AIDL을 통해서 서로 다른 프로세스에서 IPC를 통해 오는 Call을 처리해야하는 경우 사용됩니다. 근데 onBind는 일반 어플리케이션 작성시에는 쓸일이 많이 없습니다.

원래 이 두부분이 윈도우즈 메시지 처리구조와 프로세스 간의 IPC 처리 구조에 대한 이해 없이 이해하기가 힘든 부분입니다. 많이 안쓰이는 부분은 일단 넘어가시고 많이 쓰인다고 말씀드린 부분만 일단 익혀두시면 좋을듯 합니다.

 

 


 

http://codelab.textcube.com/457

1. 인터페이스(aidl) 생성
2. 구현클래스 생성
3. 메니페스트에 적고
4. 엑티비티에서 해당 클래스를가져와서
5. 구현된 함수를 사용.

의 순서로 진행됩니다.

사실 엑티비티 레벨이니 서비스 레벨이니 신경안써도 돼는 작은 어플에서는 샤용할일이 없을듯.


...........


지금 생각해보니 평소하던데로
XxxService , XxxServiceImpl이라는 편이 차라리 읽기 편하지 싶음.
I를 앞에붙여서 인터페이스임을 표시하는게 어느동네 표기법이더라?


덧. 서비스 클래스만 만들면 훨씬더간단해지는데 그건 이따가 자고일어나서 해보고 포스팅하겠음.

 


 

http://www.flowdas.com/blog/archives/2337.html

안 드로이드 AIDL 문법(Android AIDL Syntax)

자주 받는 질문중의 하나는 “AIDL의 정확한 문법이 어떻게 되는가?” 입니다. 안드로이드의 문서에는 예제 형태로만 설명되어 있을 뿐 형식화된 문법이 제시되지 않고 있습니다. 대충 알고 대충 써라? 천만의 말씀.

 안드로이드 (Android) 1.6 AIDL의 BNF Grammar 입니다. Yacc 문법을 따릅니다.

          ......          

PARCELABLE, INTERFACE, IN, OUT, INOUT, ONEWAY 는 각각 키워드(Keyword) parcelable, interface, in, out, inout, oneway를 뜻하고, IMPORT, PACKAGE 는 각각 import, package 문장 전체를 뜻합니다. ARRAY 는 하나 이상의 []를 뜻하고, GENERIC 은 Collection<Object,String>과 같은 Java Generic 표현을 뜻합니다. IDENTIFIER 는 대략 Java 의 클래스 명으로 쓸 수 있는 문자열이라고 보시면 됩니다. 주석 관련 구문 요소들은 생략했습니다.
SDK 의 AIDL 설명에는 나오지 않지만, oneway 키워드를 인터페이스 또는 메쏘드 앞에 붙일 수 있음을 알 수 있습니다. One-way call 에 대한 설명은 android.os.IBinder.FLAG_ONEWAY 에 대한 SDK 문서에 등장합니다. 비록 AIDL 에서의 사용법을 설명하고 있지는 않지만, 메쏘드 실행이 끝나기를 기다리지 않고 호출 즉시 복귀하는 방법을 제공하고 있음을 알 수 있습니다. AIDL 에서 oneway 로 지정한 메쏘드들의 Proxy 는 모두 transact() 를 호출할 때 FLAG_ONEWAY 를 포함하게 됩니다. 인터페이스에 oneway 를 지정하면 모든 메쏘드에 oneway 를 지정한 효과가 발생합니다. 다중 배열은 지원되는 반면 인터페이스 계승은 지원되지 않음을 확인할 수 있습니다.

 


스텁(stub)


스텁은 원격 객체에 대한 메소드 호출을 실제 구현된 원격 객체가 있는 서버로 전송하는 일을 담당하는 대리자 역할을 하는 객체이다. 클라이언트 객체가 가지게 되는 원격 객체에 대한 참조는 실제로는 지역의 스텁에 대한 참조이다. 스텁 파일은 서버 쪽과 클라이언트 쪽 모두에 필요하다. Naming 클래스나 Registry 인터페이스의 lookup() 메소드를 사용하여 RMI 등록부에 등록된 원격 객체에 대한 참조를 얻을 때 이 메소드가 반환하는 객체는 실제 원격 서버 객체가 아니라 원격 서버에 대한 스텁 객체가 된다.

필요성을 느낄때 : Activity에서 Service를 바인딩 한후 Activity에서 서비스 메소드는 간단히 호출되지만..


Service에서 Activity 메소드를 호출하는 건 힘들다는 걸 느꼈다..


그래서 공부한게 이 방법인 것 같다.^^;


출처 : 

http://blog.naver.com/dlgusrb5061?Redirect=Log&logNo=120101130132


아래의 설명은 안드로이드 프로그래밍을 기본적으로 한다고 생각하고 쓴다

 

1. 기본적으로 안드로이드 프로젝트를 생성한다.

 

2. 액티비티 에서 생성할 서비스 클래스를 만든다

 

3. .aidl 파일을 만든다

package com.service;                     // 패키지 이름 따라서..

 

interface state{                               // state 라는 인터페이스를 만든다  파일명도 state.aidl

         int getState();                        // 값을 주기 위한 함수
         int setState(int k);                  // 값을 입력하기 위한 함수

}

 

4. 위의 인터페이스를 이용하여 서비스에 bind를 생성한다.   Stub를 이용하여 만들수 있다.

// state.Stub 클래스

private final state.Stub binder = new state.Stub() {
           @Override
           public int getState() throws RemoteException {   
                      return 0;

           }
  
           @Override
           public int setState(int k) throws RemoteException {
                      return 0;
            }

};

 

synchronized private int getStatePageImpl() {
           return 0;

}

 

5. 서비스 클래스 에서 onBind함수의 return을 위의 binder로 해 준다

@Override
public IBinder onBind(Intent intent) {
           return binder;
}

 

6. 액티비티 클래스 에서 ServiceConnection 을 이용하여 서비스가 시작될 때와 종료될 때 상황을 구현한다

 

import android.content.ServiceConnection;

 

private ServiceConnection serviceConn = new ServiceConnection() {
     public void onServiceConnected(ComponentName className, IBinder binder) {
            service = state.Stub.asInterface(binder);
     }

 

     public void onServiceDisconnected(ComponentName className) {
            

     }

};

 

7. 서비스 시작과 종료를 구현한다

 

<시작>

serviceintent = new Intent(this, mainService.class);
bindService(serviceintent, serviceConn, BIND_AUTO_CREATE);

 

<종료>

unbindService(serviceConn);


==========================자세한 설명


AIDL를 사용하여 원격 언터페이스를 사용하거나 설계(디자인)하기   - 번역 2008년 2월 20일 김문섭 (Easygn Institute)


그 동안 각각의 어플리케이션은 자신이 해당되는 프로세스에서 실행되며, 다른 프로세스가 실행시되는
응용프로그램 인터페이스나 프로세스 사이에 개체를 전달해야 할 경우에 당신은 서비스를 쓰기가 가능합니다.
기본 적으로 안드로이드 플랫폼 상에서 한 프로세스는 메모리상에서, 다른 프로세스에 대한 정상적인 액세스가 불가능합니다. 
한마디로, 그들은 오브젝트 안에서 운영체제 시스템이 이해할 수 있도록 세분화된 개체를 필요로 합니다,
그리고 오브젝트 간의 구획화 작업을 당신이 하도록 합니다.

그 코드를 구획화 하는 작업은 골치아픈 작업이고, 그래서 우리는 당신을 위해 AIDL 도구를 제공하게 되었습니다.

AIDL (안드로이드 인터페이스 정의 언어)는 하나의 안드로이드 장치 위에서 잠김프로세스 통신규약(IPC)에 의해 
두 프로세스들 사이에 대화가 가능하도록 하기위한 목적으로 생성되어진 코드를 사용할 수 있게하는 IDL 언어 입니다. 


만약 당신이 한 프로세스(예: Acitivity객체) 안의 코드가 
또 다른 프로세스(예: Service 객체) 안의 한 오브젝트 위의것을 필요로 하게 된다면 
당신은 AIDL 을 사용하여 구획화 파라미터들의 코드를 생성하게 될 것입니다.


그 AIDL IPC 메커니즘은 COM or Corba 와 유사한 인터페이스를 기반으로 하고 있습니다.
그러나 보다 가볍고 빠르게 만들어졌습니다.
이것은 한 프록시 클래스와 클라이언트 클라이언트 사이에 값을 넘길 수 있도록 구현하는데 사용되어 집니다.


이 페이지는 다음의 주요 단원으로 나눠졌습니다:

* AIDL를 사용하여 IPC를 구현합니다. 
* .aidl 포맷의 IPC Class 를 호출해 봅니다.

 


◎ AIDL 를 통해 IPC 구현하기


AIDL를 사용하여 IPC 서비스를 구현하는 순서는 다음과 같습니다.

1. 내 .aidl 파일을 작성하기 
   - 이 파일은 미리 정의된 메소드와 필드를 클라이언트에 사용할 수 있도록 
     인터페이스(내인터페이스.aidl)를 정의합니다.

2. 내가 만든 .aidl 파일을 추가하기
   - (당신에 의해 이클립스 플러그인이 관리하도록 합니다) 컴파일러로 안드로이드에 인클루드 하고
     AIDL를 호출하고, tool/ 안에 넣습니다.

3. 내 인터페이스 메소드를 구현하기
   - AIDL 컴파일러는 당신의 AIDL 인터페이스로부터 자바프로그래밍 언어로 구현된 것을 생성합니다.
     이 인터페이스는 한 인터페이스(그리고 IPC 호출를 위해 필수적인 약간의 메소드가 추가된)를 상속한
     하나의 추상화 클래스로 명명된 조각을 가집니다.

4. 내 인터페이스를 클라이언트에 통보하기 
   - 만약 당신이 서비스에 기재한다면, 한 당신이 구현된 인터페이스 클래스의 인스턴스를 
     Service 로 확장 오버라이드된 Service.onBind(Intent) 에게 반환할 것입니다.


● .aidl 파일 작성하기

AIDL 은 하나 이상의 메소드를 함께 사용하는 인터페이스를 당신이 선언한 수 있도록 간단한 문법을 쓰며,
패러미터나 반환값을 가질 수 있습니다. 그 패러미터들과 반환값은 다양한 타입이 될 수 있으며,
심지어는 AIDL로 생성된 인터페이스도 될 수 있습니다.
그러나 이 점을 중요하게 참고해야 합니다. 생성되지 않은 모든 타입,
심지어 만약 같은 패키지에 정의된 당신의 인터페이스를 포함해서 당신은 반드시 import 해야 합니다. 
여기에 AIDL 가 자체 지원할 수 있는 데이터 타입이 있습니다.


* 원시형태의 자바 프로그래밍 언어타입(int, boolean 기타) - import 명시가 필요하지 않습니다.)
* 다음에 해당되는 클래스(import 명시가 필요치 않습니다.)
  String

  List   - List 내부의 모든 엘리먼트는 반드시 하나의 이 아래에 있는 리스트 내부의 한 속성이어야 합니다.
           다른 AIDL로 생성된 인터페이스와 세부 가능화된 것들을 인클루드 합니다. 리스트는 제네릭 클래스 (예: List<String>)를
           사용하는 방법을 써도 됩니다.   다른 측면의 현실적이고 구체적인 클래스라면, 비록 메소드는 리스트 인터페이스를 사용하여 
           생성된 것일지라도, 항상 ArrayList 를 통해 받을 수 있도록 하는 것입니다,

  Map    - 맵 객체 안의 모든 엘리먼트들은 반드시 리스트 안에있는 하나 이상의 속성들 이어야 하며,
           다른 AIDL로 생성된 인터페이스와 세부 가능화된 것들을 인클루드 합니다.
           제너릭 맵 (예: Map(String, Integer)은 지원하지 않습니다. 다른 측면의 현실적이고 구체적인 클래스라면, 
           비록 메소드는 맵 인터페이스를 사용해 생성된 것일지라도 항상 해쉬맵을 통해 받는 것입니다.

  CharSeq- TextView 나 다른 위젯 오브젝트들로 CharSequence 속성들을 사용하기에 매우 유용합니다.
  uence

  다른 AIDL 생성된 인터페이스는 언제나 레퍼런스로 통과됩니다. import 를 명시하는 방법은 아래와 같습니다.
   사용자 정의를 구현 클래스는 세분화가능한 프로토콜을 하거나 값 별로 전달합니다.  import를 명시하는 방법은 아래와 같습니다.

  여기 기본 AIDL 문법이 있습니다 - [ 문서 내의 소스코드 참조]

 

● 인터페이스 구현

AIDL는 당신과 함께 비슷한 이름을 가진 당신의 .aidl file 를 위해 인터페이스 파일을 생성합니다
만약 당신이 이클립스 플러그인을 사용한다면 AIDL은 빌드 프로세스(프로젝트 빌드를 위해 미리 AIDL을 실행시킬 필요가 없습니다)
파트에 자동으로 실행되도록 합니다.
만약 이 플러그인을 쓰게되면 당신은 AIDL을 먼저 실행하게 될 것입니다.

생성된 인터페이스를 포함하여 한 추상화 내부 클래스 명명 조각에 모든 당신이 선언한 .aidl 파일 그 메소드를을 선언합니다.
조각은 또한 약간의 헬퍼 메소드, 그 중에 가장 많은 asInterface(), 어느 곳에 가져온 IBinder ( application.Context.bindService()가
성공했을 때의 클라이언트 onServiceConnected() 구현체 ), 그리고 IPC메소드를 호출하는데 사용된 인터페이스의 인스턴스의 리턴 값 
들로 선언되어 있습니다. Calling an IPC 섹션을 참고하면 좀더 캐스트하는 것에 대한 더 많은 사항을 알 수 있습니다.

당신의 인터페이스를 구현할 때, YourInterface.Stub 를 확장(상속), 그리고 메소드를 구현 (.aidl 파일과 stub 구현 메소드를
안드로이드 빌드프로세스 가 .Java 파일을 프로세스하기 전에 먼저 만들도록 할 수 있습니다. )

여기 간단한 IRemoteService 호출에 대한 인터페이스 구현 예제가 있으며, 단일 메소드로 분리되고
getPid 를 사용한 익명의 인스턴스의 경우입니다. (참고할 것):

// No need to import IRemoteService if it's in the same project.
private final IRemoteService.Stub mBinder = new IRemoteService.Stub(){
    public int getPid(){
        return Process.myPid();
    }
}

 

● 인터페이스 구현에는 몇 가지 규칙이 있습니다.

* 당신의 호출 전송에 대하여 미리 예외검사를 하지 않습니다.
* IPC는 동시에 호출 됩니다. 만약 당신이 IPC 서비스가 보다 많은 작은 밀리초 단위로 처리해나갈 필요가 있다고 느끼면 
 알고 있다면, 당신은 되도록 Acitivity/View 쓰레드를 호출하지 말아야 하는데, 그 이유는 CPU가 특정 어플리케이션(안드로이드는  "Application not Responding" 다이얼로그를 표시할 수도 있습니다)에 매달려 정체될 될 수도 있기 입니다.
 다른 쓰레드로 나눠서 처리하는 방법을 시도해 봅니다.
* 메소드들은 이렇게만 지원됩니다 " 당신은 static 필드 형태로 AIDL 인터페이스를 선언할 수 없습니다.

 


● 인터페이스를 클라이언트에 공개하기

 이제 당신은 인터페이스 구현법을 알게 되었고 클라이언트에 공개할 차례 입니다. 당신의 서비스에 발표 한단 뜻이기도 합니다.
 Service를 상속받고 Service.onBind(Intent) 를 구현하도록 받아서 구현된 인터페이스 클래스 의 인스턴스를 반환합니다.

 여기 IRemoteService 인터페이스를 클라이언트 공개하는 일부 코드가 있습니다. (문서 소스코드 참조)

 


● 패러미터 값을 Parcelables(꾸러미객체) 를 이용해서 인수값으로 넘겨주기
 
 주의 :
   Parcelables 는 현재 당신이 이클립스 플러그인을 사용할시에 작동하지 않습니다. 
   강제로 시도할 경우 다음과 같은 에러들을 보게 될 것입니다. :
    .aidl files that only declare parcelables don't need to go in the makefile
     aidl can only generate code for interface, not parcelables
  이것으로 한계가 있음을 알게 되었습니다. Parcelable은 역시 build.xml 파일들 이나 당신이 가진
  사용자정의 빌드 시스템만을 사용할 수 있습니다.
  작업공간은 당신은 위해 aidl tool 로 손안의 모든 인터페이스를 구현하고 추가할 수 있도록 
  당신의 이클립스 프로젝트 상에서 실행되어 집니다.
  왜 이클립스가 aidl 파일 컴파일 시도가 불가능한지를 5장을 통해 알아보세요.
 

  만약 당신이 만든 클래스가 한 프로세스 가 다른 AIDL 인터페이스를 경유하여 보내게 되는 일을 수행한다면, 그일도 가능합니다.
  당신은 당신의 클래스가 다른 측면의 IPC 에게도 유효하다면. 그 코드를 안전하게 보호해야 합니다.
  일반적으로 그것은 당신이 시작과 동시에 서비스와 의사소통을 할 수 있음을 의미합니다.

  여기에 5개 파티의 Parcelable 프로토콜을 지원하는 클래스 생성법이 있습니다.

  1. Parcelable 인터페이스로 당신의 클래스를 구현하세요.
  2. public void writeToParcel(Parcel out) : 오브젝트와 꾸러미에 쓰기의 현재 상태를 보존할 수 있도록  다음과 같이 구현하세요.
  3. public void readToParcel(Parcel in) : 오브젝트로부터 꾸러미 값을 읽을 수 있도록 다음과 같이 구현합니다.
  4. CREATOR를 호출할 static 필드를 추가합니다. 당신의 클래스에 이것은 Parcelable.Create 인터페이스로 구현할 수 있습니다.
  5. 마지막이지만 남은 것이 있습니다. aidl 파일을 AIDL 도구가 찾을 수 있도록 parcelable 클래스에 추가하되,
     하지만 당신의 빌드에 추가하지 마세요. 이것은 C 헤더파일을 쓰는 것과 비슷합니다.
     당신은 aidl을 컴파일할 수 없습니다. parcelable 로 하여금 마치 헤더파일을 기본적으로 컴파일할수 없는 것 처럼 말입니다.

  AIDL 는 이 메소드와 필드를 당신의 오브젝트들의 구획화와 비구획화 된 곳에 생성할 것입니다.

  여기에 Rect 클래스를 Parcelable 프로토콜을 통해 구현한 예제가 있습니다.  (문서 코드 참조)

 
  Rect.aidl 예제가 있습니다.
  package android.graphics;

  // Declare Rect so AIDL can find it and knows that it implements
  // the parcelable protocol.
  parcelable Rect;

 
  구획화하는 예쁘고 간단한 Rect 클래스 입니다. 다른 메소드에서 당신이 꾸러미에 쓴 값이 
  꾸러미 위에서 어떤 식으로 보여지는지를 살펴보세요.


  주의 : 다른 프로세스로 부터 데이터를 받는 것에 보안이 되어있음을 잊지마세요.
         예로, Rect는 꾸러미로 부터 4개의 값을 읽지만 이것은 동의 하에 안전하게 올려졌습니다.
         하지만 이것은 위로 당신에게 안전하게 동의가능한 범위내의 무엇이든지 호출해서 시도하도록 만들어져 있습니다.
         구획화로부터 안전하게 보호하는 방법을 알기 위해 안드로이드에서 보안, 권한에 관한 문서를 자주 참고하세요.


● IPC 메쏘드를 호출하기

 여기엔 당신의 원격 인터페이스를 호출할 수 있도록 클래스를 호출하는 단계 입니다.

 1. 당신이 정의해둔 .aidl 파일을 인터페이스 속성 변수로 선언합니다.

 2. ServiceConnection 을 구현합니다.

 3. ApplicationContext.bindService() 를 호출합니다. 서비스연결 완성된 것의 인수를 넘깁니다.

 4. 당신의 완성된 ServiceConnection.onServiceConnected() 것으로 IBinder 인스턴스 값을 받을 수 있습니다.
    YourInterfaceName.Stub.asInterface((IBinder)Service) 를 호출해서 Yourinterface 속성으로 변환후 넘깁니다.

 5. 메소드를 당신이 정의한 인터페이스로 호출합니다. 당신은 언제나 예외 점검에 잡힐 수 있습니다. DeadObjectException,
    어느것은 연결이 끊어질 수도 있습니다 : 이것은 오직 원격메소드를 통해 예외처리 검사를 해야 합니다.

 6. 연결을 해제합니다. ApplicationContext.unbindService() 를 인터페이스의 인스턴스와 함께 호출합니다.

 
 약간의 IPC 서비스 호출에 대해 덧붙이자면.

  * 오브젝트는 맞은편의 프로세스의 갯수를 참조합니다.
  * 당신은 익명의 오브젝트에 메소드 arguments를 보낼 수 있습니다.


  여기에 AIDL 로 만들어진 서비스를 호출하는 약간의 코드 예제가 있습니다. ApiDemos project로부터 원격 Activity 샘플을 참조하세요


[Android] 안드로이드 인디케이터 설정 - NotificationManager Android / Goal

2010/08/02 13:34

[출처] 
http://blog.naver.com/oh4zzang/40111693903

안드로이드에서 NotificationManager를 통해 인디케이터 바를 설정하거나 출력(notify)할 수 있다.

흔히들 인디케이터 바를 status 바라도 말하기도 한다.

우선 간단하게 getSystemService() 메소드를 통해 NotificationManager을 받아올수 있다.  

이후 flags 값을 셋팅하고, setLatestEventInfo를 통해 noti 선택 시 실행될 Activity를 설정해 주면된다. 

 private void showNotify() {

    NotificationManager nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
 int _ID = 0xffff0001;
       
Notification notification = null;      
   notification = new Notification(R.drawable.icon, "start notify", System.currentTimeMillis());  
notification.flags = Notification.FLAG_ONGOING_EVENT;
  
   PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, ServiceSample.class), 0);
   notification.setLatestEventInfo(this, "Test Notify", "hello notification", contentIntent);
   nm.notify(_ID, notification);
 }

 

위 메소드 showNotify() 를 호출 하게 되면 아래와 같이 인디케이터 영역이 초기화되면서 등록한 아이콘과 메세지가 출력된후

 

사용자가 지우기 이전까지 인디케이터 영역에 존재하게 된다.

       

위와 같이 호출 시 다음과 같이 인디케이터 영역에 아이콘을 출력하고 notify 할 수 있다. 

왼쪽 이미지 인디케이터 영역에 안드로이드 아이콘이 출력된 것을 확인할 수 있다.

이 이미지는 Notification 객체 생성 시 지정해 줄수 있다. 여기서는 R.drawable.icon 과 같이 기본 아이콘을 사용 하였다.

new Notification(R.drawable.icon, "start notify", System.currentTimeMillis());   

 

오른쪽 이미지는 인디케이터 바를 아래로 드레그한 화면이다. 알림에 해당 noti가 등록된 것을 볼 수 있다.

여기서는 아래와 같이 등록을 하고 클릭 시 연결(link)될 인텐트, class 를 PandingIntent 로 생성 후 setLatestEventInfo() 메소드를 사용하여 연결했다.

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, ServiceSample.class), 0);
notification.setLatestEventInfo(this, "Test Notify", "hello notification", contentIntent);

 

알림 영역이 아닌 진행중 영역에 notify 를 등록 하고 싶다면 flag  를 아래와 같이 설정해 주면 된다.

   notification.flags = Notification.FLAG_ONGOING_EVENT;        

 

이전 이미지와 다르게 알림영역이 아닌 진행중 영역으로 등록 되어 있는 것을 볼 수 있다.

출처 : http://sje0114121.blog.me/150089240741

background에서 작업하기

<Service >

     예) 미디어 플레이어 : 꼭 Service로 만들어야 하는건 아니다. Activity로도 만들수있음.

          장시간으로 하면서 user Interface가 거의 없는 것을 Service로 만드는 게 좋다.

 

* intent filter 존재 : intent로 시작됨.

Intent i = new Intent(명시적 or 암시적)

startService(i);  // 한 life cycle 돌게됨.

  - 객체는 singleton이라서 다른곳에서 startService()를 다시 호출해도 onCreate()는 되지않고 onStart()만 다시불린다.

 

stopService(i);

 

bindService(i);  // 내 액티비티에서 저 서비스 연결해서 뭔가 뽑아내고자 할때 

unbindService(i);

 

* Life Cycle

          onCreate()

      |                       |

onStart()               onBind()

                 ...

             thread

      (장시간 이용할시)

                  ...

 onStop()               unBind()

      |                       |

          onDestroy()

 

 

onCreate() -> onStart() -> onStop()  -> onDestroy();

Binding할때 : onCreate() ->onBind() -> unBind() -> onDestroy();

 

onBind()

{

return new My();

}

 

class My extends Binder {

service getService();

return 0;

}

 

ServiceConnection타입의 객체 (interface) 를 inner class로 만듬.

 -  onServiceConnected(Binder b);, onServiceDisConnected() 두개 overriding해야됨.

    Connection완료된 다음에 Binding정보 넘겨주는 게 맞음.

    b.getService() 이런식으로..

 

BindService할때 매개변수로 ServiceConnection을 매개변수로 넘겨줌.

 

쓰레드를 얼마나 깔끔하게 짜느냐도 관건..

 

* Background Thread  (<-> Main Thread(UI Thread))

오래걸리는 작업이 있을 시 Background thread로 돌린다.

왜냐하면 5초이상 반응해주지 못하면 에러이기때문.

Binder-post()

 

[실습]

프로젝트 새로 생성 후,

res폴더밑에 폴더 raw하나 만들어서 kara.mp3, start.png, stop.png파일을 넣는다.

 

[AndroidManifest.xml]

Service 하나 추가한다.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="chap8.Service"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".Main"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    <service android:name="PlayService"></service>
</application>
    <uses-sdk android:minSdkVersion="7" />

</manifest>

 

[main.xml]

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical" android:layout_width="fill_parent"
 android:layout_height="fill_parent">
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal" android:layout_width="fill_parent"
  android:layout_height="wrap_content">
  <ImageButton android:id="@+id/ImageButton01"
   android:layout_width="wrap_content" android:layout_height="wrap_content"
   android:src="@raw/start"></ImageButton>
  <ImageButton android:id="@+id/ImageButton02"
   android:layout_width="wrap_content" android:layout_height="wrap_content"
   android:src="@raw/stop"></ImageButton>
 </LinearLayout>

 <ProgressBar
  android:id="@+id/ProgressBar01"
  android:layout_width="fill_parent" android:layout_height="wrap_content"
  style="?android:attr/progressBarStyleHorizontal"></ProgressBar>
</LinearLayout>

 

 

[PlayService.java]

package chap8.Service;

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;

public class PlayService extends Service implements Runnable {

 MediaPlayer player;
 
 boolean flag = true;
 private int duration;
 private int currentPosition;
 
 // getter, setter함수

 public boolean isFlag() {
  return flag;
 }

 public void setFlag(boolean flag) {
  this.flag = flag;
 }

 public int getDuration() {
  return duration;
 }

 public void setDuration(int duration) {
  this.duration = duration;
 }

 public int getCurrentPosition() {
  return currentPosition;
 }

 public void setCurrentPosition(int currentPosition) {
  this.currentPosition = currentPosition;
 }
 
 // thread 에 의해 실행되는 코드...
 // Bind되는 순간부터 run이 실행되면서 매 초마다 현재 Position를 설정한다.
 public void run() {
  // run을 빠져나가면 thread는 끝난다.
  // 장시간 해야되는건 주로 loop를 만들어 놓는다.
  while(flag) // 음원이 끝나면 나가라.
  {
   setCurrentPosition(player.getCurrentPosition());
   
   try {
    // sleep은 항상 try~cath와 같이 쓰여야 한다.
    Thread.sleep(1000); // milisecond unit
   } catch (Exception e) {
    // TODO: handle exception
   }   
  }  
 }
 
 @Override
 public IBinder onBind(Intent arg) {
  // TODO Auto-generated method stub
  player = MediaPlayer.create(this, R.raw.kara);
  setDuration(player.getDuration());
  player.start();
  
  // MediaPlayer의 음원 플레이 시간을 얻어내서 service의 데이터를
  // 업데이트 시키는 작업을 하는 thread
  //(null: 특별히 group값이 필요없음.
  // this: thread 돌릴 source, player는 이름
  Thread t = new Thread(null, this, "player");
  t.start(); // bind되는 순간 PlayService의 run()이 시작됨.
  
  return new MyBinder(); // bind될 객체 리턴해야됨.
 }

 @Override
 public void onDestroy() {
  // TODO Auto-generated method stub
  super.onDestroy();
  player.stop(); // service 멈추기
  flag = false; // thread가 멈출 수 있게 flag값 설정
 }

 @Override
 public void onStart(Intent intent, int startId) {
  // TODO Auto-generated method stub
  super.onStart(intent, startId);
  
//  player = MediaPlayer.create(this, R.raw.kara);
//  player.start();
  // SD카드의 여러 음악프로그램중 어떤걸 play할 것인지?
  // 음악이 끝났다는 신호를 받을 수 있다. 그러면 다음곡 실행시키기.
 }
 
 // Activity bind시 Activity에 전달시킬 객체
 public class MyBinder extends Binder {
  PlayService getService() {
   return PlayService.this;
  }
 }

}

 

[Main.java]

package chap8.Service;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.ProgressBar;

public class Main extends Activity implements OnClickListener, Runnable{
    /** Called when the activity is first created. */
 private ImageButton bt1;
 private ImageButton bt2;
 private ProgressBar bar;
 
 // service랑 bind해서 service 객체를 얻어 service 의 데이터에 접근하기 위해
 private PlayService pService;
 
 // UI Thread에 UI 변경작업을 지시하기 위해 선언
 private Handler handler = new Handler();
 
 // user event와 상관없이 장시간 동안 service에 접근해서 데이터 획득하는 역할
 private Thread background;
 
    @Override
    // 1. Main이 실행되면서 onCreate()함수가 가장 먼저 실행된다.
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        bt1 = (ImageButton)findViewById(R.id.ImageButton01);
        bt2 = (ImageButton)findViewById(R.id.ImageButton02);
       
        bt1.setOnClickListener(this);
        bt2.setOnClickListener(this);
       
        bar = (ProgressBar)findViewById(R.id.ProgressBar01);
        //bar.setOnClickListener(this);
    }

   
 public void onClick(View v) {
  // TODO Auto-generated method stub
  if(v == bt1)
  {
   Intent intent = new Intent(this, PlayService.class); // 명시적
   //startService(intent);
   // 2. 재생버튼을 누르면 OnClick이 실행되고,
   // 여기서 service를 bind시킨다.
   // Service에서는 onCreate(), onBind()까지 실행되게된다.
   bindService(intent, connection, Context.BIND_AUTO_CREATE);
   background = new Thread(null, this, "test");
   
  } else if(v == bt2)  {
   Intent intent = new Intent(this, PlayService.class);
   //stopService(intent);
   // stop버튼을 누르면 binding이 끊긴다.
   unbindService(connection);   
  } else if(v == bar) {
   //handler.post(updateBar);
   // UserEvent받아들일 수 있는 거는 SeekBar로만 할 수 있다.
   // ProgressBar는 시스템에 의해서만 동작된다.
  }
   
  
 }
 
 // bind 상태에 따라 자동 호출되는 메서드를 가지는 객체 선언
 private ServiceConnection connection =
  new ServiceConnection() {
   
   public void onServiceDisconnected(ComponentName name) {
    // TODO Auto-generated method stub
    pService = null;
   }
   
   public void onServiceConnected(ComponentName name, IBinder service) {
    // TODO Auto-generated method stub
    // IBinder타입을 PlayService.MyBinder타입으로 type-casting하고
    // getService로 서비스 가져온다.
    //3. Binding이 완료되면 Service 정보를 가져오고
    pService = ((PlayService.MyBinder)service).getService();
    //4. background로 thread를 실행시킨다.
    background.start(); // 이때부터 run()이 실행된다.
   }
 };
  
 // UI Thread 에게 넘겨줄 작업
 // Inner class - Runnable이 inteface이므로..
 private Runnable updateBar = new Runnable() {
  
  public void run() {
   // UI thread는 간단하게 짠다. loop문같은거 넣지않는다.
   // 6. bar가 새롭게 그려진다.
   bar.setProgress(pService.getCurrentPosition());
  }
 };
 
 // background thread가 작업할 내용을 가지는 메서드
 // 5. background thread는 돌면서 1초마다
 // UI updateBar thread한테 progress를 표시하라고 post한다.
 public void run() {
  // 전체 음원의 시간값으로 bar의 Max를 설정한다.
  bar.setMax(pService.getDuration());
  while(pService.isFlag())
  {
   try {
    Thread.sleep(1000);
    // 오늘의 key point!!
    // 1초마다 main thread한테 update progress bar하라고 날린다.

    handler.post(updateBar);
   } catch (Exception e) {
    // TODO: handle exception
   }
  }
  
 }
}



Class Overview

MediaPlayer class can be used to control playback of audio/video files and streams. An example on how to use the methods in this class can be found in VideoView. Please see Audio and Video for additional help using MediaPlayer.

Topics covered here are:

  1. State Diagram
  2. Valid and Invalid States
  3. Permissions

State Diagram

Playback control of audio/video files and streams is managed as a state machine. The following diagram shows the life cycle and the states of a MediaPlayer object driven by the supported playback control operations. The ovals represent the states a MediaPlayer object may reside in. The arcs represent the playback control operations that drive the object state transition. There are two types of arcs. The arcs with a single arrow head represent synchronous method calls, while those with a double arrow head represent asynchronous method calls.

MediaPlayer State diagram

From this state diagram, one can see that a MediaPlayer object has the following states

개발 Q&A에서 가끔 보던 질문이고 저 또한 질문 했던 내용 입니다.

이미지 버튼을 사용시 버튼을 클릭했을때와 땟을때의 처리를 해결 못해서 기본 안드로이드 버튼만
사용중이었습니다.

해결을 하려고 setBackgroundResource도 생각했었습니다만...

setBackgroundResource를 사용했을경우에는 버튼을 클릭했을경우엔 이미지가 바뀌지만
땟을경우에 그이미지가 그대로 남아있어서 스레드를 돌릴까도 생각도 했었는데요...

몇주전까지만해도 구글링을 해서도 찾지 못했던 내용 이었는데 오늘 그 해답을 찾았습니다 ㅠ.ㅠ

다른 api내용 찾다가 우연히 발견하게 되었습니다.

res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:gravity="center" xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TextView android:layout_width="wrap_content"
        android:layout_height="wrap_content" android:text="@string/hello" />

    <ImageButton android:id="@+id/imgBtn"
    android:background="@+drawable/playbutton_click"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    </ImageButton>
</LinearLayout>


res/drawable/playbutton_click.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="false" android:state_pressed="true"
        android:drawable="@drawable/btn1" />
    <item android:drawable="@drawable/btn" />
</selector>

drawable의폴더에는
버튼이 눌러졌을때의이미지와 버튼을 땟을때의 이미지파일이 존재하여야 합니다.




이렇게 간단하게 해결될 문제였답니다 ㅠ.ㅠ

많이 허접한 내용이지만 아직도 해결 못하신분들을위해 적어 봤습니다.

Service - 백그라운드 음악 실행 토요특강 / 안드로이드

2010/11/20 11:31

복사 http://blog.naver.com/jeggange/90100530068

Service

 

사용자와 상호작용 없이 내부적으로 실행되는 프로세스

- UI없이 오랫동안 살아있으면서 실행되는 코드들

- media player activity는 Context.startService()를 이용하여 백그라운드로 음악이 계속 재생되는 서비스 구동

- 서비스에 접근할 때, 서비스에 의해 나타난 인터페이스를 통해 서비스와 통신할 수 있다.

 

 

 

 

 

 

 

 

이미지 버튼과 음악 재생에 사용할 파일을 미리 준비해 둔다

미디어 파일은 /res/raw 폴더 생성

 

 

xml 버튼에 onClick 이벤트 달기

 


 android:id="@+id/btnStop" 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp"
    android:onClick="btnProcess" />

 

 

 

 

 

main.xml

 


http://schemas.android.com/apk/res/android"

    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >

    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="음악  즐기기" />

 android:id="@+id/btnStart" 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" 
    android:src="@drawable/pic"
    android:layout_marginTop="20dp"
    android:onClick="btnProcess" />

 android:id="@+id/btnStop" 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="서비스 중지"
    android:layout_marginTop="10dp"
    android:onClick="btnProcess" />

 android:id="@+id/btnExit" 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="어플 종료"
    android:layout_marginTop="10dp"
    android:onClick="btnProcess" />                   

 

 

 

 

 

Manifest.xml

 

       
       


        
 

MainApp.java

 

package aa.serviceEx;

import android.app.*;
import android.content.*;
import android.os.*;
import android.view.*;
import android.widget.*;

public class MainApp extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    public void btnProcess(View v) {
      Toast.makeText(this, "success", 2000).show();
      }
}

 

 

 

 

 

 

버튼 테스트를 위해 토스트를 달았다.

세가지 버튼을 누르게 되면 모두 같은 프로세스를 호출하기 때문에

같은 success 메시지가 나온다.

 

 

 

 

음악 재생 코드 추가

MainApp.java

 

package aa.serviceEx;

import android.app.*;
import android.content.*;
import android.os.*;
import android.view.*;
import android.view.View.*;
import android.widget.*;

public class MainApp extends Activity implements OnClickListener {
    /** Called when the activity is first created. */
 ImageButton btnStart;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        btnStart = (ImageButton)findViewById(R.id.btnStart);
        Button btnStop = (Button)findViewById(R.id.btnStop);
        Button btnExit = (Button)findViewById(R.id.btnExit);
        btnStart.setOnClickListener(this);
        btnStop.setOnClickListener(this);
        btnExit.setOnClickListener(this);
    }
   
    @Override
    public void onClick(View v) {
     if(v.getId() == R.id.btnStart) {
      startService(new Intent("aa.bb.cc.mbc"));
      btnStart.setEnabled(false);
      
     }
     else if(v.getId() == R.id.btnStop) {
      stopService(new Intent("aa.bb.cc.mbc"));
      btnStart.setEnabled(true);
      
     }
     else if(v.getId() == R.id.btnExit) {
      stopService(new Intent("aa.bb.cc.mbc"));
      btnStart.setEnabled(true);
      finish();
      
     }
    }
}

 



음악이 재생중인 상태이며,

백그라운드로 돌렸기 때문에 멀티태스킹이 가능하다.

 

 

 

 

알림 표시바 사용하기

- 시간이 나온 제일 윗 부분 드래그 해서 나오는 부분 Notification

 

MainApp.java에서 onclick 메소드 수정

 

    @Override
    public void onClick(View v) {
     // 알림 표시바 사용
     NotificationManager nm =
      (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
     
     if(v.getId() == R.id.btnStart) {
      startService(new Intent("aa.bb.cc.mbc"));
      btnStart.setEnabled(false);
      
      // Notification 처리
      Notification notification =
       new Notification(R.drawable.noti, "최신음악", System.currentTimeMillis());
      Intent intent = new Intent(this, MainApp.class);
      PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
      notification.setLatestEventInfo(this, "노래 서비스", "점심은 맛있게", pendingIntent);
      nm.notify(0, notification); // 상태표시바에 등장
     }else if(v.getId() == R.id.btnStop) {
      stopService(new Intent("aa.bb.cc.mbc"));
      btnStart.setEnabled(true);
      nm.cancel(0); // 상태 표시바에서 해제      
     }else if(v.getId() == R.id.btnExit) {
      stopService(new Intent("aa.bb.cc.mbc"));
      btnStart.setEnabled(true);
      nm.cancel(0); 
      finish();      
     }

 



 

 

 

 

MpPlayer.java

 

package aa.serviceEx;

import android.app.*;
import android.content.*;
import android.media.*;
import android.os.*;

public class MpPlayer extends Service {
 MediaPlayer mp;
 
 @Override
 public IBinder onBind(Intent intent) {
  return null;
 }
 
 @Override
 public void onStart(Intent intent, int startId) {
  super.onStart(intent, startId);
  mp = MediaPlayer.create(this, R.raw.man);
  mp.start();
 }
 
 @Override
 public void onDestroy() {
  super.onDestroy();
  mp.stop();  
  mp.release(); // 자원 반납
 }

} 


2010/08/04 16:11

출처 :  http://blog.naver.com/romistudio/50093624442

 http://blog.naver.com/romistudio/50093624442

질답 게시판에도 올려봤지만... 저만 이런 경우를 만난 것인지..아직도 알 수가 없네요.
에러 메시지는 Prepare failed status = 0x1 입니다.

인터넷을 검색해 봐도...뾰족한 답변이 없었습니다.
그러다...갑자기 하나 보인... 검색 결과물이 있었는데요..

http://www.anddev.org/viewtopic.php?p=16478

에서 ... 이런 글을 보게 되었습니다.

you store your tempfile in the application cache directory and the problem is that the MediaPlayer doesn't have access rights to application directories.

Instead you should passing a FileDescriptor to your MediaPlayer with setDataSource(FileDescriptor fd).

Something like this:
...
FileInputStream fis = new FileInputStream(bufferedFile);
FileDescriptor fd = fis.getFD();
mediaPlayer.setDataSource(fd);


결국... 저의 경우가 tempfile 이고. 어플의 캐쉬 폴더라는 것인지... 확신은 안가지만.. 위의 코드로 문제는 해결되었습니다.
http url 로 다운 받아.. /data/data/.../files 가 어플의 캐쉬 폴더?? 그리고. 내가 받은 파일이 임시 파일이라고?
논리는 안맞지만..여튼 위의 코드로 작동이 되었습니다.

먼저 게시판에 흔하게 보이는 코드이며..저 역시 사용한 코드는 다음과 같으며.. 그뒤 두번째가...위의 충고(?)를 바탕으로
작성된 코드입니다. 참고로... 흔히 보이는 코드 (아래 첫번째꺼) 로는 http:// .... 로 직접 접근해서 플레이하는건 잘됩니다.


01.try {
02. MediaPlayer mediaPlayer = new MediaPlayer();
03. mediaPlayer.setDataSource(pathinlocal+FileName);
04. mediaPlayer.prepare();   ---- 여기에서 런타임 에러 발생 Prepare failed : status = 0x1
05. mediaPlayer.start();
06.} catch (IOException e) {
07. // handle exception
08. //((EditText) ((Activity) mMain).findViewById(R.id.txtStatus)).setText(e.getMessage());
09.}



아래는 위의 충고를 바탕으로 작성되어 문제가 해결된 코드입니다.
01.try {
02. MediaPlayer mediaPlayer = new MediaPlayer();
03. FileInputStream fis = new FileInputStream(pathinlocal+FileName);
04. FileDescriptor fd = fis.getFD();
05. mediaPlayer.setDataSource(fd);
06. mediaPlayer.prepare();
07. mediaPlayer.start();
08.} catch (IOException e) {
09. // handle exception
10. //((EditText) ((Activity) mMain).findViewById(R.id.txtStatus)).setText(e.getMessage());


출처 : http://cafe.naver.com/ccjmaster.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=133

 

=========================================================================================

 

자바에서 처리하는 입력과 출력은 스트림(Stream)에 의존하다.

 

다시 말해 모든 형태의 입력과 출력은 1byte의 흐름으로 이루어져 있다는 이야기이다.

 

그런데 이러한 작업 처리를 텍스트 기반으로 한 형태로 바꿔 준다든지, 객체 기반으로 한 형태로 바꾸어 준다든지 하는 클래스가 있다.

 

우리는 먼저 1byte의 기본 입력과 출력 클래스 몇 가지를 공부하고 다음으로 각 형태로 변경시키는 클래스를 살펴보도록 할 것이다.

 

우선 1byte의 입력과 출력 기본 클래스는 InputStream과 OutputStream이다. 각 클래스의 상속관계는 다음과 같다.

 

  OutputStream

    ▶ FileOutputStream

    ▶ ByteArrayOutputStream

    ▶ PipedOutputStream

    ▶ ObjectOutputStream

    ▶ FilterOutputStream - BufferedOutputStream

    ▶ PaintStream

    ▶ DataOutputStream

 

  InputStream

    ▶ FileInputStream

    ▶ ByteArrayInputStream

    ▶ PipedInputStream

    ▶ ObjectInputStream

    ▶ SequenceInputStream

    ▶ AudioInputStream

    ▶ StringBufferInputStream

    ▶ FilterInputStream - BufferedInputStream

    ▶ LineNumberInputStream

         PushbackInputStream

         DataInputStream

 

여기에 표시된 많은 클래스를 다 공부한다는 것은 우리가 배우고자 하는 범위를 벗어나는 것이므로

 

실제로 파일 입·출력에서 많이 쓰는 형식을 한 가지씩만 외우도록 하자.

 

1byte 출력

 

  (1) 콘솔 출력용

    FileOutputStream fos = new FileOutputStream(FileDescriptor.out);
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    DataOutputStream dos = new DataOutputStream(bos);

    dos.write
 

  (2) 파일 출력용  
    File file = new File("파일명");
    FileOutputStream fos = new FileOutputStream(file);
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    DataOutputStream dos = new DataOutputStream(bos);

    dos.write
  

  (3) 네트워크 출력용
    Socket soc = new Socket();
    BufferedOutputStream bos = new BufferedOutputStream(soc.getOutputStream());
    DataOutputStream bos = new DataOutputStream(bos);

    dos.write

 

1byte 입력

 

  (1) 콘솔 입력용

    FileInputStream fis = new FileInputStream(FileDescriptor.in);
    BufferedInputStream bis = new BufferedInputStream(fis);
    DataInputStream dis = new DataInputStream(bis);
    dis.read()…
  

  (2) 파일 입력용
    File file = new File("파일명");
    FileInputStream fis = new FileInputStream(file);
    BufferedInputStream bis = new BufferedInputStream(fis);
    DataInputStream dis = new DataInputStream(bis);
    dis.read()…
  

  (3) 네트워크 입력용
    Socket soc = new Socket(…);
    BufferedInputStream bis = new BufferedInputStream(soc.getInputStream());
    DataInputStream bis = new DataInputStream(bis);
    dis.read()…

 

이제 간단한 형태의 입·출력 예제를 처리해 보도록 하자.

 

EX 01

 

import java.io.*;

public class Java {
  public static void main(String[] args) {
    File file = new File("C:\\java\\work\\abc.txt"); // C:\\java\\work\\abc.txt 에 대한 객체를 생성한다.
    try {
      FileOutputStream fos = new FileOutputStream(FileDescriptor.out); // 콘솔에 대한 출력 스트림을 생성한다.
      FileOutputStream fos1 = new FileOutputStream(file); // 파일에 대한 출력 스트림을 생성한다.
      byte[] data = {66, 68, 70, 72, (byte) '!'}; // B, D, F, H, ! 에 대한 배열을 생성한다.
      fos.write(data);
      fos1.write(data);
      // fos.close();
      // fos1.close();
    }catch(FileNotFoundException fnfe){
      System.err.println("파일을 못찾겠다.");
      System.exit(1);
    }catch(IOException io){
      System.err.println("파일 입출력 에러");
      System.exit(1);
    }
    System.out.println("실행 끝");
  }
}


 

EX 02

 

import java.io.*;

public class Java {
  public static void main(String[] args) throws FileNotFoundException, IOException{
    /*
    FileInputStream fis = new FileInputStream(FileDescriptor.in); // 키보드로부터 입력 객체를 생성한다.
    System.out.print("입력 = ");
    byte by = fis.read(); 
    */ 
    File file = new File("C:\\java\\work\\abc.txt"); // 파일로부터의 입력 객체를 생성한다.

    FileInputStream fis = new FileInputStream(file);  
    byte[] by = new byte[65536];
    int count = fis.read(by);
    for(int i = 0; i < count; i++){
      System.out.println(i + " : " + (char)by[i]);
    }
  }
}

 

EX03

 

import java.io.*;

public class Java {
  public static void main(String[] args) throws FileNotFoundException, IOException{
   

   /*

    < DataOutputStream을 풀어서 썼을 때의 코딩>
       File file = new File("c:\\java\\work");
       FileOutputStream fos = new FileOutputStream(file);
       BufferedOutputStream bos = new BufferedOutputStream(fos); // 512byte
       DataOutputStream dos = new DataOutputStream(bos);
   */
  
    // 1byte 출력을 위한 객체
    DataOutputStream dos1 = new DataOutputStream(new BufferedOutputStream(new FileOutputStream

    (new File(new File  "c:\\java\\wordk"),"HJH.txt")))); // 파일에 대한 출력 객체를 생성
    dos1.writeInt(23); // int형 숫자를 출력한다. 이것은 출력하면 파일에는 4byte의 영역을 확보하고 데이터가 표시된다.

                             // 그래서 결과가 이상하게 보인다.
    dos1.writeDouble(12.345); // double형 숫자를 출력한다. 역시 int형과 마찬가지로 8byte의 영역을 확보 후 데이터 표시

    dos1.writeBytes("ABCDEFG"); // 1byte씩 문자 형태로 출력한다. 정상적으로 보인다.

    dos1.close();
  }
}

 

EX04

 

import java.io.*;

public class Java {
  public static void main(String[] args) {
    DataInputStream dis1 = null;
    try{
      dis1 = new DataInputStream(new BufferedInputStream(new FileInputStream

      (new File(new File("c:\\java\\wordk"),"HJH.txt")))); // DataInputStream 입력 객체를 생성한다.
    } catch (FileNotFoundException fnfe){}
    int a = 0;
    double b = 0.0;
    byte[] c = null;
    try{
      a = dis1.readInt(); // int형 데이터를 입력받는다. 처음 4byte를 입력받아 저장해 둔다.
      b = dis1.readDouble(); // double형으로 데이터를 입력받는다. 다음 8byte를 입력받아 double형으로 변환한다.
      c = new byte[10]; // 문자 배열을 선언한 후 그곳에 결과를 입력받는다.
    dis1.read(c);
    dis1.close();
    }catch(IOException ie){}
   
    System.out.println("a = " + a);
    System.out.println("b = " + b);
    System.out.println("c = " + new String(c));
  }
}

'자바 > 자바팁' 카테고리의 다른 글

네이버 svn 설치방법 참고  (0) 2010.12.09
네이버 svn 설치방법  (0) 2010.12.08
색상표  (0) 2010.12.02
[펌]압축 관련 스트림 팁  (0) 2010.12.01
javax.swing.event 에서의 ListDataEvent 에 관한 설명  (1) 2010.11.17

안드로이드_개발_팁

<merge> 태그 설명
(android:sharedUserId) 하나의 프로세스에서 여러 애플리케이션 실행하기
(showDialog 사용중) is not valid is your activity running
(링크) 안드로이드 샘플로 들어 있는 NodePad (DB 사용예등..)
(링크) 안드로이드 스터디 Jni 발표 자료...
[번역] 안드로이드 2.0 Service API 변화
AccountManager 관련 내용
Activity Launch Mode
Activity가 화면에 보여질때 발생하는 이벤트
Activity내 배경을 투명하게 하기
Activity를 FullScreen으로 띄우기
Activity에 Dialog 적용하기
adb install이 잘 안될때..
adb 명령어 옵션들
adb 명령어로 응용프로그램 설치및 삭제
addContentView 사용예제
AlarmManager을 이용해서 특정시간뒤 서비스 실행하기
Android 1.5 소스 다운로드
Android 2.1 update and source code release
Android API Demo 사용해보기
Android Application Framework FAQ
Android comparing phone number to contacts list
Android cpu usage / running linux command
Android getting SMS message cursor
Android MD5 encryption
Android Orientation System 이미지
Android SDK 1.5 설치
Android SDK 화면 사이즈 변경하기
Android Search person’s name by contact id
Android send email gmail activity
Android sms received and sent event
android 데이터 베이스 변경시 ContentObserver활용하여 체크하기
Android 문서
android 바탕화면 소스 위치( )
Android 에서 Ant로 빌드시 참고할만한 내용
android 용 package와 jar 어떻게 만드나요.. !
android-log-collector (Locat의 로그를 이메일로 전송해주는 어플)
android.provider.ContactsContract 사용예
AndroidHttpClient 사용예제
Android에서 AutoCompleteTextView와 SQLite 연동하는 방법
andtweet / 안드로이드 트위터 오픈소스
AppWidget 예제
ArrayAdapter의 내용 변경 통지하는 notifyDataSetChanged() 사용예제
AssetManager (getAssets)을 이용해서 파일 읽어오기
AsyncTask에서 cancel 처리 예제
Background에 Shader 사용하기
Button 클릭하기
C/C++ 개발을 위한 Eclipse CDT 설치
Calendar 목록 읽어오기
Check phone is using roaming network
ClipboardManager 사용예제
Contact Provider Db에 접근하기
ContentProvider 사용예제
Cursor 내용을 AutoCompleteTextView 자동완성 하기
Dialog 사용예제
DOM과 SAX 파서의 차이점
Draw 9-patch
EditText / TextView 숫자만 허용
EditText 글자 출력 위치
EditText 글자수 제한하는 메소드
EditText에 대한 IME 옵션 설정및 옵션 클릭시 이벤트 처리
EditText에서 커서 위치를 지정하기
EditText와 TextView에 대해서 경계선 없애기
Email 데이터베이스에 접근
GestureDetector 사용예
getContentResolver()에 limit 추가하기
getDir()을 사용해서 디렉터리 생성하기
getSharedPreferences() 로 저장시 파일위치
glScissor, glEnable, glDepthMask 사용예제
GLSurfaceView 사용예제
Google Android developers resources / API tutorials and guides
GPS 상태 변화 감지 소스
GPS 시뮬레이터 사용방법
GPS 이용한 위치정보 얻어오기
GPS 이용한 위치정보 얻어오기
GUI 컴포넌트의 색깔과 동작변경하기 ( TextView의 attribute, java method 사용 )
Handler(핸들러) 사용예제
HttpClient 예제
HttpClient 예제
ImageButton의 테두리 영역 투명하게 하기
IME 관련
inbox내 SMS 문자 삭제하기
Intent 링크
Intent 사용예제
Intent 사용예제2
JNI 관련 참고할만한 사이트
JNI 작업시, Log 클래스 이용해서 디버깅 내용 출력하기
Keyguard 끄기(화면을 켰을 때 나오는 잠금장치를 없애기)
Language(랭귀지) 코드
Language(랭귀지) 코드
Layout with ListView and Buttons
ListView 우측의 Fast Scroll Thumb
ListView내 한Row로 TableLayout을 사용한 예제
ListView내 항목 클릭시 선택색상(주황색) 없애기
ListView에 Header 붙이기
ListView에 invalidate가 안먹는다면...
ListView에 Selector에 커스텀 색상부여하기
ListView에 교차로 행마다 색상 부여하기
Log, Trace 정보를 원격으로 관리해주는 (nullwire)
Logcat에 색상 부여하기
LogCat의 로그를 파일로 저장하기
Manifest 에서 VersionName 가져오기
MediaStore 사용하여 이미지의 폴더명 알아내기
Menu 생성방법
Menu에서 xml 로 추가한 메뉴에 대한 MenuItem 접근하기
mp3 음악 목록 출력
MP3 플레이어 (오픈소스 프로젝트)
Multicolumn ListView (멀티칼럼)
NDK (JNI) 설치 관련 정보
Notification Manager 사용예제
onInterceptTouchEvent 와 onTouchEvent 차이
onSaveInstanceState / onRestoreInstanceState
openFileOutput()으로 저장한 파일의 절대 패스 구하기
openGL ES 관련 내용 링크
OpenGL ES 관련 자료 링크
OpenGL ES 예제
OpenGL ES 함수정리
OpenGL 레퍼런스 사이트
OpenGL 삼각형 회원 예제
Orientation Sensor Tips in Android
PackageManager / getPackageArchiveInfo 로컬파일(apk)의 패키지 정보 알아내기
Parcelable Interface를 이용한 Activity 간에 데이터 전송
Post로 웹페이지 읽어서 WebView에 출력하기
Process 별 사용 메모리 정보 구하기
ProgressDialog 와 AsyncTask 사용예제
R.java 파일 고치기 ( Resource 파일 고치기 )
raw 폴더내 파일에 접근하기
Relative Layout 사용예제
res/raw 폴더내 리소스를 파일로 저장하기
SAXParser (XML 파서) 사용예제
Screen Orientation Change 될때, 임시적으로 데이터 보관하기
ScrollView에 ListView 넣기
ScrollView에 ListView 넣기
ScrollView에 ListView 넣을수 없다.
SDCard 경로
sdcard 사용 가능 여부
sdcard 사용하기
sdcard 상태 확인하기
sdcard내 특정 폴더가 쓰기 가능한지 체크하기
sdcard내 파일 저장
Service 란
Service내 비동기 호출 가능한 oneway 메소드 선언
SharedPreferences 데이터 추가/삭제 사용예제
SharedPreferences 변화 감지하기
SharedPreferences은 멀티 프로세서에 안전하지 않다
SimpleDateFormat 사용시 주의점
SimpleOnGestureListener에 ACTION_UP 이벤트 감지하기
SMS 메시지 보내기
SMS 메시지가 들어왔을때 처리 (IntentReceiver)
Socket 타임아웃 지정하기
sqlite3 사용예
style 관련 참조할만한 내용
SwitchView 사용해서 실행중 화면 전환하기
TextView 사용관련 여러가지 팁
TextView 한줄 높이 변경하기
TextView(EditText) 사용시 IME에 "Done" "Next" 표기
TextView/EditText에 숫자만 입력받게 하기
TextView내 글자가 흘러가는 효과(marquee) 주기
TextView내 글자에 하이퍼링크 속성 부여하기
TextView를 한줄로 표시 / 한줄로 표시 안될때 ... 로 표기하기
TextView에 Ticker (marquee) 효과주기
TextView에 커스텀하게 link 상태 만들기 (정규표현식 이용)
TextView의 테두리에 색상주기
TextView의 테두리에 색상주기2 (selector, shape 사용)
TextView의 테두리에 색상주기3
TimePickerDialog / DatePickerDialog 사용예제
TitleBar에 Progress Indicator 표기하기
Toast 사용예제
Toast 출력시간 연장하기
Toolchain 이란
Touch Simulate
Traceview (Graphical Log Viewer)
UI 다자이너 (사이트)
UI 쓰레드에서 Handler 사용
Uncaught Exception 핸들러
UriMatcher
vcard 관련 오픈소스
VideoView 사용예제
View mode를 Portrait 나 Landscape로 고정하고 싶을때
View.getTag/setTag and IllegalArgumentException 가 발생하면...
ViewBinder 사용예제
ViewFlipper "Receiver not registered" Error
ViewSwitcher 사용예
View에 뭔가 데이터를 집어넣을때 setTag / getTag
Webview , WebViewClient 사용예
WebView auto fit 하기
WebView 로딩시 타이틀바에 진행중 아이콘 보이게 하기
webview 스크롤
WebView 에서 자바 스크립트 사용예
WebView 웹페이지 로딩시간 구하기
WebView 클래스 기능
WebView 페이지가 로딩되었을때 처리
WebView, SimpleGestureListener 사용예
WebView를 사용한 앨범 구현
WebView에 멀티터치 관련
WebView에 새창(href)이 뜰때 웹브라우져가 아닌 현재 WebView로 출력하기
WebView에서 alert 기능 추가
WebView에서 Html 태그 추출하기
WebView에서 loadData 사용시 주의점
WebView에서 멀티 터치 가능하게 하기
WebView에서 멀티 터치 줌 가능하게 하기
WebView에서 문자열 선택하기
webview에서 유튜브 동작시키기
WebView에서 쿠키 처리 참고할 내용
WebView의 loadUrl, loadData, loadDataWithBaseURL 사용예제
Wifi 연결 상태 감지하기
wifi(와이파이)로 접속한 ip 주소 알아내기
Windows XP에서 안드로이드 SDK 설치하기
XML pull parser을 이용한 RSS Feed 분석하기
XmlPullParser를 이용해서 rss내 title 항목 읽기
YouTube Data API을 사용한 검색
간단한 TouchEvent 사용예제
간단한 소스코드 정리해놓은 사이트
개발시 성능에 대해서 고려해야 할사항
개발한 안드로이드 소프트웨어를 배포하려면
계정(Account) 목록 읽어오기
관련소스1
구글 안드로이드 마켓 입점 따라 하기 !!
구글맵 api키 받기
내장된 어플로 SMS 메시지 보내기
네트워크(network) 연결 상태 감지하기 (이벤트)
네트웍 연결, 와이파이, 3G 설정하기
넥서스 원(안드로이드) 소스 다운로드
다른 Activity 호출하기
단말기 폰번호 알아내기
동적으로 Locale 설정 변경하기
동적으로 외부의 jar 파일 로딩하기
라이브러리 프로젝트 생성하기
랭귀지 설정
레이아웃 xml 편집시 빈줄로 시작하면 안된다.
리소스 사용관련 참고 내용
리소스 참조할 새로운 라이브러리 추가하기
리소스내 String 배열 읽어오기
리소스명으로 해당 리소스 ID 구하기
마켓에서 패키지명에 해당하는 어플 찾도록 StartActivity 시키기
멀티터치 (Multi Touch) 구현 소스
멀티터치(Multi Touch) 상태 여부
모델 정보 알아내기
문자 입력기 IME 보이기 / 감추기
바코드 스캐너 오픈소스 정보
바탕 화면의 아이콘 모양 변경하기
바탕화면 배경(wallpaper) 관리
밧데리 상태 확인하기
배터리 잔량 조회
버튼 클릭시 설치된 이메일(email) 프로그램 열기
버튼 클릭하기(프로그래밍 상에서..)
버튼에 Selector 사용해서 Focus, Select, Default 등에 따라 배경설정하는 예제
볼륨 높이기 (setVolume)
부팅시 서비스 실행하기
서비스 라이프사이클 관련...
서비스 사용예제
서비스에서 Timer로 작업 처리하기
설치된 프로그램 삭제 (adb shell 사용)
소프트키에 대한 설정
스크롤(Scrollable)되는 TextView
스크린(screen) On / OFF 인덴트 수신하기
시간경과후 다이얼로그 자동 종료
시스템에서 날리는 주요 브로드캐스트 인텐트
실제 핸드폰에서 실행시키기
실행중인 프로세스 목록 알아내기 (ActivityManager)
쓰레드에서 UI 업데이트 하기
아날로그 시계/ 디지털 시계
아이폰용 OpenGL ES 강좌
안드로이드 2.1 샘플 목록
안드로이드 AIDL 문법(Android AIDL Syntax)
안드로이드 e-book /andbook (영문)
안드로이드 OCR (wordsnap-ocr)
안드로이드 opengl 소스 링크
안드로이드 SDK 1.5를 설치해보자!
안드로이드 SDK 다운로드및 설치
안드로이드 SDK와 안드로이드폰 연동하여 프로그램 설치 스샷
안드로이드 SMS 메시지
안드로이드 Transparency, Dim 처리 방법 (투명, 희미한)
안드로이드 개발환경 구축
안드로이드 게임 [Android_Virus_Mania]
안드로이드 관련 라이브러리 모음
안드로이드 기기별 고유 ID
안드로이드 기본 어플에는 종료 기능이 없다
안드로이드 멀티랭귀지 구현
안드로이드 모바일 네트웍 관리 프로젝트(APN data access toggle for Android)
안드로이드 바이너리 파일을 역컴파일 하기
안드로이드 바코드 스캐너 (zxing)
안드로이드 샘플 예제
안드로이드 소스받기
안드로이드 시스템 정보 출력하기
안드로이드 아키텍쳐 구조
안드로이드 아키텍쳐 구조 - 그림으로
안드로이드 애플리케이션 배포방법
안드로이드 어플 고속 드로잉 튜닝요령( )
안드로이드 오픈소스 다운로드
안드로이드 폰과 이클립스 연동시 스샷
안드로이드 프로그램을 디버깅하는 방법
안드로이드를 공부하려면
안드로이드에서 JNI 사용하기 링크 정리
안드로이드에서 동적으로 클래스 파일 로딩하기
안드로이드에서 지원하는 자바 표준 패키지
안테나 영역 없애기
애플리케이션내 아이콘 추가하기
액티버티 상태 정보 저장
액티버티(Activity)에서 애니메이션 효과주기
어플내의 화면을 캡쳐하기
여러 다이얼로그 사용예제
여러 컴포넌트 레이아웃에서 사용예
연결되어 있는 네트웍상태(3G, Wifi 인지) 확인
오디오 / 비디오 실행
외국 안드로이드 OCR 엔진(무료아님)
외장(sdcard)의 멀티미디어 파일(이미지, 오디오)의 변화 감지하기
원격지에서 Stack Trace 정보 받기
웹뷰에서 줌버튼 안보이게 하기
웹브라우져 띄우기
유일한 Android device ID
이메일(email) 보내기
이메일(email)로 이미지 보내기
이뮬내 DB 파일 가져오기
이뮬레이어터에서 SD-Card 이뮬레이터 하기
이뮬레이터 단축키
이뮬레이터 초기화
이뮬레이터 튜토리얼
이뮬레이터(AVD)의 사용 메모리 늘리기
이뮬레이터에 구글 계정등록하기
이뮬에서 Failed to open ringtone content://settings/system/notification_sound 에러가 발생하면...
이미지를 Stretch 하기 (nine patch 사용하여, 이미지가 컴포넌트에 가득차게)
일정 시간후 강제로 대기모드로 들어가게 하기
일정(Calendar) 화면(Activity) 띄우기
임시파일 생성
자신에게서 onClickListener 대신에 부모 레이아웃(컨테이너)에서 클릭처리
자주 사용되는 Intent Protocal 목록
전화 수신 감지하기 (recognize incoming phonecall)
전화가 왔을때 이벤트 수신하기
접촉식 한글 자판 최신 바이너리 (.apk)
제스쳐 (Gesture 관련정보)
주소록 사진 목록 읽어오기
주소록(contacts) 상세창 띄위기
주소록(contacts) 편집창 띄우기
주요 Intent 사용예제
증감현실을 Android 에뮬레이터에서 구동하는 toolkit - NyArToolkit
지도상(구글맵)에 현재 자신의 위치 표기하기 ( startActivity 사용)
찍은 사진에 대해서 영역을 자르기
차트(chart) 그래프 오픈소스
출력화면 캡쳐 참고할만한 소스
캘린더(일정) 삭제하기
캘린더(일정) 정보 읽어오기
커스텀(Custom) 위젯 만들기
클립보드내 텍스트가 존재하는지 체크
파일(File) 사용
폰 부팅후 현재까지 경과한 시간
폰(이뮬)내 설치된 SDK 버젼알기
폰에서 디버깅하기
폰의 랭귀지(언어) 설정 읽어오기
폰의 전원꺼짐및 Screen On/Off 제어 (PowerManager. newWakeLock)
폰트 변경하기
폴더 생성 및 파일 생성
프로그램 배포하기
프로그램 시작시 Locale 변경해서 멀티랭귀지 적용하기
프로그램 종료하기
한글 IME
해당 Action을 수행할수가 있는 액티버티(어플)이 존재하는지 찾기
헬로, 안드로이드 자료 분할압축1
헬로, 안드로이드 자료 분할압축2
현재 디바이스(폰)의 IP 주소 알아내기
현재 사용 가능한 메모리정보 얻어오기
현재 연주중인 오디오 어플을 음소거 하기
현재 폰의 orientation 값 구하기(portrait, landscape)
화면 portrait / landscape 제어하기
화면 모드( portrait / landscape) 가 전환될때, OrientationEventListener 이벤트 받아내기
화면 사이즈 구하기
화면 해상도 구하기
화면 회전(Landscape / Portrait)
화면복귀시 ListActivity에서 선택한 항목으로 이동시키기
화면이 가로/세로 모드로 전환시 onDestroy()가 호출되지 않도록 하기
효과음 관련 자료


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

소스코드


SD 카드에 저장되어 있는 이미지의 Thumbnails를 표시하기
Http connection , SaxParser and SharedPreferences 사용예제
Progressbar 사용예제
간단한 숫자 더하기 소스
계산기 소스
Custom View - HorizontalSlider
GridView 사용예제
ArrayAdapter 클래스를 사용해서 Gallery 클래스에 데이터 등록
Spinner 사용예제 (ArrayAdapter 사용)
버튼 사용예제
ListView 사용예제(ArrayAdapter 클래스를 사용)
ImageButton 사용예제 (리소스아이디 사용)
ImageButton 사용예제
ImageView내 이미지 출력 부분 지정하기
ImageView에 투명도(알파값) 지정하기
안드로이드 진행바 다이얼로그 예제
웹캠과 연동 예제
wifi 사용예제
ListActivity 예제 (동적으로 내용변경)
AutoCompleteTextView 사용예제
Menu 사용예제
Activity에서 전화걸기
ImageView 사용예제
Busy Coder's Guide 에서 나온 예제들
친구찾기 (FriendFind)
안드로이드 SDK - 바이오리듬 예제
위치정보 API를 사용하여 GPS 정보 취득 예제
구글 날짜 API 사용
화면에 볼튕기기
ImageView 사용예제
투명윈도우
MapView 사용예제2
MapView 사용예제1
WebView 내의 열람이력을 지운다
WebView 내에서 웹페이지 화면 확대/축소
WebView를 이용해서, 이전 웹페이지로 이동
WebView 사용예제
타이틀바의 글자색 변경
이미지를 crop해서 Bitmap 객체 생성하기
SurfaceView & Double Buffering (더블버퍼링)
AlertDialog 예제
Splash Screen
이미지파일 다운로드
URL을 통한 이미지 드로잉
Android SDK에 포함된 소스 구글링크
PopupWindow 사용예
WebView 사용예 (loadUrl, loadData)
UI Thread 사용예제
음악 스트리밍 소스
MP3 파일내 정보 추출
바이오리듬 자바 소스
동적으로 LinearLayout 화면에 이미지 추가하기2
동적으로 LinearLayout 화면에 이미지 추가하기
WebView 사용예
Android / SurfaceView 사용예제
카메라 제어
RSS Reader
SD 카드안의 음악파일 목록 출력하기
SD 카드에 저장되어 있는 비디오 목록 출력및 비디오 실행하기
3D 테트리스 게임 소스(1)
3D 테트리스 게임 소스(2)
탐색기
RSS Reader (리더) 소스
연락처(Contact) 계정 관리자
미디어 스트리밍(Custom Media Streaming with MediaPlayer)
로또(Lotto) 소스
간단한 MP3 플레이어 예제
폰내 음악 파일 목록 읽어오기
AutoCompleteTextView 사용예제
Twitter
MP3 파일 실행하기
XOR 예제
Service 예제
Gallery, ImageSwitcher 사용예제

Hey everyone,

Haven’t posted in a while – sorry school has been busy. Any who, this little code snippet/example will be on how to deal with the Intent.ACTION_SCREEN_OFF and the Intent.ACTION_SCREEN_ON, which will come in nifty if you’re making an application that might need to save state or respond to the user’s screen going to sleep/waking up, etc.

First, unlike other broad casted intents, for Intent.ACTION_SCREEN_OFF and Intent.ACTION_SCREEN_ON you CANNOT declare them in your Android Manifest! I’m not sure exactly why, but they must be registered in an IntentFilter in your JAVA code. And so, for this example we are going to have a receiver called ScreenReceiver, and I’m going to walk you through the differences between implementing it in a Service vs. in an Activity.

So, the receiver will simply look like:

01 public class ScreenReceiver extends BroadcastReceiver {
02  
03     // THANKS JASON
04     public static boolean wasScreenOn = true;
05  
06     @Override
07     public void onReceive(Context context, Intent intent) {
08         if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
09             // DO WHATEVER YOU NEED TO DO HERE
10             wasScreenOn = false;
11         else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
12             // AND DO WHATEVER YOU NEED TO DO HERE
13             wasScreenOn = true;
14         }
15     }
16  
17 }

Now, the first example will be for an Activity. Because of the life-cycle of an Activity, an Activity is actually easier to deal with as right before the screen turns off onPause() is called and right when the screen turns on onResume() is called, and so naturally we will handle the screen on/off events here:

01 public class ExampleActivity extends Activity {
02  
03    @Override
04     protected void onCreate() {
05         // INITIALIZE RECEIVER
06         IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
07         filter.addAction(Intent.ACTION_SCREEN_OFF);
08         BroadcastReceiver mReceiver = new ScreenReceiver();
09         registerReceiver(mReceiver, filter);
10         // YOUR CODE
11     }
12  
13     @Override
14     protected void onPause() {
15         // WHEN THE SCREEN IS ABOUT TO TURN OFF
16         if (ScreenReceiver.wasScreenOn) {
17             // THIS IS THE CASE WHEN ONPAUSE() IS CALLED BY THE SYSTEM DUE TO A SCREEN STATE CHANGE
18             System.out.println("SCREEN TURNED OFF");
19         else {
20             // THIS IS WHEN ONPAUSE() IS CALLED WHEN THE SCREEN STATE HAS NOT CHANGED
21         }
22         super.onPause();
23     }
24  
25     @Override
26     protected void onResume() {
27         // ONLY WHEN SCREEN TURNS ON
28         if (!ScreenReceiver.wasScreenOn) {
29             // THIS IS WHEN ONRESUME() IS CALLED DUE TO A SCREEN STATE CHANGE
30             System.out.println("SCREEN TURNED ON");
31         else {
32             // THIS IS WHEN ONRESUME() IS CALLED WHEN THE SCREEN STATE HAS NOT CHANGED
33         }
34         super.onResume();
35     }
36  
37 }

Now, note that in my onPause() and onResume() methods I run a check to see that the method was called DUE TO A SCREEN STATE CHANGE. This is important as often onPause() or onResume() will get called because of other reasons – i.e. a new activity is being started on top of this one, or an incoming call might be coming in, etc – and you want to make sure that your screen change logic is only called when the screen has actually changed.

Now, something to keep in mind, is that the order of events before the system screen turns off is:

ExampleActivity.onPause() –> ScreenReceiver.onReceive()

Which is a little unintuitive as you’d think the receiver would get hit first – and so when you play around with setting booleans, etc, be aware of this little fact, and likewise when the screen turns on the order of events is:

ExampleActivity.onResume() –> ScreenReceiver.onReceive()

And so again the order of events seems a little “backwards”.

Now, for a Service, it’s a little bit different since there is no onResume() or onPause() that gets called as the Service is always “running” in the background, and so instead what you’re going to have to do is modify your receiver a little to look like:

01 public class ScreenReceiver extends BroadcastReceiver {
02  
03     private boolean screenOff;
04  
05     @Override
06     public void onReceive(Context context, Intent intent) {
07         if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
08             screenOff = true;
09         else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
10             screenOff = false;
11         }
12         Intent i = new Intent(context, UpdateService.class);
13         i.putExtra("screen_state", screenOff);
14         context.startService(i);
15     }
16  
17 }

And your service will look like:

01 public static class UpdateService extends Service {
02  
03         @Override
04         public void onCreate() {
05             super.onCreate();
06             // REGISTER RECEIVER THAT HANDLES SCREEN ON AND SCREEN OFF LOGIC
07             IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
08             filter.addAction(Intent.ACTION_SCREEN_OFF);
09             BroadcastReceiver mReceiver = new ScreenReceiver();
10             registerReceiver(mReceiver, filter);
11         }
12  
13         @Override
14         public void onStart(Intent intent, int startId) {
15             boolean screenOn = intent.getBooleanExtra("screen_state"false);
16             if (!screenOn) {
17                 // YOUR CODE
18             else {
19                 // YOUR CODE
20             }
21         }
22 }

And so this is pretty self explanatory. When the screen state changes, it will notify your ScreenReceiver and from there you can set the state information into an Intent and send that data to your Service which can then handle it appropriately.

Hopefully this was useful. Let me know if you have questions.

Happy coding.

- jwei

[출처] http://cafe.naver.com/ccjmaster.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=168

<리니어 레이아웃>

 

 방향 설정

 

  차일드 뷰를 일렬로 배치하는 레이아웃이다.

 

  부모 뷰는 화면 전체, 차일드 뷰는 화면 하나하나를 구성하는 요소라고 보면 된다.

 

  ...

 

  리니어의 가장 중요한 속성은 배치 방향을 결정하는 orientation이다.

 

  차일드를 배치하는 방법은 수평(horizontal)·수직(vertical) 2가지가 있다.

 

  별도로 지정하지 않으면, default 속성은 수평(horizontal)이 적용된다.

 

<Button&Edit>

 

  앞서 우리가 했던 Button&Edit 에제에서

 

  orientation 속성만 vertical에서 horizontal로 바꾸어보자.

 

  Layout/Buttonedit.xml

 

  <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="vertical" // horizontal로 바꾸어보자.
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      >
  <EditText
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content"
      android:id="@+id/edit" 
      android:text="여기다 입력"
      />
  <Button
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:id="@+id/btn" 
      android:text="입력 완료"
      />
  </LinearLayout>

 

  기존의 verticla이었던 Button&Edit 예제                          horizontal로 수정한 예제

 

      

 

<TextView>

 

  기존의 했던 TextVeiw도 해보도록 하자.

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" // 마찬가지로 horizontal로 해본다.
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >

<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/insa"
    android:textColor="#ff0000"
    android:textSize="20pt"
    android:textStyle="italic"
    />
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/anyoung"
    android:textSize="20sp"
    android:textColor="#0000ff"
    />
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Good Morning"
    android:textColor="#8000ff00"
    android:textSize="5mm"
    android:typeface="serif"
    />
</LinearLayout>

 

  그리고 실행해보면 Hello 텍스트 하나만 나오고, 두 문자열을 화면에서 사라져 버렸다.

 

  

 

  왜냐하면 텍스트 뷰의 layout_width 속성이 fill_parent로 되어 있어 부모의 폭 전체를 다 차지하기 때문이다.

 

  셋 모두 보이게 하려면, 텍스트 뷰의 layout_width의 속성을 wrap_content로 바꿔 자신의 폭만큼 차지하도록 수정해야 한다.

 

<?xml version="1.0" encoding="utf-8"?> // xml 문서에서는 주석이 통하지 않으므로 복사 후 제거하고 실행한다.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    > 
<TextView  
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="@string/insa"
    android:textColor="#ff0000"
    android:textSize="20pt"
    android:textStyle="italic"
    />
<TextView  
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="@string/anyoung"
    android:textSize="20sp"
    android:textColor="#0000ff"
    />
<TextView  
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="Good Morning"
    android:textColor="#8000ff00"
    android:textSize="5mm"
    android:typeface="serif"
    />
</LinearLayout>

 

  바꾸고 실행해보면 이렇게 나온다.

 

  

 

  -----------

 

  정렬지정

 

  뷰의 영역이 충분히 크면 상하좌우에 넓은 여백이 생긴다.

 

  하지만 뷰가 커진다고 해서 내용물도 같이 커지는 것은 아니며, 이때 내용물을 뷰의 어느 쪽에 배치할 것인지의 문제가 생긴다.

 

  ...

 

  내용물을 뷰의 어느 쪽에 배치할 것인가는 gravity 속성으로 지정한다. 즉, 내용물의 정렬 방식은 gravity로 통제한다.

 

  수평, 수직 방향에 대해 각각 정렬 방식을 지정할 수 있으며 '|' 연산자로 두 개의 속성을 묶어서 지정할 수도 있다.

 

  두 속성을 같이 지정할 때는 '|' 연산자 양쪽으로 공백이 전혀 없어야 한다.

 

  ...

 

  각 정렬은 비트 필드로 정의 되어 있으며

 

  contet와 fill은 수평, 수직 정렬 상태 플래그의 조합으로 정의되어 있다.

   

 

  이 속성을 테스트하기 위해 예제를 만들어보자.

 

  리니어 레이아웃 안에 폭과 높이를 둘 다 fill_parent로 지정했다.

 

  리니어 전체를 텍스트 뷰로 가득 채웠으므로, 텍스트 뷰의 넓이는 화면 전체와 같으며 여백이 굉장히 많은 상황이다.

 

  Layout/gravity1.xml

 

    <?xml version="1.0" encoding="utf-8"?> 
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="vertical"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      >
  <TextView  
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      android:text="정렬 테스트"
      android:textSize="30px"
      android:textColor="#00ff00"
      />
</LinearLayout>

 

  gravity 속성을 따로 지정하지 않았으므로, 디폴트인 좌상단이 적용되며 문자열이 텍스트 뷰의 왼쪽 위에 출력된다.

 

  

 

  다음과 같이 gravity 속성을 center로 지정해 보자.

 

  Layout/gravity2.xml

 

  <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="vertical"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      >
  <TextView  
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      android:text="정렬 테스트"
      android:textSize="30px"
      android:textColor="#00ff00"
      android:gravity="center"
      />
  </LinearLayout>

 

  실행해보면 center는 center_horizontal|center_vertical과 같음을 알 수 있다.

 

  수평, 수직, 모두 중앙이므로 문자열이 텍스트 뷰의 정중앙에 나타날 것이다.

 

  

 

  수평, 수직 각각에 대해 다른 정렬 방향을 지정할 수도 있다. 이번에는 다음과 같이 바꿔보자.

 

  Layout/gravity3.xml

 

    <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="vertical"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      >
  <TextView  
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      android:text="정렬 테스트"
      android:textSize="30px"
      android:textColor="#00ff00"
      android:gravity="center_vertical"
      />
  </LinearLayout>

 

  Layout/gravity4.xml

 

    <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="vertical"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      >
  <TextView  
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      android:text="정렬 테스트"
      android:textSize="30px"
      android:textColor="#00ff00"
      android:gravity="center_vertical|right"
      />
  </LinearLayout>

 

  center_vertical을 지정하면 수직으로는 중앙이 되고, 수평쪽으로는 디폴트인 왼쪽이 적용되어 중앙 왼쪽에 문자열이 나타난다.

 

  물론 '|' 연산자로 묶어 별도의 정렬 방식을 지정할 수 있다. 수직으로는 중앙, 오른쪽에 정렬하면 오른쪽에 붙는다.

 

      

 

  문자열을 오른쪽 바닥에 정렬하려면 "bottom|right"으로 지정하면 되고, 상단 중앙은 "center_horizontal|top"으로 지정하면 된다.

 

  그렇다고 아무 조합이나 다 되는 것은 아니고, 수평·수직 한 방향에 대해 플래그 하나씩 2개만 조합이 가능하다.

 

  gravity 속성 하나만 놓고 보면 어렵지 않을 것이다.

 

  ...

 

  그런데 gravity와 유사한 속성으로 layout_gravity 라는 속성이 또 있다.

 

  사용할 수 있는 속성 값은 gravity와 동일하나, 적용되는 대상이 다르다.

 

   · gravity : 뷰 안의 내용물을 어디에 배치할 것인가?

 

   · layout_gravity : 뷰를 부모의 어디에 둘 것인가?

 

  방금 전에 했던 gravity2의 예제와 비교를 한다면, 이해가 빠를 것이다.

 

  Layout/gravity2 // 텍스트 뷰를 리니어에 가득 채우고, 내용물을 center에 옮긴다.

 

  <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="vertical"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      >
  <TextView  
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      android:text="정렬 테스트"
      android:textSize="30px"
      android:textColor="#00ff00"
      android:gravity="center"
      />
  </LinearLayout>

 

  

 

  Layout/layout_gravity2 // 텍스트 뷰를 문자열 크기로 설정하고, 텍스트 뷰 자체를 리니어의 중아에 배치한다.

 

  <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="vertical"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:gravity="center"
      >
  <TextView  
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:text="정렬 테스트"
      android:textSize="30px"
      android:textColor="#00ff00"
      android:background="#ff0000"
      />
  </LinearLayout>

 

  

 

  분명 같은 그림이지만, 내용은 다르다.

 

  두 방법은 분명한 차이가 있는데, 리니어의 gravity의 속성을 사용하면

 

  두 개 이상의 차일드 뷰를 묶어서 원하는 곳에 배치할 수 있다는 점이다.

 

  Layout/lgravity3.xml

 

  <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="vertical"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:gravity="center"
      >
  <TextView  
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:text="정렬 테스트"
      android:textSize="30px"
      android:textColor="#00ff00"
      android:background="#ff0000"
      />
  <Button
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:text="버튼이다."
      />
  </LinearLayout>

 

  두 차일드 뷰가 중앙에 수직으로 나란히 배치되며 겹치지도 않는다.

 

  두 차일드의 집합이 리니어의 입장에서 볼 때는 내용물이며, 따라서 center 속성이 적용되어 중앙에 온다.

 

  차일드 집합 내부에서는 수직 리니어의 배치 규칙에 따라, 두 위젯이 수직으로 나란히 놓인다.

 

  

 

  gravity는 내용물의 정렬 상태를 지정하며, layout_gravity는 뷰 자체의 정렬 상태를 지정한다.

 

  다음 예를 보면 이 두 속성의 차이점과 적절한 활용처를 분명히 알 수 있을 것이다.

 

  Layout/lgravity4.xml

 

  <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="vertical"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      >
  <TextView  
      android:layout_width="200px" 
      android:layout_height="100px" 
      android:text="정렬 테스트"
      android:textSize="30px"
      android:textColor="#00ff00"
      android:background="#ff0000"
      android:layout_gravity="center_horizontal"
     android:gravity="right|bottom"

      />
  </LinearLayout>

 

  layout_gravity는 차일드 뷰를 정렬하므로, 수평으로 중앙에 놓았다.

 

  gravity는 내용을 정렬하므로, 차일드 뷰의 오른쪽 아래에 놓았다.

  

 

  알고보니 차~암 쉽죠?


컬러 이름

16진수

 

             
 red #FF0000    
crimson #DC143C    
firebrick #B22222    
maroon #800000    
darkred #8B0000    
brown #A52A2A    
sienna #A0522D    
saddlebrown #8B4513    
indianred #CD5C5C    
rosybrown #BC8F8F    
lightcoral #F08080    
salmon #FA8072    
darksalmon #E9967A    
coral #FF7F50    
tomato #FF6347    
sandybrown #F4A460    
lightsalmon #FFA07A    
peru #CD853F    
chocolate #D2691E    
orangered #FF4500    
orange #FFA500    
darkorange #FF8C00    
tan #D2B48C    
peachpuff #FFDAB9    
bisque #FFE4C4    
moccasin #FFE4B5    
navajowhite #FFDEAD    
wheat #F5DEB3    
burlywood #DEB887    
darkgoldenrod #B8860B    
goldenrod #DAA520    
gold #FFD700    
yellow #FFFF00    
lightgoldenrodyellow #FAFAD2    
palegoldenrod #EEE8AA    
khaki #F0E68C    
darkkhaki #BDB76B    
lawngreen #7CFC00    
greenyellow #ADFF2F    
chartreuse #7FFF00    
lime #00FF00    
limegreen #32CD32    
yellowgreen #9ACD32    
olive #808000    
olivedrab #6B8E23    
darkolivegreen #556B2F    
forestgreen #228B22    
darkgreen #006400    
green #008000    
seagreen #2E8B57    
mediumseagreen #3CB371    
darkseagreen #8FBC8F    
lightgreen #90EE90    
palegreen #98FB98    
springgreen #00FF7F    
mediumspringgreen #00FA9A    
teal #008080    
darkcyan #008B8B    
lightseagreen #20B2AA    
mediumaquamarine #66CDAA    
cadetblue #5F9EA0    
steelblue #4682B4    
aquamarine #7FFFD4    
powderblue #B0E0E6    
paleturquoise #AFEEEE    
lightblue #ADD8E6    
lightsteelblue #B0C4DE    
skyblue #87CEEB    
lightskyblue #87CEFA    
mediumturquoise #48D1CC    
turquoise #40E0D0    
darkturquoise #00CED1    
aqua #00FFFF    
cyan #00FFFF    
deepskyblue #00BFFF    
dodgerblue #1E90FF    
cornflowerblue #6495ED    
royalblue #4169E1    
blue #0000FF    
mediumblue #0000CD    
navy #000080    
darkblue #00008B    
midnightblue #191970    
darkslateblue #483D8B    
slateblue #6A5ACD    
mediumslateblue #7B68EE    
mediumpurple #9370DB    
darkorchid #9932CC    
darkviolet #9400D3    
blueviolet #8A2BE2    
mediumorchid #BA55D3    
plum #DDA0DD    
lavender #E6E6FA    
thistle #D8BFD8    
orchid #DA70D6    
violet #EE82EE    
indigo #4B0082    
darkmagenta #8B008B    
purple #800080    
mediumvioletred #C71585    
deeppink #FF1493    
fuchsia #FF00FF    
magenta #FF00FF    
hotpink #FF69B4    
palevioletred #DB7093    
lightpink #FFB6C1    
pink #FFC0CB    
mistyrose #FFE4E1    
blanchedalmond #FFEBCD    
lightyellow #FFFFE0    
cornsilk #FFF8DC    
antiquewhite #FAEBD7    
papayawhip #FFEFD5    
lemonchiffon #FFFACD    
beige #F5F5DC    
linen #FAF0E6    
oldlace #FDF5E6    
lightcyan #E0FFFF    
aliceblue #F0F8FF    
whitesmoke #F5F5F5    
lavenderblush #FFF0F5    
floralwhite #FFFAF0    
mintcream #F5FFFA    
ghostwhite #F8F8FF    
honeydew #F0FFF0    
seashell #FFF5EE    
ivory #FFFFF0    
azure #F0FFFF    
snow #FFFAFA    
white #FFFFFF    
gainsboro #DCDCDC    
lightgrey #D3D3D3    
silver #C0C0C0    
darkgray #A9A9A9    
lightslategray #778899    
slategray #708090    
gray #808080    
dimgray #696969    
darkslategray #2F4F4F    
black #000000    


[출처] : http://bluejames77.blog.me/80015770905

자바에서 압축을 할려면 ZipInputStream과 GZIPInputStream을 써야 합니다.

 

이것을 이용해서 압축하는 예제를 JUNIT으로 만들어 보았습니다.

 

일단 예제를 보여드리기에 설명을 드리겠습니다.

 

1. ZipInputStream과 GZIPInputStream과의 차이점은 무엇인가요?

=> 쉽게 zip은 원도우에서 gzip은 유닉스나 리눅스에서 쓴다고 보시면 됩니다.

그러나 원도우에서도 gzip으로 압축해도 됩니다. gzip으로 하면 한글도 잘 압축됩니다.

zip은 한글 압축이 안되는데 이것은 따로 말씀드리도록 하겠습니다.

그리고 zip은 여러개를 한꺼번에 압축이 가능합니다. gzip은 지원이 안됩니다.

 

2. java.util.zip.ZipInputStream은 왜 한글 문서는 압축할 수가 없나요?

=> 이것은 썬의 버그라고 합니다. 썬것으로는 영문파일밖에는 안됩니다 -0-;

그래서 만약 한글 문서도 압축할려고 할려면 외국 개발자가 픽스해 놓은 클래스를 써야 합니다.

이것은 제가 첨부파일로 올려 놓겠습니다.

자세한 것은 이 URL을 참조하세요 마지막 덧글에 제 아이디도 보입니다 -_-a

http://www.javaservice.net/~java/bbs/read.cgi?m=resource&b=jdk&c=r_p&n=1100737475&k=압축&d=tb#1100737475

아래는 okjsp에서 pistos님이 답변해준 내용입니다.

java.util.zip은 압축파일내의 파일명 인코딩을 UTF-8로 처리해서 그래요.. 
zip 포맷이라는게 압축파일내의 파일명에 사용하는 인코딩을 지정하지 않았고, OS마다 encoding이 달라서 썬에서는 요걸 UTF-8로 정해놓고 쓰기로 한거라네요.. 
다음 버그리포트를 참고하시면 될거구요.. 

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4244499

 

3. flush()와 close()의 차이점과 쓰는 용도를 알고 싶습니다.

=> 스트림은 하나의 관이라고 보시면 됩니다 예를 들어 하수관 -_-;

즉 바이트의 흐름입니다. 중요한게 입력스트림은 입력만 가능하고 출력 스트림은 출력만 가능합니다.

생각해보세요 물을 받는 호스에서 갑자기 물이 역류한다면? 이 무슨 황당한 시츄에이션? 말이 안되죠? ^^;

flush()는 있는 물을 쏟아 버린다고 생각하시면 됩니다.

그래서 출력스트림에서 flush()를 해버리면.. 있는것을 다 털어 버리는거죠 예를 들면 호수를 탈탈 터는것!

그리고 close()는 수도 꼭지를 잠그는 것이라고 생각하면 됩니다. 우리가 보통 수도꼭지 잠글때 호스도 털죠?

호스 다 썼으니깐 털어야 하잖아요. ^^;

그래서 close()를 하면 호스를 털고[flush()] 수도꼭지를 잠근것[close()]한 것과 같은 의미입니다. 

close()하고 다시 쓸려면? open은 따로 없습니다. ^^; 다시 생성하셔야 합니다. 

 

4. ZipInputStream에만 있는 ZipEntry가 무슨 역할을 하는 것인가요?

=> ZipInputStream은 1번에서 말씀드렸다시피 여러개의 파일을 한꺼번에 압축할 수 있습니다.

원래 ZIP 파일이란 것이 하나 이상의 압축 파일을 포함하는데, 이때 각각의 파일은 ZIP 엔트리(Zip Entry)라고 합니다
Zip 엔트리는 ZipEntry 클래스의 객체로 표현되며, ZipEntry는 엔트리의 이름인 String 객체를 취하는 생성자를 가집니다.

이것도 예제(testFileZipComplex)를 보시면 금방 이해가 가실것입니다.

 

5. 이것도 디비처럼 꼭 close() 해줘야 하나요?

=> 넵 말이 필요없습니다!. 철저한 자원관리! ^-^;

예제를 보시면 제가 앞의 메소드들은 안하다가 뒤로 갈수록 했는데요.. 사실 이러시면 안됩니다!!

실전에서는 꼭 finally에서 닫아주는 센스!! 잊지마세요.

 

예제는 총 7개가 있습니다.
1. atestFileCopy 
 -> 파일카피 (스트림의 기본이라서 넣어 봤습니다 ^^;)
2. atestFileZipSimple
 -> 단순한 파일 압축. 한글깨지는 문제가 있음. 썬의 버그임 외국개발자가 버그 픽스한 라이브러리로 처리.
3. btestFileZipSimple2
 -> // 간단 압축된 파일 풀깅~ 
4. atestFileZipInOut2()
 -> ZipOutputStream을 이용한 압축 및 해제. 순서 1. 원본파일 -> 압축 -> 압축해제 후 원본파일 복귀
5. atestArrayFileZip()
 -> ZipOutputStream의 setLevel을 1-9까지 돌려보며 속도와 압축률 비교.
6. atestFileGZipInOut()
 -> GZIPOutputStream을 이용한 압축 및 해제. 순서 1.원본파일->압축->압축해제 후 원본파일복귀
7. testFileZipComplex
 -> 여러개의  파일을 하나의 zip파일로 압축.

 

소스 보시면 다 이해가 갈것입니다. 맛배기로 5번의 결과값을 보여드립니다. ^-^;

 

자바 디폴트 압축레벨8

Catalysis소개0.zip make Sucessed
Catalysis소개0.zip Size = 2086874 byte
 압축에 걸린 시간 측정 220 millisecond

Catalysis소개1.zip make Sucessed
Catalysis소개1.zip Size = 1548156 byte
 압축에 걸린 시간 측정 421 millisecond

Catalysis소개2.zip make Sucessed
Catalysis소개2.zip Size = 1541146 byte
 압축에 걸린 시간 측정 411 millisecond

Catalysis소개3.zip make Sucessed
Catalysis소개3.zip Size = 1534771 byte
 압축에 걸린 시간 측정 440 millisecond

Catalysis소개4.zip make Sucessed
Catalysis소개4.zip Size = 1526945 byte
 압축에 걸린 시간 측정 481 millisecond

Catalysis소개5.zip make Sucessed
Catalysis소개5.zip Size = 1520943 byte
 압축에 걸린 시간 측정 541 millisecond

Catalysis소개6.zip make Sucessed
Catalysis소개6.zip Size = 1516023 byte
 압축에 걸린 시간 측정 510 millisecond

Catalysis소개7.zip make Sucessed
Catalysis소개7.zip Size = 1515002 byte
 압축에 걸린 시간 측정 561 millisecond

Catalysis소개8.zip make Sucessed
Catalysis소개8.zip Size = 1513484 byte
 압축에 걸린 시간 측정 922 millisecond

Catalysis소개9.zip make Sucessed
Catalysis소개9.zip Size = 1512840 byte
 압축에 걸린 시간 측정 1081 millisecond

 

보시면 알겠지만 setLevel이 높을수록 압축률이 높고 속도가 떨어집니다. ^^;

디폴트는 8입니다.

 

ZipInputStream을 이해하는데 많은 도움이 되었으면 합니다. ^-^;

 

ps1 jazzlib_0.07은 외국개발자가 픽스해 놓은 소스.

      jazzlib.zip은 제가 위의 소스를 jar로 묶은것.

 

ps2 틀린점이나 추가할 사항이 있으시면 지적해 주는 센스!! 아시죠? ^^

mp3 player를 만드는 도중 첫번째 단계가 탐색기라서 한번 만들어봤습니다.

화면구성은 다음과 같습니다.

(암호필요)


학습내용
1. 기본 ListActivity에 커스텀 Adapter 활용
2.기본적인 자바 파일입출력
3.기본적인 화면 전환 에니메이션 활용(overridePendingTransition사용)

기본적인 탐색기라서 별 설명드릴 것도 없는듯..

최종 루트가 SD카드로 정해놓았습니다.

그리고 풀소스는 불펌방지 위해 암호설정했습니다.

암호필요하신 분은 댓글에 메일주소적어주시면 보내드리겠습니다..수고하세요^^


안드로이드의 기본적인 액티비티간 화면 전환 효과는 우에서 좌로 새로운 액티비티가 넘어와

 

화면이 전환되는 형태로 굉장히 심플하고 어떻게 보면 볼품 없다고 생각할 수도 있다 -_-ㅋ

 

이에 간단한 방법으로 액티비티 전환 시 Fade효과를 주어 좀 더 부드럽고 고급스러운

 

화면 전환 효과를 이용해 보자.

 

 

 

- 첨부파일 2개 (fade.xmlhold.xml)를 다운 받는다.

 

res 폴더 밑에anim라는 폴더를 생성해준다음 그 밑에 위에서 다운 받은 파일 2개를 넣어준다.

 

- 이동전 액티비티의 소스코드에서 다음 액티비티를 호출하는 부분인 startActivity(intent);

 

 밑에 다음의 코드를 넣어준다.

 

overridePendingTransition(R.anim.fade, R.anim.hold);

 

 

 

이 외에도 다양한 xml파일을 이용하여 액티비티 전환 시 다양한 화면 효과가 연출 가능하다.

출처 : http://lonelyshadow.tistory.com/77

개발을 하다보면 어플리케이션 전체에서 적용되는 전역 변수, 혹은 단 하나의 인스턴스를 사용해야할 때가 있다.

현재 XMPP를 이용하여 개발을 하고 있는데, connection을 단 하나만 유지해야한다.

보통 Java를 사용할 때는 Singleton을 이용하여 유일한 인스턴스를 생성하는데, (나도 처음에 Android Activity, Service와는 별개로 Singleton을 만드는 Class를 만들었었고..)

이 Singleton에서 Activity나 Service로 데이터를 주고 받는 것이 여간 어려운 일이 아니다.

실제로 만들었을 때도, Service에서 Singleton에 있는 인스턴스를 받아오려고 했더니 인스턴스를 새로 생성하고... 하여간 문제가 많다 -_-...

그런데 조금 찾아보니, Android에서 Singleton을 사용할 필요가 없었다.

Android에서는 어플리케이션 전체에 사용되는 변수 및 함수를 넣어놓는 Application Class가 있기 때문이다.

Activity 생성때와 마찬가지로 Application을 상속받아서 Application Class를 만들고,

Menifest.xml에서 현재 존재하는 application 항목에 android:name을 추가하여 만들어진 Application Class의 이름을 넣어주면 된다.

Application Class에는 Context가 존재하기 때문에, SQLiteDatabase도 바로 사용할 수 있으므로 데이터 주고 받는 것이 굉장히 편해진다. 물론 Singleton의 장점을 사용할 수 있는 것은 두말할 필요도 없고.

onCreate()로 Application 실행시의 동작을 정해주고

onTerminate()로 종료시의 동작을 정해줄 수도 있다.

Activity에서 불러올 때는,

ApplicationClassName ACN = (ApplicationClassName)getApplicationContext();
으로 생성하여 사용하면 되겠다
Bundle extras = new Bundle(); 
extras
.putSerializable("aa", Object); 
intent
.putExtras(extras); 
... 
 
Object y = getIntent().getExtras().get("aa"); 

=========================================== 
1 Vector<LOGINDATA> vvv = new Vector<LOGINDATA>();
2 Intent intent = new Intent();
3 intent.putExtra("key", vvv);


백터가 컬랙션이기 때문에 직렬화가 가능해서 위와같이 넣고 받아서 뺄때는 아래와 같이 하면 되요. ^^

 
1 Vector<LOGINDATA> rrr = (Vector<LOGINDATA>)intent.getExtras().getSerializable("key");

freedraw.zip


작성자의 티스토리 : http://javaexpert.tistory.com


다름이 아니라 이번에 처음으로 만든 어플이 있어서 올려봅니다.

올리는 이유는 펍가족님들에게 조언 좀 얻을려구영..^^;



device.pngmain.png

 

 

용기있는 왕초보의 프로젝트입니다..이름은 허접한 그림메모 어플..^^;;;;;; ==;

어플 기능 소개

1.기본적인 리스트

2.미리보기 기능 구현

3.프리드로우 기능 구현(자바 그대로 구현)

4.옵션 메뉴 기능 구현

학습된 내용

1.커스텀 CursorAdapter 공부

2.인텐트 기본 공부

3.Bitmap 기본 변환 공부

4.기본 입출력 공부

5.기본 직렬화 IO 공부

6.DB 기본 컨트롤 공부 등등

단 2장짜리 어플이지만 상당히 공부된 걸로 판단됩니다..^^;;

최적화는 못했습니다..아직 실력이..T.T

사인안된 .apk하나랑 (unsigned랑 sign이랑 있는데 뭔지 잘 모르겠음..ㅋ)

풀소스 올려봅니다. 아주 초보분들은 조금이라도 도움될듯..고수분들에게 보이기엔 상당히 부끄럽습니다..^^;

이제 몇개월만 더 하면 과정 끝나서 안드로이드 취업해야 하는데.... 더 분발해야 할듯..

혹시 여기 올리면 안되면 바로 지우겠습니다..


작성자 블로그 : http://javaexpert.tistory.com
작성자 메일주소 : bear2u@naver.com


저번 발로 만든 어플 첫번째인 그림메모에 이어 두번째 어플을 만들긴 했습니다.

너무 소스가 부끄러워 그냥 제 블로그에다 넣을려고 했으나 저랑 비슷한 왕초보분들이 상당히 많이 계신것 같아서 또 용기있게 올려봅니다.


 

개략 설명============================================================================
일반 핸드폰에 있는 매시간 알림
서비스입니다.

기본 UI는 한장이며(솔직히 디자인도 어려운 안드로이드임..==;)
alarm1.png
alarm2.png

소스또한 그리 어렵지는
않습니다..하지만 이걸 구현하기 위한 저의 개발시간은 또 일주일..^^;

그리고 AlarmManager 의 setRepeating도
있는 데 Interval로 주기적으로 하는 건데 이상하게 하다 꼬여
서 그냥 주기적으로 Set하면 다시 Set하는 방식으로
했는데..참 난감합니다..^^;;


학습내용

1.broadreceive 기본적인 사용방법 숙지
2.Service 기본
구현방법 숙지
3.인텐트 필터 공부
4.알람메니저 기본 구현방법 숙지
5.Preference 사용방법 숙지..(이것도 하다
BroadReceive에서 받아올줄 몰라서 DB로 바꿔서 이 소스에선 안씀..^^;;

아무튼 간단한 거라도 만드니 상당한 공부가
되는 건 확실하네요^^

그럼 간략하게 소스 설명해드리겠습니다.

하지만 먼저..버그가 좀 있습니다.

1.알람시간이 정확하게 정해지지가 않습니다.
예)5시에 올려야 하는 데 5시 10초정도에 울린다던가..그런경우..도저히 못 잡겠음..T.T
...아시는 분 댓글 부탁..
2.BroadReceive나 Service에서 preference에 접근할려면 어떻게 해야 하는 지 모르겠네요

(아시는 분 댓글 부탁드립니다)

소스는 다음과 같습니다..

대략적인 프로세스 흐름은

1.엑티비티를 실행하면 위와 같은 한장의 UI가 나옵니다.
2. 그럼 실행 클릭합니다.
3.인텐트 액션명을 지정해서 Broad합니다.그럼 Receiver가 받겠죠?

1.intent = new Intent();
2.intent.setAction("org.exam.Alarm_action");
3.this.sendBroadcast(intent);

4.Receiver에선 서비스를 실행합니다.

1.Intent mIntent = new Intent(context,AlarmService.class);   
2.  mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3.  if(!dbHandler.getIsFirst())
4.   new MyThread(context).start();
1.context.startService(mIntent);

5.서비스에서 AlarmManager를 객체 생성후 배운대로 PendingIntent를 설정합니다..(책보고 하긴 했지만 아직 머하는 놈인지 자세히는..)

1.AlarmManager manager =
2.   (AlarmManager)getSystemService(Context.ALARM_SERVICE);
3.   
4.  Intent mIntent = new Intent(AlarmService.this,BroadAlarmManager.class);
5.  mIntent.putExtra("id",1);
6.  PendingIntent sender = PendingIntent.getBroadcast(AlarmService.this,0,mIntent,0);

6.이제 문제의 Calendar를 설정합니다..(솔직히 이부분에서 조언을 받았으면 합니다..)

01.Calendar calendar = Calendar.getInstance();
02.calendar.setTimeInMillis(System.currentTimeMillis());
03. 
04.int mHour = calendar.get(Calendar.HOUR);
05.int mHin = calendar.get(Calendar.MINUTE);
06.int mSec = calendar.get(Calendar.HOUR);
07. 
08.Log.i("Time","1:"+mHour);
09.Log.i("Time","2:"+mHin);
10.Log.i("Time","3:"+mSec);
11. 
12.calendar.add(Calendar.MINUTE, 59-mHin);
13.calendar.add(Calendar.SECOND, 60-mSec);
14. 
15.mHour = calendar.get(Calendar.HOUR);
16.mHin = calendar.get(Calendar.MINUTE);
17.mSec = calendar.get(Calendar.HOUR);

대략 위의 소스대로 하면 다음 알람 시간은 예) 6시 00분 07초에서 10초사이에 설정됨

7.이제 AlarmManager으 Set으로 설정합니다.

1.manager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
2. 
3.Toast.makeText(this, "알람등록완료", Toast.LENGTH_SHORT).show();

8.그럼 시간이 지나고 또 지나고 매시간 정각이 되는 순간이 아니라..좀 몇초지나서..ㅋㅋ 소리가 나옵니다..(띵똥 몇시..)

소리 나오는 건 Receiver에서 옵션을 잡아서 재생하게 합니다.

여기선 쓰레드를 이용해서 하긴 했지만 뭐 굳이 안해도 될것 같더군요...^^;

01.MyThread(Context ctx){
02.   this.mCtx = ctx;
03.   calendar = Calendar.getInstance();
04.   calendar.setTimeInMillis(System.currentTimeMillis());
05.   AudioManager mAudioManager = (AudioManager) ctx.getSystemService(Context.AUDIO_SERVICE);
06.   volume =  mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
07.  }
08.  public void run(){
09.    
10.    
11.   /*
12.   int hour = calendar.get(Calendar.MINUTE);
13.    
14.   String sHour = String.valueOf(hour);
15.    
16.   if(sHour.length() >1)
17.    sHour = sHour.substring(1, sHour.length());
18.    
19.   Log.i("Receive","hour:"+sHour);
20.   */
21.   //int am = calendar.get(Calendar.AM);
22.    
23.   int tHour = calendar.get(Calendar.HOUR);
24.   Log.i("Time","thread hour : "+tHour);
25.   //if(am==0)
26.    //tHour--;
27.   MediaPlayer mp = MediaPlayer.create(mCtx, getHourVal(tHour));
1.mp.setVolume(volume, volume);
2. mp.start();
3.  
4.  
5.}


그럼 여기서 생기는 의문은 왜 Activity에서 바로 알람을 실행안하고 이렇게 약간 복잡하게 할까..

그건 부팅후에도 실행할려고 하기 때문입니다.

인텐트 필터를 적용해 액션 및 부팅 후 Broad도 잡게끔 되어있습니다.

서비스 등록및 filter 적용한 부분입니다.

1.<service android:name="AlarmService"/>
2.<receiver android:name=".BroadAlarmManager">
3. <intent-filter>
4.  <action android:name="android.intent.action.BOOT_COMPLETED" />
5.  <action android:name="org.exam.Alarm_action" />
6.   
7. </intent-filter>
8.</receiver>


이상으로 간략적인 흐름은 끝냈습니다.

적다보니 상당히 간단하지만....하지만..힘들지만 재미있네요^^

풀소스는 여전히 밑에 첨부되어 있으니 보고 마구 지적해주세요. 지적은 대환영입니다..^^

여담이지만 이 어플은 항상 요양원에 계시는 아버지께서 갤럭시를 사드렸는데 시간알리미가 없어서 불편하다가 해서 기존에 있는 걸 까는 것 보다 자식이 만든 걸 깔아 드리게 되었습니다. 지금 만족하시네요^^

그럼 다들 수고하세요.

출처 : http://pulsebeat.tistory.com/18


<목표> 
[안드로이드] Preference – UI 정보, 간단한 변수 저장하기

   

 

  이번에는 Preference에 대해 다루어 보겠습니다. Preference(이하 프리퍼런스)는 화면 이동 시 간에 발생하는 데이터 손실을 방지하기 위해 사용되는 자료형입니다. 간단한 예로 들자면, 친구에게 메시지를 보내기 위해 열심히 문자를 쓰고 있는 와중에, 전화와 온다고 가정합시다. 전화를 받고 나서 긴 장문의 메시지가 날라간다면 어떤 느낌이 들까요? 이런 일을 방지하기 위해서 프리퍼런스라는 자료형을 사용합니다. 화면 전환 시, UI 정보를 저장하고, 다시 그 화면으로 돌아왔을 때의 UI 정보를 불러와서 다시 화면에 뿌려주는 역할을 합니다. 이 밖에도 화면 전환 시에 저장하고 싶은 데이터를 저장할 수도 있습니다. 즉 간단하게 말하면, 임시 저장소라고 생각하시면 될 것 같습니다.

   

[핵심코드]   Preference

   

엑티비티 변환 데이터를 저장합니다.

SharedPreferences prefs = getSharedPreferences("PrefName", MODE_PRIVATE);

SharedPreferences.Editor editor = prefs.edit();

editor.putString(KEY_MY_PREFERENCE, text);

editor.commit();

엑티비티를 다시 실행하였을 데이터를 불러옵니다.

SharedPreferences prefs = getSharedPreferences("PrefName", MODE_PRIVATE);

String text = prefs.getString(KEY_MY_PREFERENCE, "");

   

   

  아래의 예제에서는 간단하게 두 엑티비티 간의 화면이 바뀌었다가 다시 돌아왔을 때 제대로 프리퍼런스가 동작이 되고 있는지 확인합니다.

     

   

STEP 1  Java Source Code

   

  자바 코드는 두 가지를 다루게 됩니다. 첫 엑티비티는 시작화면으로, 간단히 데이터를 입력하고 화면을 전환시킵니다. 두 번째 엑티비티는 별다른 기능없이 다시 첫번째 엑티비티로 돌아가는 역할만 수행합니다.

   

     

[[Activity]]   Preference 를 이용한 첫 번째 엑티비티

   

package example.preference;

   

import android.app.Activity;

import android.content.Intent;

import android.content.SharedPreferences;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

   

   

public class PreferenceTestActivity extends Activity {

   

public static final String KEY_MY_PREFERENCE = "my_preference";

@Override

   public void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);

   setContentView(R.layout.main);

   

   Button bt = (Button)findViewById(R.id.nextButton);

   bt.setOnClickListener(new View.OnClickListener() {

              

            @Override

            public void onClick(View v) {

                Intent intent =

                new Intent(PreferenceTestActivity.this, NextActivity.class);

                startActivity(intent);

            }

        });

   

   SharedPreferences prefs = getSharedPreferences("PrefName", MODE_PRIVATE);

   String text = prefs.getString(KEY_MY_PREFERENCE, "");

      // 번째인자는 , 두번째 인자는 키에 대한 데이터가 존재하지 않을 경우의 디폴트값

     final EditText edit =(EditText)findViewById(R.id.text);

   edit.setText(text);

}

   

    // onStop() : 이상 엑티비티가 사용저에게 보여지지 않을 불립니다.

    //          기존에 존재하는 데이터를 저장합니다.

   protected void onStop() {

    super.onStop();

   

   EditText editText =(EditText)findViewById(R.id.text);

   String text = editText.getText().toString();

   

       // 데이타를 저장합니다.

   SharedPreferences prefs = getSharedPreferences("PrefName", MODE_PRIVATE);

   SharedPreferences.Editor editor = prefs.edit();

   editor.putString(KEY_MY_PREFERENCE, text);

   editor.commit();

   }

}

     

[Activity ①]   SharedPreferences 이용하여 데이터 저장하기

   

  첫 번째 엑티비티로 화면에서 간단한 UI를 조작하고 있습니다. 버튼을 클릭하면 Intent를 이용하여 다음 엑티비티로 전환합니다. 화면을 전환하게 되면 onStop()이 호출이 되게 되며, 이 상태에서 저희가 사용할 프리퍼런스를 이용해서 데이터를 저장해야합니다. 위의 코드에서 보는 것처럼 SharedPreFerences라는 데이터 유형을 사용해야 합니다. 안드로이드 자체에서 제공해주는 자료형으로써, getSharedPreferences( Key값, Permission값 ) 메서드를 호출하여 자료형의 속성을 지정할 수 있습니다.

"PrefName" 은 말그대로 자신이 정하고 싶은 Key 값이라고 보시면 됩니다. 다음에 데이터를 호출할 때 이 Key 값을 이용하여 그 자료형을 불러올 수 있습니다. 다음 인자는 이 자료형에 대한 권한 설정을 해주는 부분입니다. MODE_PRIVATE, MODE_WORLD_READABLE, MODE_WORLD_WRITEABLE 을 이용하여 이 파일에 대한 접근 권한을 설정합니다.

   

MODE_PRIVATE

-rw-rw----

MODE_WORLD_READABLE

-rw-rw-r--

MODE_WORLD_WRITEABLE

-rw-rw--w-

   

  위에서 보시는 것과 같이 이 데이터에 대한 권한을 설정할 수 있습니다. 리눅스 개발을 한번이라도 접해신분들이라면 곧바로 이해가 되실 겁니다. 이렇게 저장된 프리퍼런스는 xml 형태로 저장이 됩니다. (소스 내에 존재하진 않습니다.) 패키지 파일 내에 있는 shared_prefs 영역에 선언된 SharedPreferences 자료가 저장되어 있는 것을 확인하실 수 있습니다.

  이렇게 저장된 프리퍼런스를 이용하여 Editor라는 자료형으로 선언합니다. 말 그대도 편집하기 위해서 선언을 한 뒤에, 자신이 저장하고 싶은 데이터 이름을 설정해주고, 저장하고 싶은 변수를 넣으면 저장이 됩니다. 그리고 마지막으로 commit()을 호출하면 데이터가 저장됩니다.

   

[[Activity ②]]   SharedPreferences 이용하여 데이터 불러오기

   

  이제 저장한 데이터를 이용하여 불러와야 합니다. 불러오는 부분은 엑티비티가 생성 시, 즉 onCreate( ) 부분에 넣으면 됩니다. SharedPreferences를 설정해주고, 미리 정해둔 Key 값을 넣어 데이터를 불러오면 됩니다. 아주 간단하게 작업이 이루어집니다.

  엑티비티의 라이프 사이클을 고려하여, 해당하는 부분에 알맞도록 프리퍼런스가 동작하도록 설정해주면, 입맛에 맞게 이용할 수 있습니다.

   

   

[[Activity]]   단순히 뒤로갈 수 있게 만드는 두 번째 화면 엑티비티

   

두 번째 화면 엑티비티는 테스트를 위해 필요한 부분입니다. 단순히 다시 화면으로 돌아갔을 때 원래의 값이 남아 있는지 확인 하는 부분입니다. 엑티비티를 생성하시고 간단히 뒤로 가는 버튼을 넣어주면 됩니다. 별다른 어려운 점이 없는 부분이니 넘어가겠습니다.

   

 class NextActivity extends Activity {

   

    public void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);

   setContentView(R.layout.next);

   

   Button bt = (Button)findViewById(R.id.previousButton);

   bt.setOnClickListener(new View.OnClickListener() {

              

            @Override

            public void onClick(View v) {

                Intent intent =

                new Intent(NextActivity.this, PreferenceTestActivity.class);

                startActivity(intent);

            }

        });

  }

}

    

     

STEP 2  Xml Code

     

   첫 번째 엑티비티는 텍스트뷰와 에디트박스, 버튼으로 구성되어 있습니다. 에디트박스에 있는 데이터가 저장되고 다시 돌아왔을 때 저장되었는지를 확인합니다. 제대로 저장이 되어 있다면, 쓰고 있던 메시지가 그대로 저장이 되어야 합니다.

   

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

>

   <TextView

   android:layout_width="fill_parent"

   android:layout_height="wrap_content"

   android:text=" 엑티비티"

   />

   <EditText

   android:id="@+id/text"

   android:layout_width="fill_parent"

   android:layout_height="wrap_content"

   />

   <Button android:text="다음으로"

   android:id="@+id/nextButton"

   android:layout_width="wrap_content"

   android:layout_height="wrap_content"></Button>

</LinearLayout>

   

  두 번 째 엑티비티는 첫 번째 엑티비티를 이용하여 돌아가기 위해 버튼만 구현해 놓았습니다.

   

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

>

   <TextView

   android:layout_width="fill_parent"

   android:layout_height="wrap_content"

   android:text="다음 엑티비티"

   />

   <Button android:text="이전으로"

   android:id="@+id/previousButton"

   android:layout_width="wrap_content"

   android:layout_height="wrap_content">

   </>

</LinearLayout>

   

   

STEP 3  AndroidManifest.xml Code

   

  메니페스트에는 다음 엑티비티를 허용하겠다는 퍼미션만 추가하면 됩니다.

     

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="example.preference"

android:versionCode="1"

android:versionName="1.0">

   <application android:icon="@drawable/icon" android:label="@string/app_name">

   <activity android:name=".PreferenceTestActivity"

android:label="@string/app_name">

      <intent-filter>

         <action android:name="android.intent.action.MAIN" />

         <category android:name="android.intent.category.LAUNCHER" />

       </intent-filter>

      </activity>

     <activity android:name=".NextActivity"></activity>

   </application>

</manifest>

   

   

   

 < 마무리 >  프리퍼런스(Preference)를 이용하여 간단한 데이터 저장하기

   

  화면 이동 시 일어날 수 있는 데이터 손실을 미리 방지하기 위해 프리퍼런스를 사용합니다. 이러한 간단한 정보를 데이터베이스를 이용하여 접근하는 것은 속도와 효율적인 면에서 큰 손실이 아닐 수 없습니다. 그렇기 때문에 안드로이드에서 제공해주는 SharedPreferencs라는 데이터 유형으로 프로그래밍 내에서의 변수 선언처럼 간단히 데이터를 저장하고 불러 올 수 있습니다. 엑티비티의 각각의 라이프 사이클에 맞게 데이터를 저장, 불러오기를 한다면 조금 더 사용성에 이점이 있도록 어플리케이션을 개발할 수 있습니다.


  • 게임에서 다양한 효과음을 멀티체널로 호출할 수 있는 SoundManager 클래스입니다.
  • 소스는 구글링중에 예제소스 수정하였습니다.

     

[SoundManager.java]

package kr.co.joynuri.animalorchestra;

import java.util.Collection;
import java.util.HashMap;

import android.content.Context;
import android.media.AudioManager;
import android.media.SoundPool;
import android.util.Log;

public class SoundManager {
   
    private static final String LOG_TAG = SoundManager.class.getSimpleName();
   
    private Context mContext;
    private SoundPool mSoundPool;
    private HashMap<Integer, Integer> mSoundPoolMap;
    private AudioManager  mAudioManager;
   
    public SoundManager(Context context) {
        mContext = context;
    }
   
    public void create() {
        mSoundPool = new SoundPool(16, AudioManager.STREAM_MUSIC, 0);
        mSoundPoolMap = new HashMap<Integer, Integer>();
        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
    }
   
    public void destroy() {
        if (mSoundPoolMap != null) {
            Collection<Integer> soundIds = mSoundPoolMap.values();
            for (int soundId : soundIds) {
                mSoundPool.unload(soundId);
                Log.d(LOG_TAG, "destroy sound id " + soundId);
            }
            mSoundPoolMap = null;
        }
    }
   
    public void load(int key, int resId) {
        Log.d(LOG_TAG, "load...START");
       
        mSoundPoolMap.put(key, mSoundPool.load(mContext, resId, 1));
       
        Log.d(LOG_TAG, "load...END");
    }
   
    public void play(int key) {
        Log.d(LOG_TAG, "play...START");
       
        int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        mSoundPool.play(
                mSoundPoolMap.get(key),
                streamVolume, streamVolume,
                1, 0, 1f);
       
        Log.d(LOG_TAG, "play...END");
    }
   
    public void playLoop(int key) {
        Log.d(LOG_TAG, "playLoop...START");
       
        int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        mSoundPool.play(
                mSoundPoolMap.get(key),
                streamVolume, streamVolume,
                1, -1, 1f);
       
        Log.d(LOG_TAG, "playLoop...END");
    }
   
    public void stop(int key) {
        mSoundPool.stop(mSoundPoolMap.get(key));
    }
   
    public void pause(int key) {
        mSoundPool.pause(mSoundPoolMap.get(key));
    }
   
    public void resume(int key) {
        mSoundPool.resume(mSoundPoolMap.get(key));
    }
   
}

 

사용예) 사운드 등록

        int coundIndex = 0;
        mSoundManager = new SoundManager(mContext);
        mSoundManager.create();
        mSoundManager.load(coundIndex++, R.raw.snd_animal_0);
        mSoundManager.load(coundIndex++, R.raw.snd_animal_1);
        mSoundManager.load(coundIndex++, R.raw.snd_animal_2);
        mSoundManager.load(coundIndex++, R.raw.snd_animal_3);
        mSoundManager.load(coundIndex++, R.raw.snd_animal_4);
        mSoundManager.load(coundIndex++, R.raw.snd_animal_5);
        mSoundManager.load(coundIndex++, R.raw.snd_animal_6);
        mSoundManager.load(coundIndex++, R.raw.snd_animal_7);
        mSoundManager.load(coundIndex++, R.raw.snd_animal_8);

사용예) 사운드 해제

        mSoundManager.destroy();

사용예) 사운드 플레이

        mSoundManager.play(index);

 



효과음 사용시 무거운 MediaPlayer 가 아닌 SoundPool 사용을 권장하는 가이드 블로그가 있어서 링크합니다. 
자세히 설명이 되어 있는데 영어라 좀 알아먹기 힘들군요 ㅎㅎ


본문 예제샘플
http://www.droidnova.com/blog/wp-content/uploads/2009/10/SoundTutorial.zip


자바로 우선 스노우크래프트 만든 다음

안드로이드로 옮겨보자..내실력에 과연 될까나..==;;

여기에 apk주소 넣은 다음 축약해서 문자메세지로 보낸다음 wifi로 apk다운받음..귀찮아지넹..ㅋ

http://goo.gl/

+ Recent posts