'안드로이드' 카테고리의 다른 글
문자열 자동완성 (0) | 2011.01.27 |
---|---|
전화중인 상태 체크하기 (0) | 2011.01.27 |
멀티 터치 구현 예제 (0) | 2011.01.27 |
spring framework 적용하여 controller 에서 error stacktrace 에러 내용이 찍히지 않을때 (0) | 2011.01.27 |
java.lang.Annotation(주석:@) (0) | 2011.01.27 |
문자열 자동완성 (0) | 2011.01.27 |
---|---|
전화중인 상태 체크하기 (0) | 2011.01.27 |
멀티 터치 구현 예제 (0) | 2011.01.27 |
spring framework 적용하여 controller 에서 error stacktrace 에러 내용이 찍히지 않을때 (0) | 2011.01.27 |
java.lang.Annotation(주석:@) (0) | 2011.01.27 |
public boolean onTouchEvent(final MotionEvent event)
{
final int action = event.getAction();
if(mIsMultiTouchSupported)
{
switch (action & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_POINTER_DOWN : {
if(mActivePointerId == -1)
{
final int pind = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
int pid = event.getPointerId(pind);
final int x = (int)event.getX(pid);
final int y = (int)event.getY(pid);
if(pointInArea(x, y))
{
mActivePointerId = pid;
// System.out.println("down pointer x = "+x+" , y = "+y);
onAction(UIAREA_ACTION_DOWN, x, y);
}
}
}
break;
case MotionEvent.ACTION_DOWN: {
if(mActivePointerId == -1)
{
final int x = (int)event.getX();
final int y = (int)event.getY();
if(pointInArea(x, y))
{
mActivePointerId = event.getPointerId(0);
// System.out.println("down x = "+x+" , y = "+y);
onAction(UIAREA_ACTION_DOWN, x, y);
}
}
break;
}
case MotionEvent.ACTION_MOVE: {
if(mActivePointerId != -1)
{
// Find the index of the active pointer and fetch its position
final int pointerIndex = event.findPointerIndex(mActivePointerId);
final int x = (int)event.getX(pointerIndex);
final int y = (int)event.getY(pointerIndex);
onAction(UIAREA_ACTION_MOVE, x, y);
}
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = -1;
break;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = event.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
final int x = (int)event.getX(mActivePointerId);
final int y = (int)event.getY(mActivePointerId);
mActivePointerId = -1;
// System.out.println(" up x = "+x+" , y = "+y);
onAction(UIAREA_ACTION_UP, x, y);
}
break;
}
}//end of switch
}
else
{
switch (action)
{
case MotionEvent.ACTION_DOWN: {
final int x = (int)event.getX();
final int y = (int)event.getY();
if(pointInArea(x, y))
{
// System.out.println("down x = "+x+" , y = "+y);
onAction(UIAREA_ACTION_DOWN, x, y);
}
break;
}
case MotionEvent.ACTION_MOVE: {
final int x = (int)event.getX();
final int y = (int)event.getY();
if(pointInArea(x, y))
{
// System.out.println("move x = "+x+" , y = "+y);
onAction(UIAREA_ACTION_MOVE, x, y);
}
break;
}
case MotionEvent.ACTION_CANCEL: {
break;
}
case MotionEvent.ACTION_UP:{
final int x = (int)event.getX();
final int y = (int)event.getY();
onAction(UIAREA_ACTION_UP, x, y);
break;
}
}//end of switch
}
return true;
}
전화중인 상태 체크하기 (0) | 2011.01.27 |
---|---|
Telephony 기능 (0) | 2011.01.27 |
spring framework 적용하여 controller 에서 error stacktrace 에러 내용이 찍히지 않을때 (0) | 2011.01.27 |
java.lang.Annotation(주석:@) (0) | 2011.01.27 |
View Fipper (0) | 2011.01.27 |
spring error stacktrace 에러 내용이 찍히지 않을때
[
에러가 발생하게 되면 보통 stacktrace 의 객체에 저장된 내용을 print 해서 문제를 파악하게 된다.
하지만 spring framework 에서 위와 같이 간단하게 표현되는 경우가 있다.
그 원인을 찾기 위해서 Controller 가 상속받은 클래스를 따라 올라가다 보니
MultiActionController 함수중에 Exception 이 발생할때 실행되는 놈이 있는데 그 함수가
아래와 같다.
protected Method getExceptionHandler(Throwable exception){
Class exceptionClass = exception.getClass();
if(logger.isDebugEnabled())
logger.debug("Trying to find handler for exception class [" + exceptionClass.getName() + "]");
Method handler;
for(handler = (Method)exceptionHandlerMap.get(exceptionClass);
handler == null && !exceptionClass.equals(java.lang.Throwable.class);
handler = (Method)exceptionHandlerMap.get(exceptionClass))
{
if(logger.isDebugEnabled())
logger.debug("Trying to find handler for exception superclass [" + exceptionClass.getName() + "]");
exceptionClass = exceptionClass.getSuperclass();
}
return handler;
}
내용을 보면 대충 알겠지만 logger.isDebugEnabled 일때 Trying to find handler 을 print하는걸 볼수 있다.
이 옵션을 어떻게 바꿔야 될지 더 찾아봐야겠지만 당장은 MultiActionController 상속받아
클래스를 만든후 getExceptionHandler 오버로딩 해서 기능을 변경하는것이 편할것 같다.
방법은 exception 객체에서 StackTraceElement[] 배열을 가져온후 그내용을 StringBuffer
저장하여 log4j 로 출력하는 절차이다. 문자열을 구성한 로직은 일반적인 에러 출력형태를
취해서 print 한다. 다음은 오버로딩한 함수의 내용이다.
protected Method getExceptionHandler(Throwable exception){
StackTraceElement[] element = exception.getStackTrace();
StringBuffer errorBuff = new StringBuffer(exception.getMessage());
errorBuff.append("\n");
for (int i=0; i < element.length; i++){
errorBuff.append("\tat ").append(element[i]).append("\n");
}
log.debug(errorBuff.toString());
return super.getExceptionHandler(exception);
Telephony 기능 (0) | 2011.01.27 |
---|---|
멀티 터치 구현 예제 (0) | 2011.01.27 |
java.lang.Annotation(주석:@) (0) | 2011.01.27 |
View Fipper (0) | 2011.01.27 |
상태바(Status Bar) (0) | 2011.01.27 |
J2SE 5.0에 추가된 중요한 기능중 하나로, 어노테이션 유형은 일반 클래스와 비슷해보이지만 독특한 속성이 있다.
표기법은 (@)(at) 표시로 하고, 클래스에서 @(at)기호와 함께 사용하여 다른 자바 코드에 주석을 달 수 있다.
주석태그가 코멘트가 아니라 소스에 포함된다. 여기서 중요한 점은 주석이 선언적 프로그래밍 모델을 체계적으로 지원하기 위한 방법이라는 것이다.
The Override Annotation
package dfi.study.java;
public class OverrideTest01{
public OverrideTest01() { }
@Override
public String toString() {
return super.toString() + " [Override Test]";
}
@Override
public int hasCode() {
return toString().hashCode();
}
}
Override Annotation의 오타 찾아내기
The Deprecated Annotation
@SuppressWarnings({"unchecked", "deprecation"})
The SuppressWarnings Annotation (type-safe가 아닌 Tiger 코드)
package dfi.study.java;
import java.util.ArrayList;
public class SuppressWarningsTest01
{
public void SuppressWarningsTest01()
{
ArrayList wordList = new ArrayList(); // no typing information on the List
wordList.add("study"); // causes error on list addition
}
}
non-typed 코드에서 컴파일러 경고
-컴파일 라인에 -Xlint를 추가하면 무엇이 잘못되었는지 구체적으로 표시할 수 있다.
경고 제거하기
package dfi.study.java;
import java.util.ArrayList;
@SuppressWarnings(value={"unchecked"})
public class SuppressWarningsTest01
{
public void SuppressWarningsTest01()
{
ArrayList wordList = new ArrayList(); // no typing information on the List
wordList.add("study"); // causes error on list addition
}
}
멀티 터치 구현 예제 (0) | 2011.01.27 |
---|---|
spring framework 적용하여 controller 에서 error stacktrace 에러 내용이 찍히지 않을때 (0) | 2011.01.27 |
View Fipper (0) | 2011.01.27 |
상태바(Status Bar) (0) | 2011.01.27 |
PowerManager (0) | 2011.01.27 |
ViewFlipper
: In/Out 속성을 지정하여 View 의 이동을 animation 처리한다.
1. 레이아웃 구성
ViewFlipper 에 포함될 View 를 정의
2. 애니메니션 구성
res/anim 에 원하는 애니메이션 구성
3. 코드 구성
mFilpper = (ViewFlipper)this.findVeiwById(R.id.flipper)
mFilpper.startFlipping();
mFilpper.setInAnimation(...);
mFilpper.setOutAnimation(...);
* 선언한 뷰를 class로 매핑
flipper = (ViewFlipper)findViewById(R.id.flipper);
title = (Title)flipper.getChildAt(0);
menu = (Menu)flipper.getChildAt(1);
game = (Game)flipper.getChildAt(2);
* 원하는 뷰를 화면에 나타내기
flipper.setDisplayedChild(2);
* 참고사항
setContentView혹은 layoutinflate를 하는 시점에 모든 뷰가 생성이 되고 화면에 보이는 여부와 상관없이
종료할때까지는 계속 살아 있기 때문에 특정 view를 보일때 초기화를 한다든지 하는건 알아서 해줘야함
(별도의 overriding할 method같은건 당연히 제공되지 않음)
## 이벤트 처리
http://tigerwoods.tistory.com/23
OnTouchListener 인터페이스의 구현
화면에 일어나는 touch를 감지하기 위해서는 android.view.View.OnTouchListener interface를 구현하여야 한다.
OnTouchListener 인터페이스는 다음과 같은 abstract callback method를 포함 함으로 구현해 주어야 한다.
Animation 리소스의 사용
push_left_in.xml: 새로운 view가 왼쪽 방향으로 밀려 들어옴.
push_left_out.xml: 기존 view가 왼쪽 방향으로 밀려 나감.
push_right_in.xml: 새로운 view가 오른쪽 방향으로 밀려 들어옴.
push_right_out.xml: 기존 view가 오른쪽 방향으로 밀려 나감.
<translate>
상하좌우 이동 animation을 지정하며. TranslateAnimation 클래스에 대응한다.
<alpha>
투명함을 조정하며, AlphaAnimation 클래스에 대응한다.
Java code에서 ViewFlipper 객체의 사용
View:addView(View): layout xml 문서 내부의 ViewFlipper element에 nest된 view 이외에 새로운 view를 동적으로 추가한다.
ViewAnimator:setInAnimation(Context, int): 새로운 view가 화면에 진입시의 animation 설정
ViewAnimator:setOutAnimation(Context, int): 기존 view가 화면에서 퇴장시의 animation 설정
ViewAnimator:showNext(): ViewFlipper에 등록된 view중 현재 view의 다음 view를 화면에 보이게 함
ViewAnimator:showPrevious(): ViewFlipper에 등록된 view중 현재 view의 전 view를 화면에 보이게 함
ViewFlipper:setFlipInterval(int): 자동 flipping시 적용할 시간간격 (1/1000초 단위 사용)
ViewFlipper:startFlipping(): 설정된 시간간격을 적용해 자동 flipping 시작 함
ViewFlipper:stopFlipping(): 자동 flipping을 정지 함
ViewSwitcher : ViewFlipper와 동일
spring framework 적용하여 controller 에서 error stacktrace 에러 내용이 찍히지 않을때 (0) | 2011.01.27 |
---|---|
java.lang.Annotation(주석:@) (0) | 2011.01.27 |
상태바(Status Bar) (0) | 2011.01.27 |
PowerManager (0) | 2011.01.27 |
Accelerometer, orientation (0) | 2011.01.27 |
상태바Status Bar 노티피케이션은 시스템의 상태바(선택 사항으로 조회 텍스트(ticker-text) 메시지를 가짐)에 아이콘을, 그리고 “노티피케이션notifications” 윈도우에는 확장 메시지를 추가한다. 그 사용자가 확장 메시지를 선택할 때, 안드로이드는 노티피케이션에 정의된 인텐트를 발생시킨다(보통 액티비티를 런치하기 위해). 여러분은 또한 디바이스 상의 사운드sound, 진동vibration, 그리고 발광 빛flashing light을 사용해서 사용자에게 경보alert하도록 노티피케이션을 설정할 수 있다.
상태바 노티피케이션은 백그라운드 서비스Service가 사용자에게 응답을 요구하는 이벤트를 경보alert 하는 것이 필요한 경우에 사용되어야 한다. 백그라운드 서비스는 사용자와의 상호작용을 받아들이기 위해 그것 자신의 액티비티를 결코 런치해서는 안된다. 서비스는 대신 사용자에 의해 선택될 때, 액티비티를 런치할 상태바 노티피케이션을 생성해야 한다.
아래의 스크린샷은 왼쪽 사이드에 노티피케이션 아이콘을 가진 상태바를 보여준다.
아래의 스크린샷은 “노티피케이션Notifications” 윈도우에 있는 노티피케이션의 확장 메시지를 보여준다. 사용자는 상태바를 아래로 내림(또는 홈 옵션 메뉴에서 노티피케이션을 선택함)으로써 노티피케이션 윈도우를 나타나게 할 수 있다.
액티비티 또는 서비스는 상태바 노티피케이션을 시작시킬 수 있다. 액티비티는 그것이 활성화되어 있고 포커스되어 있는 동안에만 액션을 수행할 수 있기 때문에, 여러분은 서비스로부터 여러분의 상태바 노티피케이션을 생성해야 한다. 이 방식에서, 노티피케이션은 사용자가 다른 애플리케이션을 사용하거나 또는 그 디바이스가 절전상태에 있는 동안 백그라운드로부터 생성될 수 있다. 노티피케이션을 생성하기 위해서, 여러분은 두 가지 클래스를 사용해야 한다: Notification과 NotifactionManager가 그것이다.
상태바status bar 아이콘, 확장 메시지expanded message, 그리고 재생할 사운드와 같은 별도의 설정과 같이, 여러분의 상태 바 노티피케이션의 속성들을 정의하기 위해서는 노티피케이션Notification 클래스의 인스턴스를 사용하라. 노티피케이션 매니저NotificationManager는 모든 노티피케이션을 실행하고 관리하는 안드로이드 시스템 서비스이다. 여러분은 노티피케이션 매니저를 인스턴스화하지는 않는다. 여러분의 노티피케이션을 노티피케이션 매니저에게 건네주기 위해, 여러분은 getSystemService()를 사용하여 노티피케이션 매니저에 대한 레퍼런스를 얻어와야 한다. 그런 다음에 여러분이 사용자에게 통보하길 원할 때, notify()를 사용해서 노티피케이션 매니저에게 여러분의 노티피케이션 오브젝트를 전달하라.
상태바 노티피케이션을 생성하기 위해서는 다음과 같이 하라.
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
int icon = R.drawable.notification_icon;
CharSequence tickerText = "Hello";
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when);
Context context = getApplicationContext();
CharSequence contentTitle = "My notification";
CharSequence contentText = "Hello World!";
Intent notificationIntent = new Intent(this, MyClass.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
private static final int HELLO_ID = 1;
mNotificationManager.notify(HELLO_ID, notification);
이것이 끝이다. 여러분의 사용자는 이제 노티피케이션을 통보받았다notified.
노티피케이션 매니저NotificationManager는 모든 노티피케이션을 관리하는 시스템 서비스이다. 여러분은 getSystemService()를 사용해서 노티피케이션 매니저에 대한 레퍼런스를 얻어와야 한다. 예를 들어 다음과 같다.
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
여러분이 상태바 노티피케이션을 전송하고자 할 때, 노티피케이션 매니저에게notify(int,Notification)를 사용해서 노티피케이션 오브젝트를 파라미터로 전달하라. 첫 번째 파라미터는 노티피케이션에 대한 고유한 ID이며, 두 번째는 노티피케이션 오브젝트이다. 그 ID는 여러분의 애플리케이션으로부터 그 노티피케이션을 고유하게 식별한다. 이 ID는 여러분이 노티피케이션을 업데이트하는 것이 필요하거나 또는 (여러분의 애플리케이션이 다른 종류의 노티피케이션들을 관리한다면) 사용자가 노티피케이션에 정의된 인텐트를 통해 여러분의 애플리케이션으로 돌아올 때 적절한 액션을 선택하는 것이 필요할 때 필수적이다.
사용자가 노티피케이션 윈도우에서 상태바 노티피케이션을 선택할 때 그것을 없애기 위해서는, 여러분의 노티피케이션 오브젝트에 “FLAG_AUTO_CANCEL” 플래그를 추가하라. 여러분은 또한 cancel(int)를 사용해서 상태바 노티피케이션에 노티피케이션 ID를 전달함으로써 수동으로 그것을 없앨 수 있으며, 또한 cancelAll()를 사용해서 여러분의 모든 노티피케이션을 없앨 수 있다.
노티피케이션Notificaton 오브젝트는 상태바에 표시되는 노티피케이션 메시지의 상세 사항과 “노티피케이션Notifcations” 윈도우, 그리고 사운드와 깜박이는 발광 빛과 같은 그 밖의 경보 설정을 정의한다.
상태바 노티피케이션은 다음과 같은 모든 것을 요구한다.
상태바 노티피케이션에 대한 선택적인 설정에는 다음과 같은 것이 포함된다.
신규 노티피케이션에 대한 시작 도구는 Notification(int,CharSequence,long) 생성자와 setLatestEventInfo(Context,CharSequence,CharSequence, PendingIntent) 메쏘드를 포함한다. 이것들은 노티피케이션에 대해 요구되는 모든 설정을 정의한다. 아래의 단편snippet은 기본적인 노티피케이션 셋업을 보여준다.
int icon = R.drawable.notification_icon; // icon from resources
CharSequence tickerText = "Hello"; // ticker-text
long when = System.currentTimeMillis(); // notification time
Context context = getApplicationContext(); // application Context
CharSequence contentTitle = "My notification"; // expanded message title
CharSequence contentText = "Hello World!"; // expanded message text
Intent notificationIntent = new Intent(this, MyClass.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
// the next two lines initialize the Notification, using the configurations above
Notification notification = new Notification(icon, tickerText, when);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
이벤트들이 여러분의 애플리케이션에서 계속 발생함에 따라 여러분은 상태바 노티피케이션에 있는 정보를 업데이트할 수 있다. 예를 들어 이전 메시지가 읽혀지기 전에 신규 SMS 텍스트 메시지가 도착하면, 그 메시징 애플리케이션은 수신된 신규 메시지의 전체 숫자를 보여주기 위해 이미 존재하는 노티피케이션을 업데이트 한다. 이미 존재하는 노티피케이션을 업데이트하는 이 방식은, 노티피케이션 윈도우에서의 혼란clutter을 피하기 때문에 노티피케이션 매니저에 신규 노티피케이션을 추가하는 것보다 훨씬 더 좋다.
각각의 노티피케이션은 정수integer ID를 가지고 노티피케이션 매니저에 의해 고유하게 식별되기 때문에, 여러분은 신규 값을 가지고 setLatestEventInfo()를 호출함으로써 노티피케이션을 수정하고, 그 노티피케이션의 일부 필드 값들을 변경하고, 그리고 나서 다시 notify()를 호출할 수 있다.
여러분은 (컨텍스트와 확장 메시지 타이틀과 텍스트를 제외하고) 오브젝트 멤버 필드를 사용해서 각각의 속성을 수정할 수 있다. contentTitle과 contentText에 대한 신규 값을 가지고 setLatestEventInfo()를 호출함으로써 여러분이 그 노티피케이션을 업데이트할 때, 여러분은 항상 그 텍스트 메시지를 변경revise해야 한다. 그런 다음 그 노티피케이션을 업데이트 하기 위해 notify()를 호출하라(물론, 만약 여러분이 커스텀 확장 뷰를 생성했다면, 이러한 타이틀과 텍스트 값을 업데이트하는 것은 아무런 영향을 주지 않는다).
여러분은 디폴트 노티피케이션 사운드(이것은 사용자에 의해 정의된다) 또는 여러분의 애플리케이션에 의해 지정된 사운드를 사용해서 사용자에게 경보alert할 수 있다.
사용자의 디폴트 사운드를 사용하기 위해서는, 디폴트 필드에 “DEFAULT_SOUND”를 추가하라.
notification.defaults |= Notification.DEFAULT_SOUND;
여러분의 노티피케이션에서 다른 사운드를 사용하기 위해서는, 사운드 필드에 Uri 레퍼런스를 전달하라. 다음의 예제는 디바이스 SD 카드에 저장된 알고 있는 오디오 파일을 사용한다.
notification.sound = Uri.parse("file:///sdcard/notification/ringer.mp3");
다음의 예제에서는, 그 오디오 파일이 내부 MediaStore 컨텐트 프로바이더에서 선택된다.
notification.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6");
이 경우에, 미디어 파일 (“6”)에 대한 정확한 ID를 알고 있으며, 그리고 컨텐트 Uri의 끝에 덧붙여진다. 만약 여러분이 정확한 ID를 모른다면, 여러분은 컨텐트 리졸버ContentResolver를 사용해서 미디어스토어MediaStore에서 사용가능한 모든 미디어를 쿼리해야 한다. 컨텐트 리졸버ContentResolver를 사용하는 것에 대한 더 자세한 정보에 대해서는 7장. “컨텐트 프로바이더”를 보라.
만약 여러분이 사용자가 노티피케이션에 응답할 때까지 또는 노티피케이션이 취소될 때까지 사운드가 계속해서 반복되길 원한다면, 그 플래그 필드에 “FLAG_INSISTENT”를 추가하라.
Note: 만약 그 디폴트 필드가 “DEFAULT_SOUND” 를 포함한다면, 그러면 그 디폴트 사운드는 사운드 필드에 의해 정의된 임의의 사운드를 오버라이드 한다.
여러분은 디폴트 진동 패턴 또는 여러분의 애플리케이션에 의해 정의된 진동 패턴을 사용해서 사용자에게 경보alert할 수 있다.
디폴트 패턴을 사용하기 위해서는, 디폴트 필드에 “DEFAULT_VIBRATE”를 추가하라.
notification.defaults |= Notification.DEFAULT_VIBRATE;
여러분 자신의 진동 패턴을 정의하기 위해서는 vibrate 필드에 long 값 배열을 전달하라.
long[] vibrate = {0,100,200,300};
notification.vibrate = vibrate;
long 배열은 진동이 꺼지고 켜지는 길이에 대한 번갈아 있는 패턴을 (1/1000초 단위로) 정의한다. 첫 번째 값은 시작하기 전에 얼마나 오래 기다릴 것인가(꺼진 상태)이고, 두 번째 값은 첫 번째 진동의 길이이고, 세 번째는 그 다음의 꺼져 있는 길이, 그리고 기타 등등이다. 그 패턴은 여러분이 좋아하는 만큼 길 수 있으나 반복되도록 설정될 수 없다.
Note: 만약 디폴트 필드가 “DEFAULT_VIBRATE”를 포함한다면, 그러면 그 디폴트 진동은 vibrate 필드에 의해 정의된 임의의 진동을 오버라이드 한다.
발광 LED 빛을 사용해서 사용자에게 경보alert하기 위해서, 여러분은 (만약 사용할 수 있다면) 디폴트 빛 패턴을 구현할 수 있거나 또는 여러분 자신의 컬러와 그 빛에 대한 패턴을 정의할 수 있다.
디폴트 빛을 설정하기 위해서는 그 디폴트 필드에 “DEFAULT_LIGHTS”를 추가하라.
notification.defaults |= Notification.DEFAULT_LIGHTS;
여러분 자신의 컬러와 패턴을 정의하기 위해서는 (컬러에 대해서는) ledARGB 필드, ledOffMS 필드(1/1000초 단위의 빛이 꺼져 유지되는 시간의 길이), ledOnMS(1/1000초 단위의 빛이 켜져 유지되는 시간의 길이) 값을 정의하고, 그리고 또한 그 플래그 필드에 “FLAG_SHOW_LIGHTS”를 추가하라.
notification.ledARGB = 0xff00ff00;
notification.ledOnMS = 300;
notification.ledOffMS = 1000;
notification.flags |= Notification.FLAG_SHOW_LIGHTS;
이 예제에서, 초록색 빛이 반복적으로 300 밀리세컨드(1/1000초) 동안 켜지고 1초 동안 꺼진다. 스펙트럼 내의 모든 컬러가 디바이스 LED에 의해 지원되는 것은 아니다. 그리고 모든 디바이스가 동일 컬러를 지원하지 않는다. 그러므로 그 하드웨어는 자신의 능력의 최선을 산정한다. 초록색은 가장 일반적인 노티피케이션 컬러이다.
여러분은 노티피케이션 필드와 플래그를 사용해서 여러분의 노티피케이션에 더 많은 몇가지 기능들을 추가할 수 있다. 약간의 유용한 기능들이 아래에 포함되어 있다.
여러분의 애플리케이션을 커스터마이징할 수 있는 추가적인 기능들에 대한 더 자세한 정보에 대해서는 노티피케이션Notification 클래스 레퍼런스를 보라.
디폴트로, “노티피케이션Notifications” 윈도우에서 사용되는 확장 뷰는 기본적인 타이틀과 텍스트 메시지를 포함한다. 이것들은 setLatestEventInfo() 메쏘드의 content Title과 contentText 파라미터에 의해 정의된다. 하지만 여러분은 또한 리모트뷰RemoteViews를 사용해서 확장 뷰에 대한 커스텀 레이아웃을 정의할 수 있다. 위에 보이는 스크린샷은 LinearLayout에 이미지 뷰와 텍스트 뷰를 사용한 커스텀 확장 뷰의 예제이다.
확장 메시지에 대한 여러분 자신의 레이아웃을 정의하기 위해서는, 리모트뷰RemoteViews 오브젝트를 인스턴스화하고, 여러분의 노티피케이션의 컨텐트뷰contentView 필드에 리모트뷰RemoteView를 전달하라. contentIntent 필드에는 PendingIntent를 전달하라.
커스텀 확장 뷰를 생성하는 것은 예제를 통해 가장 잘 이해된다.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="3dp"
>
<ImageView android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginRight="10dp"
/>
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:textColor="#000"
/>
</LinearLayout>
이 레이아웃은 확장 뷰를 위해 사용된다. 그러나 이미지 뷰와 텍스트 뷰의 컨텐트는 여전히 애플리케이션에 의해 정의될 필요가 있다. 리모트뷰RemoteViews는 이 컨텐트를 여러분으로 하여금 정의할 수 있도록 하는 약간의 편리한 메쏘드들을 제공한다.
RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification_layout);
contentView.setImageViewResource(R.id.image, R.drawable.notification_image);
contentView.setTextViewText(R.id.text, "Hello, this message is in a custom expanded view");
notification.contentView = contentView;
여기에서 보여지듯이, 애플리케이션의 패키지 이름과 레이아웃 리소스 ID를 리모트뷰RemoteViews 생성자constructor에게 전달하라. 그런 다음에, setImageViewResource()와 setTextViewText()를 사용해서 이미지 뷰와 텍스트 뷰에 대한 내용을 정의하라. 각각의 경우에서, 해당 뷰에 대한 값과 함께 여러분이 설정하고자 하는 적절한 뷰 오브젝트의 레퍼런스 ID를 전달하라. 최종적으로 그 리모트뷰RemoteViews 오브젝트는 컨텐트뷰contentView 필드로 노티피케이션에게 전달된다.
Intent notificationIntent = new Intent(this, MyClass.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.contentIntent = contentIntent;
mNotificationManager.notify(CUSTOM_VIEW_ID, notification);
리모트뷰RemoteViews 클래스는 또한 여러분의 노티피케이션의 확장 뷰에 측정기Chronometer 또는 진행상태바ProgressBar를 쉽게 추가하기 위해 사용할 수 있는 메쏘드들을 포함한다. 리모트뷰RemoteViews 를 사용해서 커스텀 레이아웃을 생성하는 것에 대한 더 자세한 정보에 대해서는 리모트뷰RemoteViews 클래스 레퍼런스를 참고하라.
Note: 커스텀 확장 뷰를 생성할 때 여러분은 특별히 여러분의 커스텀 레이아웃이 다른 디바이스 오리엔테이션과 해상도에서 적절하게 기능하는 지를 보장하기 위해 주의해야 한다. 이 조언은 안드로이드 상에 생성된 모든 뷰 레이아웃에 적용되지만, 그것은 특별히 이 경우에 중요하다. 왜냐하면 여러분의 레이아웃 실소유물real estate이 매우 제한되기 때문이다. 그러므로 여러분의 커스텀 레이아웃을 너무 복잡하게 만들지 마라. 그리고 다양한 설정에서 그것을 확실히 테스트하라.
java.lang.Annotation(주석:@) (0) | 2011.01.27 |
---|---|
View Fipper (0) | 2011.01.27 |
PowerManager (0) | 2011.01.27 |
Accelerometer, orientation (0) | 2011.01.27 |
Notification Manager (0) | 2011.01.27 |
Device의 Power state를 제어할 수 있게 해준다. Device 베터리 사용시간은 이 API의 사용에 따라 영향을 받게 된다. 따라서 반드시 필요한 경우가 아니라면 Wakelock을 acquire하지 않는 것이 좋다. 가능한 낮은 레벨을 사용하고 사용후에는 바로 release하는 것이 좋다.
PowerManager pm = (PowerManager)Context.getSystemServier(Context.POWER_SERVICE);
아주 기초적인 API인 newWakeLock()를 사용할 것이다.
이 API는 PowerManager.WakeLock객체를 만든다.
device의 powerstate를 제어하기 위해 이 객체의 method를 사용하게 된다.
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
wl.acquire();
// ..screen will stay on during this section..
wl.release();
System 전원에 영향을 미치는 flag가 아래와 같이 정의되어 있다.
PARTIAL_WAKE_LOCK : CPU(On*), Screen(OFF), Keyboard(OFF)
SCREEN_DIM_WAKE_LOCK : CPU(On), Screen(Dim), Keyboard(OFF)
SCREEN_BRIGHT_WAKE_LOCK : CPU(On), Screen(Bright), Keyboard(OFF)
FULL_WAKE_LOCK : CPU(On), Screen(Bright), Keyboard(Bright)
cf) PARTIAL_WAKE_LOCK를 유지하는 동안 CPU는 계속 run상태로 된다. 어떤 타이머나 사용자가 power button을 누르더라도 상태는 유지가 된다. 나머지 wakelock은 CPU가 run상태가 되지만 사용자가 power button을 눌러서 sleep으로 갈 수 있다.
Screen에만 적용되는 2가지 flag가 더 있다. 이 플래그는 PARKTIAL_WAKE_LOCK에는 영향을 안준다.
1. ACQUIRE_CAUSES_WAKEUP
Normal wake locks don't actually turn on the illumination. Instead, they cause the illumination to remain on once it turns on (e.g. from user activity). This flag will force the screen and/or keyboard to turn on immediately, when the WakeLock is acquired. A typical use would be for notifications which are important for the user to see immediately
2. ON_AFTER_RELEASE
if this flag is set, the user activity timer will be reset when the WakeLock is released, causing the illumination to remain on a bit longer. This can be used to redece flicker if you are cycling between wake lock conditions.
PowerManager는 Screen을 On/Off할때 WindowManager에 통지를 하고 이는 KeyguardViewMediator를 통해 LockScreen에도 전달된다.
PowerManagerService.mNotificationTask
-> WindowManagerPolicy.screenTurnedOn()
-> KeyguardViewMediator.onScreenTurnedOn();
-> WindowManagerPolicy.screenTurnedOff()
-> KeyguardViewMediator.onScreenTurnedOff();
출처 : http://pheadra.tistory.com/category/Android/Android%20Service
View Fipper (0) | 2011.01.27 |
---|---|
상태바(Status Bar) (0) | 2011.01.27 |
Accelerometer, orientation (0) | 2011.01.27 |
Notification Manager (0) | 2011.01.27 |
Android: gdb를 이용한 Dalvik VM 디버깅 (0) | 2011.01.27 |
1. 센서 관리자
센서 관리자는 안드로이드 장치에서 이용할 수 있는 센서 하드웨어를 관리하는 데 사용
센서 레퍼런스를 얻는 법
String service_name = Context.SENSOR_SERVICE;
SensorManager sensorManager = (SensorManager)getSystemService(service_name);
다음 보인 패턴은 이용할 수 있는 모든 하드웨어 센서로부터의 센서 결과를 모니터 하는 데 이용할 수 있다.
SensorListener mySensorListener = new SensorListener() {
Public void onSensorChanged(int sensor, float[] values){
// 센서 값 변화를 다룬다.
}
Public void onAccracyChanged(int sensor, int accuracy){
//정확도의 변화를 다룬다.
}
};
센서의 정확도 변화를 보려면 onAccracyChanged을 구현해야 한다. Accuracy 매개변수는 다음과 같은 상수 이다.
SensorManager.SENSOR_STATUS_ACCURACY_HIGH 센서가 가능한 가장 높은 정확도
SensorManager.SENSOR_STATUS_ACCURACY_LOW 센서가 가능한 가장 낮은 정확도
SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM 센서가 가능한 가장 높은 정확도
SensorManager.SENSOR_STATUS_UNRELIABLE 센서 데이터를 신뢰할 수 없음을 나타내며, 조정이필요하거나 현재 측정이 불가능함
SensorManager.SENSOR_ACCELEROMETER 현재 가속도를 세 축을 따라 제곱 초당 미터(m/s2)로 리턴하는 가속도 센서.
SensorManager.SENSOR_ORIENTATION 세 축에 대한 현재 방향을 도 단위로 리턴하는 방향센서
SensorManager.SENSOR_LIGHT 주변 조도를 럭스로 기술한 단일 값을 리턴하는 주변 광 센서
SensorManager.SENSOR_MAGNETIC_FIELD 현재 자기장을 세 축을 따라 마이크로테슬라로 측정하는 데 사용되는 센서
SensorManager.SENSOR_PROXIMITY 장치와 대상 물체 간의 거리를 미터로 기술한 단일 값을 리턴하는 근접 센서
SensorManager.SENSOR_TEMPERATURE 주변 온도를 섭씨로 리턴하는 온도 센서
특정 센서로부터의 변화를 통지받으려면, 센서 리스너를 만들고, 이 리스너로 트리거 해야하는 센서와 센서의 업데이트 속도를 지정하는 센서 관리자에 이를 등록한다.
sensorManager.registerListener(mySensorListener, SensorManager.SENSOR_TRICORDER, SensorManager.SENSOR_DELAY_FESTEST);
업데이트 속도 관련 상수
SensorManager.SENSOR_DELAY_FESTEST 가장 빠른 업데이트 속도
SensorManager.SENSOR_DELAY_GAME 게임 제어에 가장 적합한 업데이트 속도
SensorManager.SENSOR_DELAY_NORMAL 기본 업데이트 속도
SensorManager.SENSOR_DELAY_UI UI 기능 업데이트에 적합한 속도
sensorManager.registerListener(mySensorListener, SensorManager.SENSOR_TRICORDER); // default NORMAL
2. 가속도 센서와 나침반 이용하기
- 하드웨어의 현재 방향 측정
- 방향 변화 모니터
- 사용자가 향하고 있는 방향 식별
- 위 – 아래, 좌 – 우, 앞 – 뒤 방향 가속도(이동 속도의 변화) 모니터
Accelerometer는 가속도를 측정하는데 이용된다.
가속도는 속도의 변화 비율로 정의되므로, 가속도 센서는 장치의 속도가 주어진 방향에서 얼마나 빨리 변화하고 있는지를 측정할 수 있고, 사용자의 움직임과 이 움직임의 속도 변화 비율을 감지 할 수 있다.
주의) 가속도 센서는 속도를 측정하지 않는다 그래서 속도를 측정하려면, 시간에 대한 가속도의 변화를 측정해야 할 필요가 있다.
가속도 센서는 움직임에 기인한 가속도와 중력에 기인한 가속도 간을 구분하지 못한다. 따라서 Z축에 대한 가속도를 감지하는 가속도 센서는 정지 상태에 있을 때 -9.8m/s2 을 읽을 것이다.(이 값은 SensorManager.STANDARD_GRAVITY 상수)
가속도 변화 감지하기
가속도는 앞-뒤(세로 Longitudinal), 좌-우(가로 Lateral), 위-아래(수직 Vertical) 이렇게 세 방향 축을 따라 측정될 수 있다.
수직 양의 값은 위, 음의 값은 아래
세로 양의 값은 앞, 음의 값은 뒤
가로 양의 값은 오른쪽, 음의 값은 왼쪽
좌표 축 정의
X축 : 화면에 수평축(portrait 모드에서 짧은 에지를 landscape 모드에서 긴 에지)을 나타내며 오른쪽을 가리킨다.
Y축 : 화면에 수직축을 나타내며 화면 위쪽을 가리킨다.(원점은 왼쪽 밑 코너)
Z축 : 단말이 화면을 위로 해서 테이블에 올려져 있다고 생각했을 때 하늘을 가리킨다.
SensorManager sm = (SensorManager)getSystemServie(Context.SENSOR_SERVICE);
Sm.registerListener(mySensorListener,
SensorManager.SENSOR_ACCELEROMETER,
SensorManager.SENSOR_DELAY_UI);
SensorListener mySensorListener = new SensorListener() {
Public void onSensorChanged(int sensor, float[] values){
// 센서 값 변화를 다룬다.
If(sensor == SenSorManager.SENSOR_ACCELEROMETER) {
Float xAxis = values[SensorManager.DATA_X]; // 앞 – 뒤
Float yAxis = values[SensorManager.DATA_Y]; // 좌 – 우
Float zAxis = values[SensorManager.DATA_Z];//
Float raw_xAxis = values[SensorManager.RAW_DATA_X];
Float raw_yAxis = values[SensorManager.RAW_DATA_Y];
Float raw_zAxis = values[SensorManager.RAW_DATA_Z];
}
}
};
참고 사이트
http://blog.androgames.net/85/android-accelerometer-tutorial/
http://blog.androgames.net/135/android-orientation-tutorial/
출처 : http://pheadra.tistory.com/category/Android/Android%20Service
상태바(Status Bar) (0) | 2011.01.27 |
---|---|
PowerManager (0) | 2011.01.27 |
Notification Manager (0) | 2011.01.27 |
Android: gdb를 이용한 Dalvik VM 디버깅 (0) | 2011.01.27 |
서비스를 부팅시 시작시키기 (Start Service at Boot Time) (0) | 2011.01.27 |
PowerManager (0) | 2011.01.27 |
---|---|
Accelerometer, orientation (0) | 2011.01.27 |
Android: gdb를 이용한 Dalvik VM 디버깅 (0) | 2011.01.27 |
서비스를 부팅시 시작시키기 (Start Service at Boot Time) (0) | 2011.01.27 |
Fingerprint 추적 방법 (0) | 2011.01.27 |
adb forward tcp:4000 tcp:4000
arm-eabi-gdb /workspace/android/out/target/product/generic/system/bin/app_process
set solib-search-path /workspace/android/out/target/product/generic/symbols/system/lib
target remote :4000
break InterpAsm-armv5te.S:10143
출처 : http://androidkr.blogspot.com/2010/10/android-gdb-dalvik-vm.html
Accelerometer, orientation (0) | 2011.01.27 |
---|---|
Notification Manager (0) | 2011.01.27 |
서비스를 부팅시 시작시키기 (Start Service at Boot Time) (0) | 2011.01.27 |
Fingerprint 추적 방법 (0) | 2011.01.27 |
디바이스의 고유 정보값 얻어오기 (0) | 2011.01.27 |