1. Touch mode에서도 Keypad를 쓸수 있게 하기위해
- View를 생성할때 setFocusableInTouchMode(true);를 호출 한다.

2. View mode를 Portrait 나 Landscape로 고정하고 싶을때
- Manifest의 Activity 에 android:screenOrientation="landscape"을 추가한다.

3. 슬라이드를 열고 닫을때 onDestroy()가 호출되지 않도록 하기위해
- Manifest의 Activity 에 android:configChanges="orientationkeyboardHidden" 을 추가한다.
- "orientationkeyboardHidden" 이 둘중에 하나라도 빠지면 슬라이드를 열때 onDesroy()가 호출된다.

4. Scoket 통신을 할수 있도록 하기 위해
- 퍼미션을 추가 한다. uses-permission android:name="android.permission.INTERNET"

5. 진동을 사용할수 있도록 하기 위해

- 퍼미션을 추가한다. uses-permission android:name="android.permission.VIBRATE" 

6. 안테나 영역 없에기
- Manifest의 Activity 에 android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"

7. Manifest의 versionName 갖고오기.
- mContext.getPackageManager().getPackageInfo("package name", 0).versionName

ex)

package="com.gamevil.android"
android:versionCode="1"
android:versionName="1.0.0">





android:label="@string/app_name"
android:configChanges="orientationkeyboardHidden"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">


17. Android 키보드 숫자형으로 시작하게 하기
edittext.setInputType(InputType.TYPE_CLASS_NUMBER);

16. Android listview 검정화면 없애기
android:cacheColorHint="#00000000"

15. Android 화면 고정하기
AndroidManifest.xml의 activity 속성중 screenOrientation을 다음과 같이 지정해준다.

//화면을 세로로 유지
<activity android:name=".Powermeter"
                  android:label="@string/app_name"
                  android:screenOrientation="portrait">
//화면을 가로로 유지
<activity android:name=".Powermeter"
                  android:label="@string/app_name"
                  android:screenOrientation="landscape">
자바 소스에서
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

14. Android Handler example
  // 시간주고 바로 뜨게 하기 20이 최소 가능 값..
        new Handler().postDelayed(new Runnable() {
            public void run() {
                openOptionsMenu();
            }
        }, 20); 

13. Android 소프트 키보드 끄기 및 보이기 및 숨기기
  // 키보드 오프시키는 소스..
  EditText et = (EditText)findViewById(R.id.menu6_e_number);
  et.setInputType(0); //가상키보드 오프

1. 보이게 하기

EditText et = (EditText)findViewById(R.id.moneyEdit);
et.setInputType(0); //가상키보드 오프
        
        et.setOnClickListener(new OnClickListener() {   
   public void onClick(View arg0) {    
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); 
          imm.showSoftInput(input, 0);
   }         
        });

InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); 
imm.showSoftInput(editText, 0);

2. 숨기기
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); 
imm.hideSoftInputFromWindow(myEditText.getWindowToken(), 0); 


12. Android  Edittext Hint, 흐리게 보이기
android:hint="ex) 안드로이드"


11. Android  EditText 숫자키만 허용하기

DigitsKeyListener digit = 
new DigitsKeyListener(true, true); // first true : is signed, second one : is decimal
digit.setKeyListener( MyDigitKeyListener );

위와같이 하거나 xml 에서

android:inputType="number"


10. Android  Option menu 실행 소스
openOptionsMenu();


9. Android Menu 만들기
- xml 소스
res/menu/menu.menu

<menu xmlns:android="http://schemas.android.com/apk/res/android">
 <item
  android:id="@+id/adjust"
  android:title="수정"
  android:orderInCategory="1" >
 </item>
 <item
  android:id="@+id/delete"
  android:title="삭제"
  android:orderInCategory="2" >
 </item>
</menu>

- 자바 소스
 // OptionMenu
 public boolean onCreateOptionsMenu(Menu menu){
  getMenuInflater().inflate(R.menu.del_adjust, menu);
  return true;
 }

    // OptionMenu click event
 public boolean onOptionsItemSelected(MenuItem item) {
  switch (item.getItemId()) {
   case R.id.adjust:
    finish();
    return true;
    
   case R.id.delete:
    finish();
    return true;
  }
  return false;
 }

8. Android Dialog 만들기 (Android.Dialog.Builder())

기존에는 Activity에서 showAlert(()를 제공해줬나보다. (예제를 보니...)
더 이상 지원하지 않기 때문에 AlertDialog.Builder()를 이용하여 Dialog를 생성하였다.

*onClickLister() 생성시 반드시 DialogInterface.OnClickListener()라고 클래스를 적어줘야 한다. 
 (Activity에서 button 클릭 이벤트를 처리하기 위해 import한 View 클래스에 OnClickListener 메소드가 있다.)

a. Android  yes or no - 버튼 2개짜리
new AlertDialog.Builder(LoginMainActivity.this)
.setTitle("Login Data")
.setMessage("rosa : test") //줄였음
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {                                        
        //...할일
    }
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {
        //...할일
    }
})
.show();

b. Android  ok (or cancel)
new AlertDialog.Builder(LoginMainActivity.this)
        .setTitle("Login Data")
        .setMessage("rosa : test") //줄였음
        .setNeutralButton("OK", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {                                        
                //...할일
            }
        })        
        .show();

c. Android   다른 layout 출력
new AlertDialog.Builder(LoginMainActivity.this)
.setTitle("list 예제")        
.setItems(R.array.listBtnArray, new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int selectedIndex) {        
        String[] list = getResources().getStringArray(R.array.listBtnArray);        
        new AlertDialog.Builder(LoginMainActivity.this)
        .setTitle("선택한 리스트 아이템")
        .setMessage(list[selectedIndex])
        .setNeutralButton("OK", new DialogInterface.OnClickListener(){
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // TODO Auto-generated method stub                        
            }                    
        });                
    }
    })
.show();

--
value 값으로 array 추가
<string-array name="listBtnArray">
        <item>One</item>
        <item>Two</item>
        <item>Three</item>
    </string-array>



7. Android  뒤로 가기 키
 onBackPressed();

6. Android  바이브레이터 
Vibrator vibe = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
vibe.vibrate(500);
// 퍼미션        
<uses-permission android:name="android.permission.VIBRATE"></uses-permission>

5. Android  밝기 셋팅
Window w = getWindow();
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.screenBrightness = 0~1까지의 float 값;
w.setAttributes(lp);

-1.f를 주면 default 밝기로 세팅됩니다.

4. Android  화면 꺼지는것 막기
현재 Activity가 보여지고 있는 동안은 시간이 지나도
화면이 자동으로 꺼지지 않도록 합니다.
즉 단말이 슬립상태로 들어가지 않고 계속 화면을 켜놓습니다.

getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

3. Android  toast
1-Type
Toast.makeText.(this, "토스트 메세지", Toast.LENGTH_SHORT).show();

2-Type
Context context = getApplicationContext();
String msg = "";
int duration = Toast.LENGTH_SHORT;
Toast.makeText(context, b, duration).show();


2. Android  View 백그라운드 색 변경
TextView a = null; 
a.setBackgroundColor(Color.WHITE);

1. Android  timer 이용
http://docs.androidside.com/docs/reference/java/util/TimerTask.html
--------------------------------------------------------------------------------------------------
모토로이 볼륨 올리고 내리는 버튼 키값을 알아내서
edittext 에 원하는 값을 넣는 방법 볼룸 위아래 버튼을 누르면
화면에 벨로시 볼륨 조절하는 창이 나타나는데 완전히 키값을 가로채는 방법 

et_editText.setOnKeyListener(new OnKeyListener() {
        
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
           // TODO Auto-generated method stub
           if(event.getAction() == KeyEvent.ACTION_DOWN){
              if(keyCode == 24 || keyCode == 25){
              et_editText.setText("1234567890");
              
              return true;
              }
           }
           return false;
        }
        
     });


- 전체적으로 필요한 기능
// 종료 후 재 부팅시 기능이 죽지않고 유지되게 하는 방법들..
http://www.androidpub.com/android_dev_qna/189549

- 박사마 만드는데 필요한 기능
// view에서  페이지 넘기는 기능
API Demos에서 Animation에 간단하게 Fade in, Zoom in 효과가 있네요.

내가 만드는 부분에 필요한 부분들
// 강제로 클릭을 발생시키는 이벤트
dispatchTouchEvent
// 좌표관련들..
getWidth()랑 getHeight()로 전체 좌표값을 얻어오고 %로 비율 정해서 좌표값 설정하세요

출처 : http://winchester.tistory.com/

텍스트 입력 창이 있는 경우 soft input을 자동으로 띄워주는 것이 UX 측면에서 좋다. 그래서 대부분 iPhone이나 Android의 app들은 자동으로 soft input을 띄워준다.


Android에서 activity가 시작될 때 자동으로 soft input을 보여주는 방법은 http://developer.android.com/guide/topics/manifest/activity-element.html#wsoft 에 잘 정리되어 있다.
그런데 여기 나온 방법으로 app을 만들어서 emulator에서 백날 돌려봐야 soft input이 나오지 않는다. 왜 그럴까? 이를 명확하게 설명해 놓은 공식 문서는 어디에도 없다.
그 이유는 http://groups.google.com/group/android-developers/browse_thread/thread/17210d784766602d?pli=1 의 대화내용들을 읽어보면 알 수 있다. 여기서 android framework engineer로 보이는 Dianne Hackborn이라는 사람이 다음과 같은 말을 하였다.

Typically the emulator runs as a device that has a keyboard, in which case 
the system deliberately does not automatically show the IME because the user 
has easy access to a real keyboard.  It is recommended to not defeat this 
behavior, resulting in an inconsistent behavior with the rest of the 
applications. 

그렇다. hardware keyboard가 있으면 manifest에 option을 아무리 줘도 soft input이 안 나올 수도 있다는 얘기다. 문서에는 이딴 설명 하나도 없다. android를 하면서 많이 느끼는 거지만 java가 정말 문서화 하나는 잘 했었구나라는 거다. 
대화 내용들을 쭉 읽어 보면 알겠지만 보통 hardware keyboard는 접혀 있는 상태인데 그런 경우는 당연히 soft input을 보여줘야 하는 거 아니냐고 따지는 사람도 있다. 내가 봐도 그렇다. 
뭐 하여튼 이 option이 제대로 동작하는지 확인하려면 emulator를 만들 때 hardware keyboard를 지원하지 않는 것으로 profile을 만들어야 한다. 그럼 잘 된다.

그런데, 난! 장비에 hardware keyboard가 있든 없든 자동으로 soft input을 보여주고 싶단 말이다! 보통 hardware keyboard가 사용 가능 상태로 되어 있으면 soft input을 띄워달라고 해도 시스템에서 알아서 안 띄운다. 고로 activity 시작할 때 강제로 soft input을 띄워달라고 코드를 넣어야 한다.

InputMethodManager manager = (InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
manager.showSoftInput(findViewById(R.id.text), 0);

onCreate에 위 코드를 넣고 실행해 보자. soft input이 뜰까? 안뜰까? 안뜬다. 오 지쟈스!!! 왜 안뜰까? 안타깝게도 onCreate 시점에는 activity를 만들고 있는 상황이라 이런 요청을 가볍게 씹어주신다. 어차피 activity가 화면에 보여지는 최초의 순간은 life cycle 상 onCreate -> onStart -> onResume 이 모두 끝나야 한다. (물론 저 life cycle 중간 중간에 잡다구리한 phase들이 더 있다) 고로 onResume에 나 조금 있다가 이것좀 해달라고 요청을 넣어야 한다.

@Override
protected void onResume() {
super.onResume();
final View view = findViewById(R.id.text);
view.postDelayed(new Runnable() {
public void run() {
InputMethodManager manager = (InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
manager.showSoftInput(view, 0);
}
}, 100);
emulator 실행 시 다음과 같이 해보자.

~/dev/android-sdk/tools/emulator -avd 에뮬레이터이름 -partition-size 1024 -nojni -no-boot-anim -netfast

partition-size 는 성능과 관계는 없지만 기본적으로 emulator의 phone storage가 굉장히 작기 때문에 이렇게 설정해 놓으면 넉넉하게 사용할 수 있다.

nojni 는 테스트를 해 본 것은 아니지만 개념상 jni library check를 하지 않는 것이기 때문에 실행 속도가 좀 빨라지지 않을까 싶다.

no-noot-anim 이 녀석은 emulator를 처음 구동할 때 나오는 animation 효과를 하지 않도록 설정하는 것으로 emulator의 구동이 눈에 띄게 확연히 빨라지는 것을 체험할 수 있다.

1. keyDispatchingTimedOut 에 의해서 발생되는 원인

 5초내에 키또는 터치등에 대한 입력의 반응이 없을 경우, BroadcastReceiver가 10초내에
 작업을 종료하지 않을 경우 발생합니다. 안드로이드 문서에서 확인하세요.
 http://developer.android.com/guide/practices/design/responsiveness.html


안드로이드에서는 기본 입력 장치가 Touch이다. 실제로는 몇가지 입력 장치를 위한 준비가 되어 있는 것으로 보이며 인터넷에서 마우스를 위한 패치된 코드가 있다.

 

http://gitorious.org/0xdroid/frameworks_base/commit/a236aff3fcfca4ae3e200de48bfbb76daf2b7bb9

 

코드 패치 하기 전에 aesop에서 안드로이드의 key/touch event dispatch 과정을 정리한 내용이 있는데 이를 참고하면 좀 더 이해가 쉬울 것 같다.

 

 

 

실제 패치하여 동작시키면 완벽한 것은 아니고 몇가지 문제점을 가지고 있다.

일단 수정된 사항 위주로 정리해 본다.

 

/frameworks/base/core/java/android/view/RawInputEvent.java

 

public class RawInputEvent {
    // Event class as defined by EventHub.
    public static final int CLASS_KEYBOARD = 0x00000001;
    public static final int CLASS_ALPHAKEY = 0x00000002;
    public static final int CLASS_TOUCHSCREEN = 0x00000004;
    public static final int CLASS_TRACKBALL = 0x00000008;
    public static final int CLASS_MOUSE= 0x00000010;    
    // More special classes for QueuedEvent below.
    public static final int CLASS_CONFIGURATION_CHANGED = 0x10000000;

 

    ......

}

 

코드를 보면 알곘지만 keyboard, alphakey, touchscreen, trackball 을 기본 지원 장치로 준비해 두었다. 이 패치는 trackball의 내용을 수정하여 mouse에 대응하도록 작업되었다.

 

/frameworks/base/include/ui/EventHub.h

 

class EventHub : public RefBase
{
public:
    EventHub();
    
    status_t errorCheck() const;
    
    // bit fields for classes of devices.
    enum {
        CLASS_KEYBOARD      = 0x00000001,
        CLASS_ALPHAKEY      = 0x00000002,
        CLASS_TOUCHSCREEN   = 0x00000004,
        CLASS_TRACKBALL     = 0x00000008,
        CLASS_MOUSE         = 0x00000010
    };

 

    ......


 

java 소스와 c 소스를 모두 고쳐주어야 하기 때문에 위와 같이 두 곳에서 타입을 추가해준다.

 

/frameworks/base/libs/ui/EventHub.cpp

 

int EventHub::open_device(const char *deviceName)
{

    ......

 

    if (test_bit(BTN_MOUSE, key_bitmask)) {
        uint8_t rel_bitmask[(REL_MAX+1)/8];
        memset(rel_bitmask, 0, sizeof(rel_bitmask));
        LOGV("Getting relative controllers...");
        if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0)
        {
            if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
              if (test_bit(BTN_LEFT,key_bitmask) && 
                  test_bit(BTN_RIGHT,key_bitmask))
                device->classes |= CLASS_MOUSE;
              else

                device->classes |= CLASS_TRACKBALL;
            }
        }
    }
 

 

}

 

touchscreen의 경우 디바이스 드라이버로부터 전달되는 좌표 정보는 절대 좌표이지만 mouse나 trackball 의 경우는 상대적인 좌표 이동 정보를 받게 된다. mouse나 trackball의 좌표 처리를 REL_X와 REL_Y 조건을 비교하면 알 수 있는데 mouse와 trackball을 구분하기 위해서 BTN_LEFT, BTN_RIGHT의 유무도 체크하고 있다. (개인적인 생각으로 TRACK BALL도 추후에는 두 경우가 있을 것 같은데 구분하는 이유를 모르겠다.)

 

/frameworks/base/services/java/com/android/server/KeyInputQueue.java

 

    Thread mThread = new Thread("InputDeviceReader") {
        public void run() {

 

                        // Is it a key event?
                        if (type == RawInputEvent.EV_KEY &&
                                (classes&RawInputEvent.CLASS_KEYBOARD) != 0 &&
                                (scancode < RawInputEvent.BTN_FIRST ||
                                        scancode > RawInputEvent.BTN_LAST)) {
                            boolean down;
                            if (ev.value != 0) {
                                down = true;
                                di.mDownTime = curTime;
                            } else {
                                down = false;
                            }
                            int keycode = rotateKeyCodeLocked(ev.keycode);
                            addLocked(di, curTime, ev.flags,
                                    RawInputEvent.CLASS_KEYBOARD,
                                    newKeyEvent(di, di.mDownTime, curTime, down,
                                            keycode, 0, scancode,
                                            ((ev.flags & WindowManagerPolicy.FLAG_WOKE_HERE) != 0)
                                             ? KeyEvent.FLAG_WOKE_HERE : 0));
                        } else if (ev.type == RawInputEvent.EV_KEY) {
                            if (ev.scancode == RawInputEvent.BTN_TOUCH &&
                                    (classes&RawInputEvent.CLASS_TOUCHSCREEN) != 0) {
                                di.mAbs.changed = true;
                                di.mAbs.down = ev.value != 0;
                            }
                            if (ev.scancode == RawInputEvent.BTN_MOUSE &&
                                (((classes&RawInputEvent.CLASS_TRACKBALL) != 0) ||
                                 ((classes&RawInputEvent.CLASS_MOUSE) != 0))) {     
                        
                                di.mRel.changed = true;
                                di.mRel.down = ev.value != 0;
//                                send = true;
                            }
    
                        } else if (ev.type == RawInputEvent.EV_ABS &&
                                (classes&RawInputEvent.CLASS_TOUCHSCREEN) != 0) {
                            if (ev.scancode == RawInputEvent.ABS_X) {
                                di.mAbs.changed = true;
                                di.mAbs.x = ev.value;
                            } else if (ev.scancode == RawInputEvent.ABS_Y) {
                                di.mAbs.changed = true;
                                di.mAbs.y = ev.value;
                            } else if (ev.scancode == RawInputEvent.ABS_PRESSURE) {
                                di.mAbs.changed = true;
                                di.mAbs.pressure = ev.value;
                            } else if (ev.scancode == RawInputEvent.ABS_TOOL_WIDTH) {
                                di.mAbs.changed = true;
                                di.mAbs.size = ev.value;
                            }
    
                        } else if (ev.type == RawInputEvent.EV_REL &&
                                   (((classes&RawInputEvent.CLASS_TRACKBALL) != 0) ||
                                   ((classes&RawInputEvent.CLASS_MOUSE) != 0))) {

                            // Add this relative movement into our totals.
                            if (ev.scancode == RawInputEvent.REL_X) {
                                di.mRel.changed = true;
                                di.mRel.x += ev.value;
                            } else if (ev.scancode == RawInputEvent.REL_Y) {
                                di.mRel.changed = true;
                                di.mRel.y += ev.value;
                            }
                        }


                         if (send || ev.type == RawInputEvent.EV_SYN) {
                            if (mDisplay != null) {
                                if (!mHaveGlobalMetaState) {
                                    computeGlobalMetaStateLocked();
                                }
                                
                                MotionEvent me;
                                me = di.mAbs.generateMotion(di, curTime, true,
                                        mDisplay, mOrientation, mGlobalMetaState);
                                if (false) 
                                    Log.v(TAG, "Absolute: x=" + di.mAbs.x
                                        + " y=" + di.mAbs.y + " ev=" + me);
                                if (me != null) {
                                    if (WindowManagerPolicy.WATCH_POINTER) {
                                        Log.i(TAG, "Enqueueing: " + me);
                                    }
                                    addLocked(di, curTime, ev.flags,
                                            RawInputEvent.CLASS_TOUCHSCREEN, me);
                                }
                                me = di.mRel.generateMotion(di, curTime, false,
                                        mDisplay, mOrientation, mGlobalMetaState);
                                if (false) 
                                    Log.v(TAG, "Relative: x=" + di.mRel.x
                                        + " y=" + di.mRel.y + " ev=" + me);
                                if (me != null) {
                                   if ((classes & RawInputEvent.CLASS_TRACKBALL) != 0) {
                                        addLocked(di, curTime, ev.flags,
                                                 RawInputEvent.CLASS_TRACKBALL, me);
                                   } else {
                                       addLocked(di, curTime, ev.flags,
                                           RawInputEvent.CLASS_MOUSE, me);
                                   }

                                }
                            }
                        }

       }

    }; 

 

Thread를 수정해서 mouse 입력 처리를 할 수 있도록 한다. 크게 수정해야 될 곳은 3곳이다. 처음 두곳은 CLASS_TRACKBALL에 의해서만 relative evnet가 발생하는 것을 CLASS_MOUSE로도 가능하게 한다. 마지막은 원래는 relative event를 발생시키는 것이 CLASS_TRACKBALL 뿐이지만 이제는 CLASS_MOUSE도 발생시키므로 이를 구분해서 addLocked()을 호출하기 위한 코드이다.

 

/frameworks/base/services/java/com/android/server/WindowManagerService.java

 

마지막 수정이 실제 화면에 보여주기 위한 코드이다. 안드로이드의 경우 CLASS_TRACKBALL을 정의해서 mouse나 trackball에 대한 입력을 처리할 수 있도록은 해 두었는데 실제 화면상에 mouse cursor를 그리는 부분은 작업이 되어 있지 않다. 이를 처리하는 내용이 주된 내용이다.

   

import! android.graphics.Canvas;
import! android.graphics.Path;

 

화면상에 mouse cursor를 그려주기 위해서 Canvas와 Path를 import! 한다.

 

public class WindowManagerService extends IWindowManager.Stub implements Watchdog.Monitor {

    SurfaceSession mFxSession;
    private DimAnimator mDimAnimator = null;
    Surface mBlurSurface;
    boolean mBlurShown;
    Surface mMouseSurface;
    int mShowMouse = 0;
    int mMlx;
    int mMly;
    int mMlw;
    int mMlh;

    

    ...... 

 

}

 

mouse cursor는 새로운 surface에 그려주고 이를 surface flinger를 이용해서 합쳐주어야 하기 때문에 mMouseSurface를 추가한다. 다른 변수는 상대 좌표에서 마지막 그려진 좌표 등을 저장하기 위한 변수를 정의한다.

 

        private void process() {

                ...... 

                try {
                    if (ev != null) {
                        curTime = ev.when;
                        int eventType;
                        if (ev.classType == RawInputEvent.CLASS_TOUCHSCREEN) {
                            eventType = eventType((MotionEvent)ev.event);
                        } else if (ev.classType == RawInputEvent.CLASS_KEYBOARD ||
                                   ev.classType == RawInputEvent.CLASS_TRACKBALL || 
                                   ev.classType == RawInputEvent.CLASS_MOUSE) {

                            eventType = LocalPowerManager.BUTTON_EVENT;
                        } else {
                            eventType = LocalPowerManager.OTHER_EVENT;
                        }
                        try {
                            long now = SystemClock.uptimeMillis();

                            if ((now - mLastBatteryStatsCallTime)
                                    >= MIN_TIME_BETWEEN_USERACTIVITIES) {
                                mLastBatteryStatsCallTime = now;
                                mBatteryStats.noteInputEvent();
                            }
                        } catch (RemoteException e) {
                            // Ignore
                        }
                        mPowerManager.userActivity(curTime, false, eventType, false);
                        switch (ev.classType) {
                            case RawInputEvent.CLASS_KEYBOARD:
                                KeyEvent ke = (KeyEvent)ev.event;
                                if (ke.isDown()) {
                                    lastKey = ke;
                                    keyRepeatCount = 0;
                                    lastKeyTime = curTime;
                                    nextKeyTime = lastKeyTime
                                            + KEY_REPEAT_FIRST_DELAY;
                                    if (DEBUG_INPUT) Log.v(
                                        TAG, "Received key down: first repeat @ "
                                        + nextKeyTime);
                                } else {
                                    lastKey = null;
                                    // Arbitrary long timeout.
                                    lastKeyTime = curTime;
                                    nextKeyTime = curTime + LONG_WAIT;
                                    if (DEBUG_INPUT) Log.v(
                                        TAG, "Received key up: ignore repeat @ "
                                        + nextKeyTime);
                                }
                                dispatchKey((KeyEvent)ev.event, 0, 0);
                                mQueue.recycleEvent(ev);
                                break;
                            case RawInputEvent.CLASS_TOUCHSCREEN:
                                //Log.i(TAG, "Read next event " + ev);
                                dispatchPointer(ev, (MotionEvent)ev.event, 0, 0);
                                break;
                            case RawInputEvent.CLASS_MOUSE:
                                MotionEvent mmev = (MotionEvent)ev.event;
                                int mcx = mMlx + (int)(mmev.getX()* mmev.getXPrecision());
                                int mcy = mMly + (int)(mmev.getY()* mmev.getYPrecision());
                                mcx = ((mcx < 0) ? 0 :(mcx >= mDisplay.getWidth() ?(mDisplay.getWidth()-1):mcx));
                                mcy = ((mcy < 0) ? 0 :(mcy >= mDisplay.getHeight()?(mDisplay.getHeight() - 1):mcy));
                                
                                mmev.setLocation((float) mcx, (float) mcy);
                                dispatchPointer(ev, mmev, 0, 0);
                                if (mMouseSurface != null && (mMlx != mcx || mMly != mcy))            {                                                
                                    // Should we use lock? synchronized(mWindowMap) {
                                    Surface.openTransaction();
                                    if (DEBUG_INPUT)
                                        Log.i(TAG, 
                                              "Open transaction for the mouse surface");
                                    WindowState top = 
                                       (WindowState)mWindows.get(mWindows.size() - 1);
                                    try {
                                        if (DEBUG_INPUT)
                                            Log.i(TAG, "Move surf, x: " +  
                                                  Integer.toString(mcx) + " y:" 
                                                  + Integer.toString(mcy));
                                        
                                        mMouseSurface.setPosition(mcx,mcy);
                                        mMouseSurface.setLayer(top.mAnimLayer + 1);
                                        if (mShowMouse != 1) {
                                            mMouseSurface.show();
                                            mShowMouse = 1;
                                       }
                                        mMlx = mcx;
                                        mMly = mcy;
                                    } catch ( RuntimeException e) {
                                       Log.e(TAG, "Failure showing mouse surface",e);
                                   }
                                    Surface.closeTransaction();
                                }                                
                               break;


                            case RawInputEvent.CLASS_TRACKBALL:
                                dispatchTrackball(ev, (MotionEvent)ev.event, 0, 0);
                                break;
                            case RawInputEvent.CLASS_CONFIGURATION_CHANGED:
                                configChanged = true;
                                break;
                            default:
                                mQueue.recycleEvent(ev);
                            break;
                        }

                      }

                    }

                  } 

 

첫번째 수정은 위에서와 마찬가지로 CLASS_TRACKBALL로만 되어 있는 것에 CLASS_MOUSE에 대한 코드를 추가한 것이다.

두번째 위치는 mouse event 정보로 올라온 값으로부터 mouse가 그려져야 할 위치를 계산하는 코드이다.

setPosition으로 mMouseSurface의 위치를 설정하고 show()를 호출하여 mouse cursor를 보여준다. 한번 show되면 두번 호출하지 않기 위하여 mShowMouse를 이용해서 flag 관리를 한다.

 

    private final void performLayoutAndPlaceSurfacesLockedInner(
            boolean recoveringMemory) {
        final long currentTime = SystemClock.uptimeMillis();
        final int dw = mDisplay.getWidth();
        final int dh = mDisplay.getHeight();

        final int N = mWindows.size();
        int i;

        // FIRST LOOP: Perform a layout, if needed.
        performLayoutLockedInner();

        if (mFxSession == null) {
            mFxSession = new SurfaceSession();
        }

        if (mMouseSurface == null) {
            int mMx, mMy, mMw, mMh;
            Canvas mCanvas;
            Path mPath = new Path();

            if (DEBUG_INPUT)
                Log.i(TAG, "Create Mouse Surface");
            
            mMw = 20;
            mMh = 20;
            mMx = (mDisplay.getWidth() - mMw) / 2;
            mMy = (mDisplay.getHeight() - mMh) / 2;
            
            try {
               
                /*
                 *First Mouse event, create Surface
                 */
                
                mMouseSurface =
                    new Surface(mFxSession,
                                0,-1,mMw,mMy,
                                PixelFormat.TRANSPARENT,
                                Surface.FX_SURFACE_NORMAL);
                mCanvas = mMouseSurface.lockCanvas(null);
                mCanvas.drawColor(0x0);

                
                
                mPath.moveTo!(0.0f,0.0f);
                mPath.lineTo(16.0f, 0.0f);
                mPath.lineTo(0.0f, 16.0f);
                mPath.close();
                mCanvas.clipPath(mPath);
                mCanvas.drawColor(0x66666666);

                mMouseSurface.unlockCanvasAndPost(mCanvas);
                mMouseSurface.openTransaction();      
                mMouseSurface.setSize(mMw,mMh);
                mMouseSurface.closeTransaction();
                
            } catch (Exception e) {
                Log.e(TAG, "Exception creating mouse surface",e);
            }
            mMlx = mMx;
            mMly = mMy;
            mMlw = mMw;
            mMlh = mMh;
        }

        ...... 

}

 

여기에서는 mMouseSurface를 생성해 주고, mMouseSurface에서 mCanvas와 mPath를 이용해서 mouse cursor를 그려준다. 실제로 여기에서는 mMouseSurface에 그림 그려주는 것과 좌표를 초기화 해주는 것 외에는 특별한 작업은 하지 않는다. mouse 입력에 따른 동작은 이전 코드에서 처리된다.

출처 : http://blog.daum.net/_blog/BlogTypeView.do?blogid=0CNH3&articleno=16011039#ajax_history_home

 첫번째 글에서 간략하게 정리를 하였지만, 인터넷을 검색을 하다보니 상세하게 설명이 되어 있어서 글을 퍼왔습니다.

꼭! 참조 하시길 바랍니다.

1. Activity의 4가지 주요 상태 (4 essential states of Activity)

 

Active/Running 상태

Activity A가 화면의 가장 앞(foreground)에 있어 사용자가 직접 볼 수 있고, 포커스를 가지고 있는 상태.

다시 말하자면 입/출력이 가능한 상태.

 

 

 

Pause 상태

Active상태의 activity A가 화면의 foreground를 새로 점유한 activity N에게 포커스를 잃었지만 아직은 A의 일부가 보이는 상태 (foreground를 획득한 activity N이 화면 전체를 사용하지 않거나, 반투명하게 구현 되어 있을 때).

 

 

 

Stop 상태

Active/Pause상태의 activity A가 full-screen크기의 activity N에게 화면 foreground를 선점 당한 상태.

 

 

 

Killed (Dead) 상태

Activity A가 생성되지도 않았거나 생성 후 소멸된 상태.

 

 

 

 

2. Activity의 상태 변이와 callback 메소드

 

Activity의 상태변이도

 

위에서 설명한 4가지 Activity상태간 변이 시에 코드의 흐름을 나타낸 그림이다. (클릭하면 크게 보임)


 

참고. onRestoreInstanceState(Bundle) onSaveInstanceState(Bundle)메소드들은 life cycle 에 직접적으로 관여하는 메소드는 아니며 상황에 따라 호출이 생략될 수 있다. 다음 단락: Activity의 강제 종료와 복구에서 자세히 설명.

 

 

위의 그림에서 파란색 실선은 정상적인 Actvity의 흐름이며 붉은색 점선은 비정상적인 Activity의 흐름이다.

위 그림을 이용하면 수 많은 Activity의 상태변이 case들에서 어떤 callback들이 어떤 차례로 호출되는지 쉽게 볼 수 있다.

 

예를 들어, Activity가 처음 실행돼서 사용자에게 사용되다 정상 종료 된다면 다음과 같은 callback이 차례로 호출된다.

onCreate(Bundle) -> onStart() -> onResume() -> onPause() -> onStop() -> onDestory()

 

 

또, Running상태의 Activity A가 다른 Activity B에게 완전히 가렸다 A가 다시 foreground로 와서 사용자에게 사용되는 경우는 다음과 같은 callback이 차례로 호출된다.

onSaveInstanceState(...) -> onPause() -> onStop() -> onRestart() -> onStart() ->onResume()

 

 

마지막 예로, 화면의 일부가 가린 pause 상태의 Activity A가 system 자원(메모리)의 부족으로 system에 의해 강제로 종료 당했다가 system 자원의 여유가 생겨 다시 복구 될 때는 다음과 같은 callback이 차례로 호출된다.

강제종료 -> onCreate(…) -> onStart() -> onRestoreInstanceState(...) -> onResume()

 

 

 

Life Cycle 관련 Callback 메소드 분석

 

Activity의 상태변이 시 호출되는 callback들을 각각 자세히 설명하면 다음과 같다. (클릭하면 크게 보임)



 

한가지 중요한 것은 위의 callback을 오버라이딩 할 때는 다음과 같이 super클래스의 원래 callback을 먼저 호출하여야 한다.

protected void onPause() {
super.onPause();
...
}


 


 

 

 

3. Activity의 강제 종료와 복구

 

System에 의한 Activity의 강제 종료

 

스마트폰 플랫폼은 PC와 달리 제한된 리소스(대표적으로RAM)을 가지고 있기 때문에 여러 가지 작업을 동시에 진행할 때 리소스 부족현상에 직면할 수 있다.

 

이는 심각한 문제를 유발 할 수도 있는데, 한가지 예를 들어 보자. 예를 들어 사용자가 이용하고 있는 게임 어플리케이션의 Activity A가 foreground서 사용자와 interact하고 있다고 치자. 이때 전화가 걸려오면 시스템은 incoming call Activity B를 foreground에 띄워 사용자에게 전화가 왔음을 알려야 한다. 하지만 만약에 A가 시스템의 리소스를 거의 전부 점유하고 있는 상황이라면 B Activity를 띄우는 것이 불가능 할 수 있다.

 

스마트폰에서 게임을 하는 것 보다 전화를 받는 Task가 훨씬 중요한 것이 일반적임으로, 이 경우 디바이스의 효율적인 운영이 이뤄진다고 볼 수 없고 이는 곧 user의 불편함으로 이어진다.

 

그래서 안드로이드에서는 여러 개의 Activity를 운영 중 시스템 리소스가 부족하면 특정 상태에 있는 Activity를 강제로 종료 할 수 있게 디자인 되어있다. Activity의 상태에 따른 강제 종료 우선 순위는 다음과 같다.

Running 상태: 절대 강제 종료 되지 않음

Pause 상태: 강제 종료 2순위

Stop 상태: 강제 종료 1 순위

 

전 단락의 life cycle 관련 callback 테이블을 보면 강제 종료 칼럼에 yes라고 표기된 onPause(), onStop(), onDestroy()가 있는데 이들 callback이 호출 된 뒤에는 Activity가 언제든지 강제 종료 될 수 있다는 뜻이다.

 

한가지 중요한 것은 onPause() callback이 실행 중에는 Activity는 아직 Running 상태이고 onPause()가 리턴 하자마자 Activity는 Pause상태가 되기 때문에 onPause() callback은 항상 return이 보장되는 반면 나머지 2 개의 callback, onStop(), onDestroy()이 실행 될 때는 Activity는 각각 Pause상태, Stop상태이기 때문에 return이 보장되지 않는다.

 

이런 이유(onPause() 이후에는 Activity가 강제 종료 당할 수 있음)로 onPause() callback에서 사용자가 진행하던 작업을 저장 하는 등의 강제 종료에 대비한 작업을 해주어야 한다.

 

 

 

강제 종료된 Activity의 복구

 

강제 종료된 Activity는 가동하는데 충분한 resource가 확보되면 (예를 들면 Activity A를 강제 종료 시켰던 Activity B의 종료 등) 자동으로 복구되지만, 한가지 작업이 이루어 지지 않는다면 사용자에게 심각한 불편을 초래할 수 있다. 다음과 같은 시나리오를 가정해 보자.

User가 계산기 어플리케이션의 Activity A를 통해 시간이 오래 걸리는 작업(예, 숫자 100개 더하기 중 50개를 더한 상황) 중에 전화가 걸려왔는데 시스템의 리소스 부족으로 incoming call Activity B를 띄울 수 없는 상황이 발생 했다고 쳐보자. 시스템은 A를 강제 종료 시켜 부족한 리소스를 확보하고 B를 사용자에게 보여줘 사용자가 전화를 받을 수 있게 한다. 전화 통화를 완료한 후 시스템은 강제종료 된 A를 자동으로 복구 했지만 사용자가 이미 수행하고 있던 작업(100개중 50를 더한 중간 결과)의 상태는 초기화 되어 버리고 사용자는 다시 처음부터 작업을 수행해야 한다.

 

위와 같은 불편을 막기 위해, 안드로이드의 Activity 클래스는 onSaveInstanceState(Bundle) 메소드와 onRestoreInstanceState(Bundle) callback 메소드를 제공한다.

 

우선 위의 Activity 상태변이도에서 본것과 같이,

onSaveInstanceState(Bundle)은 onPause()전에 호출되며 파라미터로 전달 받는 Bundle 인스턴스에 현재 activity의 상태를 저장하게 된다. 저장된 Bundle인스턴스는 시스템이 Activity를 자동으로 복원할 때 호출되는 onCreate(Bundle) -> onStart() -> onRestroreInstanceState(Bundle) -> onResume() callback 중 onCreate(…) onRestoreInstanceState(…) callback에 모두 파라미터로 전달 됨으로 양쪽 어디서건 사용해서 강제종료 되기 전의 상태로 Activity를 복구 시키면 된다.

 

한가지 참고할 사상은 onSaveInstanceState(Bundle)과 onRestroreInstanceState(Bundle)은 life cycle과 직접적으로 관련이 있는 callback이 아님으로 Activity의 상태 변화 시 항상 호출된다는 보장이 없다. 논리적으로 꼭 필요한 상황에서만 호출됨으로 Activity상태가 바뀔 때 예외 없이 호출 되어야 하는 루틴은 life cycle 관련 callback (onResume(), onPause() 등)에서 구현 하여야 한다.

 

예를 들면, 사용자가 Activity 를 디바이스의 BACK key 로 직접 종료하거나 Activity.finish() 메소드를 사용해 정상 종료되는 경우에는 Activity의 현 상태를 복구할 필요가 없기 때문에 onSaveInstanceState(Bundle) callback의 호출은 생략된다.

 

 

 

 

4. Activity 생명주기 예제 (Activity Life Cycle Demo)

어떠한 상황에서 Activity가 상태변이를 일으키는지 눈으로 직접 확인하기 위해 예제를 작성했지만, Activity의 강제 종료를 시뮬레이션 하기 위해서는 실제 메모리가 부족한 상황을 만들어야 하는데 이 부분은 추후 업데이트를 할 예정이다.

 

예제는 2개의 버튼을 가지고 있는 Main Activity 한 개와 sub Activity 2개로 이루어졌다.

Sub Activity중 하나는 Pause 상태를 재현하기 위한 반투명 배경의 Activity이며 (Pause 상태의 조건은 running 중인 activity가 반투명 Activity난 non-full screen Activity에 의해 일부가 가렸을 때 임을 상기), 두 번째 Activity는 Main Activity 의 Stop상태를 재현하기 위한 full screen창이다.

 

상태변이를 확인하기 위해서는 life cycle관련 callback이 호출될 때 마다 Logcat에 Log를 남기는 방법을 사용했다.

(Logcat 사용 방법은 링크 참조)

 

 

Running 상태 재현

 

Activity의 생성시를 보면 다음과 같은 callback들이 호출되는 것을 볼 수 있다.

 

Logcat Log 내용

 

 

 

Running 상태 -> Pause상태 -> Running 상태 재현

 

Running상태인 Main Activity를 Pause상태로 전환 시키기 위해 반투명 sub activity를 foreground로 불러오면 다음과 같은 순서로 callback들이 호출된다.

 

Logcat Log내용

 

눈 여겨 볼만한 점은 onSaveInstanceState(Bundle)의 호출이다. Pause상태의 main activity는 언제 강제 종료 당할지 모르기 때문에 onSaveInstanceState(Bundle)이 call 되고 있다.

 

 

다시 Main Activity로 돌아오기 위해 반투명 sub Activity를 종료하면 (finish() 호출) 다음과 같은 callback이 차례로 호출된다.

 

Logcat Log내용

 

Sub Activity를 우선 종료 후 Main Activity를 foreground로 되돌리는 것이 아니라 Sub Activity를 Pause상태로 만들고 Main Activity가 Sub Activity를 가리면 Sub Activity가 Stop상태로 전환 되고 소멸 된다.

 

 

 

Running 상태 -> Stop상태 -> Running 상태 재현

 

Running 상태인 Main Activity를 Stop상태로 전환 시키기 위해 full-screen size의 Activity를 main activity 앞으로 불러온다.

 

Logcat Log 내용

 

여기서도 Main Activity가 Pause상태에 들어가고 Sub Activity가 foreground를 점유하면서 Main Activity를 완전히 가리면 Main Activity가 Stop() 상태로 전환되는 것을 볼 수 있다.

 

 

Full screen sub Activity를 닫으면 (Activity.finish() 메소드 호출) main activity가 running 상태로 복귀 하는 것을 볼 수 있다.

 

Logcat Log 내용

 

Stop상태였던 Main Activity가 Running 상태로 전환되면서 onRestart()가 호출되는 것을 볼 수 있다.

또, Sub Activity는 Activity.finish() 메소드를 사용해 정상적으로 종료되는 상황이라 onPause()호출 전에 onSaveInstanceState(Bundle) 메소드가 생략된 것도 볼 수 있다.



 예제 소스


출처 : http://tigerwoods.tistory.com/30

//show webapp:

Uri uri = Uri.parse("http://www.google.com");
Intent it  = new Intent(Intent.ACTION_VIEW,uri);
startActivity(it);

//show maps:
Uri uri = Uri.parse("geo:38.899533,-77.036476");
Intent it = new Intent(Intent.Action_VIEW,uri);
startActivity(it);

//show ways
Uri uri = Uri.parse("http://maps.google.com/maps?f=d&saddr=startLat%20startLng&daddr=endLat%20endLng&hl=en");
Intent it = new Intent(Intent.ACTION_VIEW,URI);
startActivity(it);

//call dial program
Uri uri = Uri.parse("tel:xxxxxx");
Intent it = new Intent(Intent.ACTION_DIAL, uri); 
startActivity(it); 

Uri uri = Uri.parse("tel.xxxxxx");
Intent it =new Intent(Intent.ACTION_CALL,uri);
//don't forget add this config:<uses-permission id="android.permission.CALL_PHONE" />

//send sms/mms
//call sender program
Intent it = new Intent(Intent.ACTION_VIEW);  
it.putExtra("sms_body", "The SMS text");  
it.setType("vnd.android-dir/mms-sms");  
startActivity(it); 

//send sms
Uri uri = Uri.parse("smsto:0800000123");  
Intent it = new Intent(Intent.ACTION_SENDTO, uri);  
it.putExtra("sms_body", "The SMS text");  
startActivity(it); 

//send mms
Uri uri = Uri.parse("content://media/external/images/media/23");  
Intent it = new Intent(Intent.ACTION_SEND);  
it.putExtra("sms_body", "some text");  
it.putExtra(Intent.EXTRA_STREAM, uri);  
it.setType("image/png");  
startActivity(it);

//send email

Uri uri = Uri.parse("mailto:xxx@abc.com");
Intent it = new Intent(Intent.ACTION_SENDTO, uri);
startActivity(it);

Intent it = new Intent(Intent.ACTION_SEND);  
it.putExtra(Intent.EXTRA_EMAIL, "me@abc.com");  
it.putExtra(Intent.EXTRA_TEXT, "The email body text");  
it.setType("text/plain");  
startActivity(Intent.createChooser(it, "Choose Email Client")); 

Intent it=new Intent(Intent.ACTION_SEND);    
String[] tos={"me@abc.com"};    
String[] ccs={"you@abc.com"};    
it.putExtra(Intent.EXTRA_EMAIL, tos);    
it.putExtra(Intent.EXTRA_CC, ccs);    
it.putExtra(Intent.EXTRA_TEXT, "The email body text");    
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");    
it.setType("message/rfc822");    
startActivity(Intent.createChooser(it, "Choose Email Client"));  


//add extra
Intent it = new Intent(Intent.ACTION_SEND);  
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");  
it.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/mysong.mp3");  
sendIntent.setType("audio/mp3");  
startActivity(Intent.createChooser(it, "Choose Email Client"));

//play media
Intent it = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse("file:///sdcard/song.mp3");
it.setDataAndType(uri, "audio/mp3");
startActivity(it);

Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1");  
Intent it = new Intent(Intent.ACTION_VIEW, uri);  
startActivity(it); 

//Uninstall
Uri uri = Uri.fromParts("package", strPackageName, null);  
Intent it = new Intent(Intent.ACTION_DELETE, uri);  
startActivity(it);

//uninstall apk
Uri uninstallUri = Uri.fromParts("package", "xxx", null);
returnIt = new Intent(Intent.ACTION_DELETE, uninstallUri);

//install apk
Uri installUri = Uri.fromParts("package", "xxx", null);
returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri);

//play audio
Uri playUri = Uri.parse("file:///sdcard/download/everything.mp3");
returnIt = new Intent(Intent.ACTION_VIEW, playUri);

//send extra
Intent it = new Intent(Intent.ACTION_SEND); 
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text"); 
it.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/eoe.mp3"); 
sendIntent.setType("audio/mp3"); 
startActivity(Intent.createChooser(it, "Choose Email Client"));

//search
Uri uri = Uri.parse("market://search?q=pname:pkg_name"); 
Intent it = new Intent(Intent.ACTION_VIEW, uri); 
startActivity(it); 
//where pkg_name is the full package path for an application 

//show program detail page
Uri uri = Uri.parse("market://details?id=app_id"); 
Intent it = new Intent(Intent.ACTION_VIEW, uri); 
startActivity(it); 
//where app_id is the application ID, find the ID 
//by clicking on your application on Market home 
//page, and notice the ID from the address bar


//search google
Intent intent = new Intent();
intent.setAction(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY,"searchString")


[출처] intent 사용법|작성자 밥플


'안드로이드' 카테고리의 다른 글

안드로이드에서 마우스 이벤트 처리하기  (0) 2011.01.27
Activity Lifecycle - 2[필독]  (0) 2011.01.27
Device를 Rotate시 꼭 알아두어야 할사항.  (0) 2011.01.27
AndroidManifest  (0) 2011.01.26
Permission List  (0) 2011.01.26
 
1. Rotate를 처리하면 Layout을 항상 다시 그려준다.
2. 이에 따라 Layout을 다시 그려주게 되면 View값의 ID값을 다시 지정해주어야 한다.
3. 그렇기 때문에 만약 처음에는 View가 나타나다 Rotate만 처리되고 Layout의
    ITEM이 나타나지 않는 현상이 발생한다면
4. View의 id값이 다를수도 있다는 것을 첫번째 유의해야 한다.

'안드로이드' 카테고리의 다른 글

Activity Lifecycle - 2[필독]  (0) 2011.01.27
Telephony & SMS & Search & Play Media & MMS & Web Intent  (0) 2011.01.27
AndroidManifest  (0) 2011.01.26
Permission List  (0) 2011.01.26
ViewSwitcher 예제 코드  (0) 2011.01.26

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

<manifest>

<uses-permission />

<permission />

<permission-tree />

<permission-group />

<instrumentation />

<uses-sdk />

<uses-configuration />

<uses-feature />

<supports-screens />

<application>

<activity>

<intent-filter>

<action />

<category />

<data />

</intent-filter>

<meta-data />

</activity>

<activity-alias>

<intent-filter> . . . </intent-filter>

<meta-data />

</activity-alias>

<service>

<intent-filter> . . . </intent-filter>

<meta-data/>

</service>

<receiver>

<intent-filter> . . . </intent-filter>

<meta-data />

</receiver>

<provider>

<grant-uri-permission />

<path-permission />

<meta-data />

</provider>

<uses-library />

</application>

</manifest>

 

매니패스트 파일은 어플리케이션에 대한 전반적인 정보를 담고 있는 파일로, 어플리케이션이 실행되기 전에 시스템이 알고 있어야 하는 파일이다. 이 매니페스트 파일 안에는 어플리케이션 컴포넌트(Activity, Service, intents, Content provider, Broadcast Receivers)에 대한 노드를 포함하고 있고 Intent filter와 같이 permissions을 사용해 다른 컴포넌트와 어플리케이션이 어떻게 상호 작용을 하는지를 결정한다.

 

</receiver>

<provider>

<grant-uri-permission />

<path-permission />

<meta-data />

</provider>

<uses-library />

</application>

</manifest>

<manifest>

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

    package="com.example.android.notepad"

android:versionCode="1"

    android:versionName="1.0">

[어플리케이션 태그  Permission 태그들]

</manifest>

AndroidManifest.xml의 root element로써 <manifest> 태그가 전체를 감싸는 구조를 하고 있으며 package attribute의 값으로는 어플리케이션의 base를 지정하는 Java package 이름이 온다.

 

<uses-permission>

<uses-permission android:name="string" />

어플리케이션의 필요한 기능의 권한을 정의해준다. 여기에 정의된 권한은 설치 과정 중 사용자에게 보여주고 권한부여 혹은 거절이 결정된다.

android:name  애플리케이션 안에 <permission>엘리먼트를 사용해서 정의된 퍼미션 이름

다른 애플리케이션에 의해 정의된 퍼미션의 이름

표준 시스템 퍼미션의 이름( - android.permission.INTERNET)

 

<permission>

<permission android:description="string resource"

android:icon="drawable resource"

android:label="string resource"

android:name="string"

android:permissionGroup="string"

android:protectionLevel=["normal" | "dangerous" | "signature" | "signatureOrSystem"]

/>

컴포넌 사용하기 위한 권한 중에 안드로이드가 제공하는 권한 이외에 다른 권한이 필요할 때 정의한다. 다른 어플리케이션이 이 컴포넌트를 사용하려면 자신의 매니페스트에 uses-permission 태그를 설정해 주거나<activity android:permission>속성에 권한을 추가해 주면 된다.

                                android:description  퍼미션의 설명으로 사용자에게 퍼미션을 설명하기 위해 사용 될 수도 있다.

android:icon  퍼미션을 의미하는 아이콘의 리소스의 레퍼런스로 예를 들어 res/drawable/app_note.png라는 파일이 있다면 @drawable/app_note라고 쓴다.

android:label  사용자에게 보여질 수 있는 퍼미션의 이름다. 배포가 될때는 string.xml에 정의하고 @string/app_name 같이 사용하여야 한다.

android:name  코드에서 사용되는 퍼미션의 이름이다. com.example.project.PERMITTED_ACTION과 같이 고유한 이름을 사용해야 한다.

android:permissionGroup  그룹에 퍼미션을 할당한다. <permission-group>으로 선언되어진 그룹의 이름을 지정한다.

android:protectionLevel  이 레벨 설정에 따라서 사용자가 퍼미션을 요구하는 애플리케이션을 알 수 있거나 해당 퍼미션을 누가 사용하는지를 알 수 있다.

normal : 디폴트 값으로 낮은 수위의 위험을 갖는다. 최소한의 위험요소를 가진 애플리케이션이 다른 애플리케이션 레벨의 기능들에 대해 접접근하는 것 부여한다.

dangerous : 높은 수위의 위험을 갖는다. 사용자의 사적 데이터 접근이나 디바이스에 대한 제어를 허용한다.

signature : 애플리케이션이 다른 애플리케이션과 같은 인증서를 가지고 사인되었을때에 한하여 시스템이 퍼미션을 부여한다.

signatureOrSystem : 시스템이 안드로이드 시스템 이미지 안에 있거나 시스템 이미지 안에 있는 것들과 같은 인증서로 사인된 애플리케이션에 한하여 부여한다.

 

<permission-tree>

<permission-tree android:icon="drawable resource"

   android:label="string resource"

      android:name="string" />

퍼미션 트리에 대한 기본적인 이름을 선언한다. 이 애플리케이션은 트리 내의 모든 이름들에 대한 소유권을 갖는다.

 

<permission-group>

<permission-group android:description="string resource"

 android:icon="drawable resource"

 android:label="string resource"

        android:name="string" />

퍼미션 그룹의 이름을 선언한다.

 

<instrumentation>

실행 시 액티비티와 서비스를 테스트 하기 위한 프레임워크롤 제공하며, 선언된 클래스는 시스템리소스와 상호작용을 모니터링하기 위한 연결 고리를 제공한다.

Jfeature를 설치해 Test를 사용할 경우

<instrumentation android:targetPackage="com.jfeature" android:name="android.test.InstrumentationTestRunner" />

<instrumentation android:functionalTest=["true" | "false"]

android:handleProfiling=["true" | "false"]

android:icon="drawable resource"

android:label="string resource"

android:name="string"

android:targetPackage="string" />

이 엘리먼트가 매니페스트에 자동으로 생성된다.

android:functionalTest  기능적 테스트를 위해 수행되어야 하는지 여부를 표시한다. 디폴트 값은 false이다.

android:handleProfiling  프로파일링을 on, off 할 것인지의 여부를 표시한다. 프로파일링을 시작할 때와 멈출때는 결정하려면 ture, 프로파일링이 시행되는 모든 시간 동안 계속 하려면 false로 표시한다. 디폴트는 false이다.

android:targetPackage  타겟으로 정할 패키지 주소를 입력한다.

 

<uses-sdk>

<uses-sdk android:minSdkVersion="integer"

android:maxSdkVersion="integer"

amdroid:targetSdkVersion="integer" />

Android Version이 아닌 API 레벨을 설정한다.

android:minSdkVersion  API의 최소레벨을 지정하는 함수로 Default값은 1이다.

시스템이 지정한 값보다 낮은 버전 이라면 시스템에 설치 되지 않는다.

android:maxSdkVersion  API의 최소레벨을 지정하는 함수이다. 시스템이 지정한 값보다 높은 버전이라면 시스템에 설치 되지 않는다. 이 애트리뷰트를 사용하는 것을 권장하지 않는다. 왜냐하면 신규 버전의 안드로이드 플렛폼 배치가 차단되고 더 높은 API 레벨로 시스템이 업데이트 된 이후 사용자의 디바이스에서 maxSdkVersion이 시스템보다 낮은 값으로 설정된 애플리케이션이 제거된다.

android:targetSdkVersion - 애플리케이션이 타겟으로 하고 있는 API 레벨을 지정하는 함수이다.

 

<uses-feature>

<uses-feature android:glEsVersion="integer"

       android:name="string" />

SDK버전을 선언하는 것과 비슷하게 기능을 지원하지 않는 디바이스 상에는 설치가 되지 않도록 하는 옵션이다. 예를 들어 디바이스가 카메라를 지원하지 않으면 어플리케이션이 설치 되지 않는다. 애플리케이션이 특정 디바이스를 사용해야 한다면 이 옵션을 추가해야 한다.

                                   android:glEsVersion  애플리케이션이 필요로 하는 GLES 버전이다.

android:name  애플리케이션이 필요로 하는 기능의 이름으로써 예로 android.hardware.camera와 같이 쓰이는데 이것은 애플리케이션이 카메라를 필요로 한다는 의미이다.

<supports-screens>

<supports-screens android:smallScreens=["true" | "false"]

                 android:normalScreens=["true" | "false"]

                 android:largeScreens=["true" | "false"]

                 android:anyDensity=["true" | "false"] />

애플리케이션이 지원하는 스크린 크기를 지정하는 옵션이다.(멀티해상도 관련)

android:smallScreens  애플리케이션이 normal보다 더 작은 스크린을 지원하는지 여부이다. API 레벨 4이상에서는 디폴트 값이 ture이고 다른 레벨에서는 false이다.

android:normalScreens  애플리케이션이 normal 스크린을 지원하는지 여부다. 디폴트 값은 true이다.

android:largeScreens  애플리케이션이 normal보다 더 큰 스크린을 지원하는지 여부이다. API 레벨 4이상에서는 디폴트 값이 ture이고 다른 레벨에서는 false이다.

android:anyDensity  애플리케이션이 임의의 스크린 밀도를 수용할 수 있는 지에 대한 옵션이다. API레벨 4이상에서는 디폴트 값이 true이고 다른 레벨에서는 false이다.

 

<application>

<application android:allowClearUserData=["true" | "false]

android:allowTaskReparenting=["true" | "false"]

android:debuggable=["true" | "false"]

android:description="string resource"

android:enabled=["true" | "false"]

android:hasCode=["true" | "false"]

android:icon="drawable resource"

android:label="string resource"

android:manageSpaceActivity="string"

android:name="string"

android:permission="string"

android:persistent=["true" | "false"]

android:process="string"

android:task="string"

android:theme="resource or theme" >

. . .

</application>

이 엘리먼트는 반드시 한번 사용되어야 한다. Application 아래에 있는 서브 엘리먼트는 없거나 순서가 바뀌어도 문제되지 않는다. 애플리케이션의 메타데이타(타이틀, 아이콘, 테마 등)을 지정한다.

                                    android:allowClearUserData  사용자들에게 사용자 데이터를 제거할 수 있는 옵션을 부여할 것인가에 대한 애트리뷰트이다.

                                    android:allowTaskReparenting  이 애트리뷰트가 true로 설정되어 있다면 액티비티는 시작된태스크부터 affinity를 갖는 태스크가 된다.

예를 들어 e-mail Activity에서 web page링크를 클릭하게 되면 해당 페이지가 보여지는 브라우저가 시작되게 된다. 이 Activity는 Browser Application에 정의 되어 있지만 e-mail Task의 일부로 실행된 상태이다. 만약 android:allowTaskReparenting이 true로 되어있고 Browser Task로 Reparenting되면 Browser어플리케이션에서 그 페이지가 보여질 것이고 다시 e-mail Task가 보여지면 그 Activity는 보이지 않게 된다. 디폴트 값은 false이다.

D:\WORK\리소스\Task.png

                                 android:debuggable  사용자모드로 실행중일 때 디버그 될수 있는지를 설정한다. 디폴트 값은 false이다. false로 설정한다면 Wating for Debugger화면에서 더 이상 진행되지 않는다.

     android:enable  애플리케이션의 컴포넌트를 인스턴스화 할 수 있는지를 설정한다. 디폴트 값은true이다. “true”라면 각 컴포넌트의 enabled 애트리뷰트가 그 컴포넌트의 활성화 여부를 결정하고false라면 모든 컴포넌트들은 비활성화 된다.

 android:hasCode  시스템 코드가 아닌 다른 코드를 포함하고 있는지를 설정한다. 디폴트 값은 true이다.

 android:manageSpaceActivity  디바이스상에서 애플리케이션이 점유하는 메모리를 사용자가 관리 할 수 있도록 하는 액티비티 이름이다.

adroid:permission  클라이언트와 애플리케이션이 상호작용하기 위해 필요한 퍼미션 이름이다. 이 애트리뷰트는 애플리케이션 안의 모든 컴포넌트에 퍼미션을 적용한다.

android:persistent  애플리케이션이 항상 실행 상태로 있는지의 설정값이다. 디폴트는 false이다.

android:process  애플리케이션 프로세스의 이름이다. 애플리케이션 안에 모든 컴포넌트는 이 애트리뷰트의 프로세스로 실행이 되고 각 컴포넌트에 process 애트리뷰트를 설정 함으로써 오버라이드 할 수 있다. 디폴트 <manifest>엘리먼트의 package이름이다. 이 애트리뷰트의 이름이 콜론(:)으로 시작되면 private하고 소문자로 시작한다면 그 이름을 가진 글로벌 프로세스가 만들어진다. 글로벌 프로세스는 공유될 수 있어 리소스 사용을 감소시킨다.

android:taskAffinity  애플리케이션 안 모든 액티비티에 적용되는 affinity이름이다. 액티비티 내에 taskAffinity를 설정했다면 적용되지 않는다. 디폴트로 <manifest>엘리먼트의 package 이름을 가지고 어플리케이션내에 액티비티는 동일 Affinity를 공유한다.

android:theme  애플리케이션 안의 모든 액티비티에 적용되는 스타일 리소스에 대한 레퍼런스 이다. 각각의 액티비티는 이 설정을 override 할 수 있다.

 

<activity>

<activity android:allowTaskReparenting=["true" | "false"]

android:alwaysRetainTaskState=["true" | "false"]

android:clearTaskOnLaunch=["true" | "false"]

android:configChanges=[one or more of: "mcc" "mnc" "locale"

"touchscreen" "keyboard" "keyboardHidden" "navigation" "orientation" "fontScale"]

android:enabled=["true" | "false"]

android:excludeFromRecents=["true" | "false"]

android:exported=["true" | "false"]

android:finishOnTaskLaunch=["true" | "false"]

android:icon="drawable resource"

android:label="string resource"

android:launchMode=["multiple" | "singleTop" | "singleTask" | "singleInstance"]

android:multiprocess=["true" | "false"]

android:name="string"

android:permission="string"

android:process="string"

android:screenOrientation=["unspecified" | "user" | "behind" | "landscape" | "portrait" | "sensor" | "nonsensor"]

android:stateNotNeeded=["true" | "false"]

android:taskAffinity="string"

android:theme="resource or theme"

android:windowSoftInputMode=[one or more of: "stateUnspecified"

"stateUnchanged" "stateHidden"

"stateAlwaysHidden" "stateVisible"

"stateAlwaysVisible" "adjustUnspecified"

"adjustResize" "adjustPan"] >

. . .

</activity>

각각의 액티비티마다 <activity>태그가 필요하다. 매니페스트 파일에 액티비티가 정의되어 있지 않다면 해당 액티비티를 실행시킬 수 없다.(런타임 오류가 발생)

                        android:allowTaskReparenting  친화력 있는 태스크 설정 애트리뷰트이다. 이 애트리뷰트가 설정되지 않으면 <application>엘리먼트의 allowTaskReparenting에 설정된 값이 액티비티에 적용된다. 디폴트 값은 false이다.

                        android:alwaysRetainTaskState  사용자가 Task를 오랫동안 방치하면 시스템은 Root Activity를 제외한 모든 Activities의 Task를 Clear 시킨다. 이 애트리뷰트가 true로 설정 되어 있다면 Task는 오랜 시간이 지나도 Stack에 있는 모든 Activity를 유지한다. 디폴트 값은 false이다.

                        android:clearTaskOnLaunch  이 속성이 true로 설정되어 있으면 사용자가 Task를 떠났다가 다시 돌아 올 때마다 Stack은 Root Activity로 정리된다. 디폴트 값은 false이다.

                        Android:configChanges  시스템은 각 어플리케이션을 종료하고 재시작한 뒤 리소스 값을 다시 읽어 들임으로써 언어, 위치, 하드웨어에 대한 런타임 변경을 지원한다. 런타임 구성 변경을 감지하는 activity를 가지려면 Manifest 노드에 android: configChanges 속성을 추가 한 뒤 변경을 하고자 하는 구성 변경을 지정한다. 여러 값을 사용할 때는 |’에 의해 구분된다.

mcc : IMSI 모바일 국가 코드가 변경되었다.

mnc : IMSI 모바일 네트워크 코드가 변경되었다.

locale : 사용자가 다른 언어 설정을 선택했다.

touchscreen : 터치스크린이 변경되었다.

keyboard : 키보드 종류가 바뀌었다.

keyboardHidden : 키보드가 보여졌거나 숨겨졌다.

navigation : 네비게이션 타입이 변경 되었다.

origentation : 화면이 세로 방향이나 가로 방향으로 회전됐다.

fontScale : 사용자가 선호하는 글꼴 크기를 변경했다.

 

/// Configuraion 객체를 사용해 새로운 구성 값을 결정하도록

/// OnConfigurationChnaged 메서드를  한다.

@Override

public void onConfigurationChanged(Configuration _newConfig) {

      super.onConfigurationChanged(_newConfig);

     // resource 값에 기반을 두고 있는 모든 GUI update 한다.

 

     // ....

     if (_newConfig.orientation == Configuration.OPRIENTATION_LANDSCAPE)

{

        // 방향이 landscape 변경되면 해당 방향으로 반응을 한다.

}

 

    if (_newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO)

    {

        // 변경된 키보드의 유무에 반응을 한다.

    }

}

시스템이 재시작 되지 않을 경우 다음과 같이한다.

android:excludeFromRecents  true이면 사용자가 볼 수 있는 최근 런치된 액티비티 리스트에서 제외되고 false이면 리스트에 포함된다. 디폴트 값은 false이다.

android:exported  다른 애플리케이션의 컴포넌트에서 이 액티비티를 런치 할 수 있는지를 설정한다. false”라면 이 액티비티는 같은 애플리케이션 혹은 같은 유저 ID를 가진 애플리케이션 컴포넌트만 런치 할 수 있다. 디폴트는 액티비티가 인텐트 필터를 포함하는지에 달려있다. 필터가 없다면 디폴트 값이 false이고 필터가 있다면 true이다.

MAIN/LAUNCHER 액티비티에는 절대로 false값을 주면 안 된다. false값을 주게 되면 SecurityException이 발생하고 exported 속성을 true로 설정해 달라는 메시지가 출된다.

            android:finishOnTaskLaunch  사용자가 태스크를 런치 할 때 마다 액티비티의 기존 인스턴스가 종료 되어야 하는지의 여부를 설정한다. 종료되어야 한다면 true이고 종료되지 않아야 한다면 false이다. 디폴트 값은 false이다. 만약 이 애트리뷰트와 allowTaskReparenting이 모두 true라면 액티비티 친화력은 무시되어 액티비티는 부모를 바꾸지 않고 파괴된다.

android:launchMode  액티비티가 어떻게 런치되어야 하는지에 대한 명령이다. 4가지 런치모드(standard singleTop” “singleTask singleInstance )가 있고 디폴트는 standard이다.

모드는 두개의 main Group으로 나뉜다(standard, singleTop / singleTask, singleInstance). standard, singleTop모드를 가지는 액티비티는 여러 번 인스턴스화 될 수 있으나(Intent Object가 FLAG_ACTIVITY_NEW_TASK flag를 가지고 있지 않을 경우에 해당) singleInstance 액티비티는 하나의 Task만 시작 할 수 있다.

standard vs singleTop : standard 액티비티에 대한 새로운 Intent가 발생하면 언제나 해당 Class의 Instance가 만들어 지지만 singleTop 액티비티의 새로운 Instance는 생성 될 수도 있다. 즉, Target Task에 이미 해당 액티비티의 인스턴스가 존재하면 새로 만들어지지 않고 기존 인스턴스가 새로운 Intent를 받게 된다.

singleTask vs singleInstance : singleTask 액티비티는 다른 액티비티들이 해당 Task의 일부가 되는 것을 허락하여 singleTask 액티비티는 액티비티 스택의 root에 존재하게 되고 다른 액티비티들은 동일한 Task에서 시작 될 수 있다. 이와 달리 singleInstance 액티비티는 어떤 다른 액티비티들도 해당 Task의 일부가 될 수 없다. 이로 인해 해당 Task에는 유일한 Activity만 존재하고 또 다른 Activity를 실행하려고 하면 새로운 Task로 할당이 된다.

android:multiprocess  이 플래그가 true이면 액티비티 인스턴스가 다양한 프로세스에서 실행 될 수 있다. 디폴트 값은 false이고 true값은 지양한다.

android:noHistory  true라면 사용자가 액티비티를 떠나 화면에 보이지 않았을 때 스택에서 제거되고 종료(finish()메소드가 호출됨)된다. 기본값은 false이다.

android:permission  액티비티를 런치하기 위해 혹은 인텐트에 응답하기 위해 얻어야 하는 퍼미션 이름이다. 만약 startActivity() 또는 startActivityForResult()의 호출자가 퍼미션을 부여받지 않으면 인텐트는 해당 액티비티에 전달 되지 않는다.

애트리뷰트가 설정되지 않으면 <application>엘리먼트의 퍼미션이 적용되고 <application>엘리먼트 퍼미션이 없다면 이 액티비티는 퍼미션에 의해 보호되지 않는다.

android:process  액티비티가 실행되어야 하는 프로세스의 이름이다. 디폴트 프로세스 이름은 어플리케이션 패키지 이름이다.

android:screenOrientation  액티비티의 방향을 설정한다.

unspecified : 시스템에서 디바이스에 따라 방향을 결정

landscape : 가로방향

portrait : 세로방향

behind : 이전 액티비티의 스택에 따라 결정

user : 사용자 설정

sensor : 가속 센서의 방향에 따라 결정

nosensor : 가속 센서를 사용하지 않음, unspecified와 비슷

android:stateNotNeeded  액티비티가 임시로 종료되기 전에 리소스를 저장하기 위해 onSaveInstanceState() 메쏘드가 호출된다.  메쏘드는 액티비티가 재시작될 , onCreate() 전달되는 Bundle 액티비티의 현재 상태를 저장한다. 만약  애트리뷰트가 true”로 설정되 onSaveInstanceState() 호출되지  onCreate() bundle 대신에 null 전달받는다. 디폴트 값은 false이다.

android:taskAffinity  이곳에 다른 task name을 설정해 주면 이 액티비티는 해당 task에 실행된다. 하나의 어플리케이션에서 실행되는 아이콘을 여러 개 만드는데 사용된다. 기본적으로 액티비티는 애플리케이션의 친화력을 상속한다. 애플리케이션의 디폴트 친화력 이름은 <manifest>엘리먼트의 패키지 이름이다.

android:theme  액티비티의 테마를 정의하는 스타일 리소스에 대한 레퍼런스이다. 기본적으로 <application>엘리먼트의 테마를 사용하고 테마가 없으면 시스템 테마가 사용된다.

android:windowSoftInputMode  소프트 키보드 상태 : 액티비티가 사용자 관심의 포커스를 받을 때 소프트 키보드가 보여지는지 여부를 설정한다.

액티비티 메인 윈도우에 대한 조정 : 소프트 키보드를 위한 공간을 만들기 위해 액티비티 메인 윈도우를 작게 줄일 지의 여부 또는 메인 윈도우 일부가 소프트 키보드에 의해 가려질 때 현재 포커스를 보이도록 하기 위해 메인 윈도우의 컨텐트가 상하로 움직일 지의 여부를 설정한다.

stateUnspecified : 소프트 키보드 상태에 대해 시스템이 적절한상태를 선택하거나 테마 설정값을 따른다. 소프트 키보드의 디폴트 설정 값.

stateUnchanged : 소프트 키보드는 마지막 상태로 유지

stateHidden : 사용자 액티비티를 선택할 때 소프트 키보드는 숨겨짐

stateAlwaysHidden : 액티비티의 메인 위도우가 입력 포커스를 가질 때 소프트 키보드는 항상 숨겨짐

stateVisible : 사용자가 액티비티 메인 위도우 앞으로 갈 때 소프트 키보드 보여짐

stateAlwaysVisible : 사용자가 액티비티를 선택할 때 소프트 키보드 보여짐

adjustUnspecified : 스크롤 할 수 잇는 레이아웃 뷰들을 가지고 있다면 윈도우 크기 재조정. 메인 윈도우의 디폴트 값

adjustResize : 스크린에 소프트 키보드 공간을 만들기 위해 메인 윈도우 크기가 항상 재조정 됨

adjustPan : 소프트 키보드 공간을 만들기 위해 메인 윈도우 크기가 재조정 되지 않음

 

<intent-filter>

수행되어야 할 Action을 서술해 놓은 정보의 묶음이다. 이 정보에는 수행되었을 때의 데이터, Action을 수행하기 위한 구성 요소의 Category, 그리고 또 다른 적절한 지시 등이 포함된다.

Android System은 Component를 구동하기 전에 Component가 다루려 하는 의도를 파악해야 하기 때문에 Intent Filters은 <intent-filter> 요소로 Manifest에 규정되어 있어야 한다. 하나의 Component는 여러 개의 Filters을 가질 수 있고 각각은 서로 다른 Capabilities를 나타내게 된다.

<intent-filter android:icon="drawable resource"

android:label="string resource"

android:priority="integer" >

. . .

</intent-filter>

Target Component를 명시적으로 명명한 Intent는 해당 Component를 활성화 시키게 되는데 이 때는 filter가 사용되지 않는다. 그러나 명시적으로 Target을 정하지 않게 되면 Component's Filters 중 하나를 통해 전달하게 된다.

android:priority  부모 컴포넌트가 필터에 따른 인텐트 처리의 우선순위이다. 액티비티와 브로드캐스드의 경우에 해당한다.

필터와 일치하는 인텐트에 대해 응답 방법에 대한 정보를 제공하고 인텐트에 대한 잠재적 타겟으로 높은 우선순위인 액티비티만을 고려한다.

높은 우선순위의 값을 가지는 브로트캐스트 리시버가 먼저 호출된다.

 

<action>

<action android:name="string" />

<intent-filter>엘리먼트는 반드시 하나이상의 <action>엘리먼트를 포함해야 한다.

android:name  액선의 이름으로써 ACTION_문자열 상수이다. 예를들어 ACTION_MAIN에 대해서는android.intent.action.MAIN, ACTION_WEB_SEARCH에 대해서는 anroid.intent.action.WEB_SEARCH를 사용한다.

안드로이드 패키지가 아닌 직접 정의한 액션에 대해서는 접두어로 패키지 이름을 사용하는 것이 좋다. 예를들어 TRANSMOGRIFY액션은 com.example.project.TRANSMOGRIFY 처럼 사용한다.

<category>

<category android:name="string" />

인텐트가 카테고리 테스트를 통과하기 위해서는 인텐트 오브젝트 안의 모든 카테고리가 필터에 있는 카테고리와 일치해야 한다.

android:name  카테고리의 이름으로써 CATEGORY_name 상수이다. 예를들어 CATEGORY_LAUNCHER에 대한 문자열 값은 android.intent.category.LAUNCHER이다.

<data>

URI와 데이터 타입(MIME 미디어 타입) 지정 할 수 있다. schema, host, port, path와 같은 URI 애트리뷰트들에 의해 지정된다.

scheme://host:port/path 또는 pathPrefix 또는 pathPattern

예를들어 content://com.example.project:200/folder/subfolder/etc이다.

<data android:scheme=”something” android:host=”project.example.com” />

<data android:host="string"

android:mimeType="string"

android:path="string"

android:pathPattern="string"

android:pathPrefix="string"

android:port="string"

android:scheme="string" />

<data android:scheme=”something” /><data android:host=”project.example.com” /> 동일하다.

android:host  URI authority의 host영역이다. scheme가 없으면 이 애트리뷰트는 의미가 없다. 호스트 이름은 항상 소문자로 지정해야 한다.

android:mimType  image/jpeg 또는 audio/mpeg4-generic과 같은 MIME 미디어 타입이다. 하위타입에 대해 와일드카드(*)를 사용할수 있으면 항상 소문자를 사용해서 지정해야 한다.

android:path

android:pathPrefix

android:pathPattern  URI authority의 path영역이다. path 애트리뷰트는 인텐트 오브젝트 내의 전체 path와 일치하는 path를 지정한다. pathPrefix 애트리뷰트는 인텐트 오브젝트 내 path의 첫 머리만 일치하는 부분적인 path를 지정한다. pathPattern 애트리뷰트는 인텐트 오브젝트 내의 전체 path와 일치하는 path를 지정하지만 다음과 같은 와일드카드를 포함할 수 있다. 첫째로 별표(*)는 바로 앞에 나오는 문자가 0번 이상 발생하는 것을 나타내고 둘째로는 마침표 뒤에 별표가 나오는 것(.*)은 어떤 문자든 0번 이상 발생하는 것을 나타낸다.

XML에서 \은 이스케이프 문자로써 사용된다.

scheme와 host 애트리뷰트가 필터에 없으면 이 애트리뷰트는 의미가 없다.

android:port - URI authority의 port영역이다. scheme와 host 애트리뷰트가 지정될 때에만 의미를 같는다.

android:scheme  URI authority의 scheme영역이다. Scheme이 없다면 나머지 애트리뷰트는 의미가 없다. 스키마는 항상 소문자를 사용해야 한다.

 

<meta-data>

데이터에 대한 정의나 설명이다. 컴포넌트 엘리먼트는 <meta-data> 서브엘리먼트를 포함할 수 있다. <meta-data>의 모든 값은 하나의 Bundle로 모아지고 PackageItemInfo.metaData 필드로써 컴포넌트에서 사용할 수 있다.

<meta-data android:name="string"

android:resource="resource specification"

android:value="string" />

android:name  아이템에 대한 고유한 이름이다. 예를들어 com.example.project.activity.fred처럼 Java 스타일 naming 규약을 사용해야 한다.

android:resource  리소스에 대한 레퍼런스 이다. ID는 Bundle.getInt() 메쏘드에 의해 meta-data Bundle로부터 얻을수 있다.

android:value  아이템에 할당된 값이다. 아래는 값으로 할당 할수 있는 데이터 타입과 값을 얻기 위해 사용하는 메쏘드들이다.

타입

Bundle 메쏘드

유니코드 문자를 위한 \\n  \\uxxxxx 같은 스케이프(escape) 캐릭터에 더블 백슬래시(\\) 사용하는 문자열 

getString()

100같은 정수(integer) 

getInt()

(true) 또는 거짓(false)  하나인 boolean 

getBoolean()

#rgb,#argb,#rrggbb 또는 #aarrggbb형식의 컬러 

getString()

1.23 같은 부동소수점 

getFloat()

 

<activity-alias>

<activity-alias android:enabled=["true" | "false"]

android:exported=["true" | "false"]

android:icon="drawable resource"

android:label="string resource"

android:name="string"

android:permission="string"

android:targetActivity="string" >

. . .

</activity-alias>

<activity> 타겟으로 지정해 그 타겟과 다른 속성으로 <activity>를 호출한다. targetActivity는 같은 <application>안에 있어야 하고 <activity-alias>보다 먼저 선언 되어 있어야 한다. targetActivity는 Activity-alias의 부모 엘리먼트이고 activity-alias는 targetActivity의 애트리뷰트를 따르지만 activity-alias안에 같은 애트리뷰트가 선언되면 activity-alias 애트리뷰트 값을 따른다.

android:exported  다른 애플리케이션의 컴포넌트들이 이 앨리어스를 통해 타겟 액티비티를 런치할 수 있는지를 설정한다. 런치할 수 있다면 true이다. 인텐트 필터가 없으면 디폴트 값은 false이고 인텐트 필터가 있다면 디폴트 값은 true이다.

android:name  앨리어스의 이름을 지정한다. 이름은 전체 클래스 이름과 비슷해야 하고 실제 클래스 이름을 참조하지 않는다.

android:permission  이것이 설정된다면 targetActivity 퍼미션을 대체한다. 설정이 되지 않는다면 앨리어스를 통해 타겟을 활성화 하기 위한 퍼미션은 필요하지 않다.

android:targetActivity  앨리어스를 통해 활성화 될 수 있는 액티비티의 이름을 지정한다.

 

<service>

<service android:enabled=["true" | "false"]

android:exported=["true" | "false"]

android:icon="drawable resource"

android:label="string resource"

android:name="string"

android:permission="string"

android:process="string" >

. . .

</service>

각 서비스마다 <service>태그가 필요하다. 서비스는 백그라운드 오퍼레이션이나 다른 애플리케이션이 호출 할 수 있는 커뮤니케이션 API를 구현하기 위해 사용된다.

android:icon  서비스 아이콘은 이곳에서 설정하던 <application>엘리먼트에서 설정하던 모든 서비스의 인텐트 필터에 대한 디폴트 아이콘이다.

android:label  서비스 아이콘은 이곳에서 설정하던 <application>엘리먼트에서 설정하던 모든 서비스의 인텐트 필터에 대한 디폴트 라벨이다.

android:name  서비스를 구현하는 Service 서브클래스의 이름이다. com.example.project.RoomService 처럼 전체 클래스 이름이어야 한다. 하지만 .RoomService와 같이 단축형 이름이라면 <manifest>엘리먼트에 지정된 패키지 이름 끝에 붙여진다.

android:permission  서비스를 런치하거나 바인드를 하 위해 가져야 하는 퍼미션 이름이다. 만약 startsService(), bindService(), stopService()의 호출자가 이 퍼미션을 부여받지 않는다면 이 메쏘느는 작동하지 않으며 인턴트 오브젝트는 서비스에 전달되지 않는다. 이 퍼미션을 설정하지 않으면 <application>퍼미션이 적용되고 <application>퍼미션이 없다면 퍼미션이 적용되지 않는다.

 

<receiver>

<receiver android:enabled=["true" | "false"]

android:exported=["true" | "false"]

android:icon="drawable resource"

android:label="string resource"

android:name="string"

android:permission="string"

android:process="string" >

. . .

</receiver>

어플리케이션이 브로드캐스트 메시지를 수신할수 있도록 한다. 브로드캐스트 리시버는 애플리케이션의 다른 컴포넌트들이 실행되지 않아도 다른 애플리케이션 또는 시스템에 의해 브로드캐스트 되는 인텐트를 받기 위해 애플리케이션을 활성화 한다.

시스템에게 브로드캐스트 리시버를 알기기 위한 방법으로는 이 엘리먼트를 가지고 매니페스트 파일 안에 선언하는 것과 코드 안에서 동적으로 리시버를 만들어서 Context.registerReceiver() 메쏘드를 사용해서 등록한다.

android:exported  브로드캐스트 리시버가 다른 애플리케이션 소스로부터 메시지를 받을수 있는지를 설정한다. 받을수 있으면 true이고 아니면 false이다. 인텐트 필터가 없으면 디폴트 값은 false이고 인텐트 필터가 있다면 디폴트 값은 true이다.

 

<provider>

<provider android:authorities="list"

android:enabled=["true" | "false"]

android:exported=["true" | "false"]

android:grantUriPermissions=["true" | "false"]

android:icon="drawable resource"

android:initOrder="integer"

android:label="string resource"

android:multiprocess=["true" | "false"]

android:name="string"

android:permission="string"

android:process="string"

android:readPermission="string"

android:syncable=["true" | "false"]

android:writePermission="string" >

. . .

</provider>

애플리케이션의 일부가 되는 모든 컨텐트 프로바이더를 선언해야 한다. 컨텐트 프로바이더 서브클래스에 대한 이름은 URI authority이다.

android:authorities  데이터를 구분하는 URI authority 목록이다. Authority가 여러 개이면 세미콜론(;)으로 이름을 구분한다. 최소한 하나의 authority가 지정되어야 한다.

android:grantUriPermissions  일시적으로 radPermission, writePermission, 데이터 접근 할수 있게 하려면 ture로 설정하거나 <grant-uri-permission>서브엘리먼트를 정의함으로써 이 기능을 활성화 한다. 퍼미션을 설정하지 않으려면  false로 한다.

android:initOrder  컨텐트 프로바이더가 인스턴스화되어야 하는 순서를 설정한다. 높은 숫자들이 먼저 초기화 된다.

android:permission  클라이언트가 컨텐트 프로바이더의 데이터를 읽거나 쓰기 위해 가져야 하는 퍼미션의 이름이다. 이 애트리뷰트는 읽기와 쓰기 모두에게 하나의 퍼미션을 설정한다. 하지만 readPermission과 writePermission 애트리뷰트가 이것보다 우선순위이다.

android:readPermission  클라이언트가 컨텐트 프로바이더에 쿼리하기 위해 가져야 하는 퍼미션이다.

android:syncable  컨텐트 프로바이더의 제어하에 있는 데이터가 서버 상의 데이터와 동기화되어져야 한다면 true 아니면 false이다.

android:writePermission  클라이언트가 컨텐트 프로바이더에 의해 제어되는 데이터를 변경하기 위해 가져야 하는 퍼미션이다.

 

<uses-library>

<uses-permission android:name="string" />

어플리케이션에 링크 되어야 하는 외부 라이브러리를 지정한다.

android:name  라이브러리 이름




디폴트 값

Element

Atrribute

디폴트 값

<instrumentation>

android:functionalTest

false

 

android:handleProfiling

false

<uses-sdk>

android:minSdkVersion

1

 

android:maxSdkVersion

없음

<supports-screens>

android:smallScreens

true(API Level 7 기준)

 

android:normalScreens

true(API Level 7 기준)

 

android:largeScreens

true(API Level 7 기준)

 

android:anyDensity

true(API Level 7 기준)

<application>

android:allowClearUserData

 

 

android:allowTaskReparenting

false

 

android:debuggable

false

 

android:enable

true

 

android:hasCode

true

 

android:persistent

false

 

android:process

<manifest>엘리먼트의 package 이름

 

android:taskAffinity

<manifest>엘리먼트의 package 이름

<activity>

android:alwaysRetainTaskState

false

 

android:clearTskOnLaunch

false

 

android:enabled

true

 

android:excludeFromRecents

false

 

android:exported

Intent 필터가 없다면 false

Intent 필터가 있다면 true

 

android:finishOnTaskLaunch

false

 

android:launchMode

standard

 

android:multiprocess

false

 

android:noHistory

false

 

android:permission

<application>엘리먼트의 퍼미션

<application>퍼미션이 없다면 퍼미션에 의해 보호 되지 않음

 

android:process

애플리케이션의 패키지 이름

 

android:stateNotNeeded

false

 

android:taskAffinity

어플리케이션의 친화력을 상속.

어플리케이션의 디폴트 친화력 이름은 <manifest>엘리먼트의 패키지 이름이다.

 

android:theme

<application>테마

<application>테마가 없다면 시스템 테마

 

android:windowSoftInputMode

소프트 키보드 : stateUnspecified

메인 윈도우 : adjustUnspecified

<intent-filter>

android:label

부모 컴포넌트에 설정된 라벨

부모가 라벨을 설정하지 않으면 <application>라벨

<activity-alias>

android:enabled

true

 

android:exported

인텐트 필터가 없으면 false

인텐트 필터가 있으면 true

 

android:permission

targetActivity의 퍼미션

targetActivity의 퍼미션이 없다면 퍼미션에 의해 보호되지 않음

<service>

android:enabled

true

 

android:exported

인텐트 필터가 없으면 false

인텐트 필터가 있으면 true

 

android:permission

<application>엘리먼트의 퍼미션

<application>퍼미션이 없다면 퍼미션에 의해 보호되지 않음

<receiver>

android:enabled

true

 

android:exported

인텐트 필터가 없으면 false

인텐트 필터가 있으면 true

 

android:permission

<application>엘리먼트의 퍼미션

<application>퍼미션이 없다면 퍼미션에 의해 보호되지 않음

<provider>

android:enabled

true

 

android:exported

인텐트 필터가 없으면 false

인텐트 필터가 있으면 true

 

android:multiprocess

false

 

android:process

<application>엘리먼트의 프로세스

 

출처 : http://chiyo85.tistory.com/32


Constants
String ACCESS_CHECKIN_PROPERTIES Allows read/write access to the "properties" table in the checkin database, to change values that get uploaded.
String ACCESS_COARSE_LOCATION Allows an application to access coarse (e.g., Cell-ID, WiFi) location
String ACCESS_FINE_LOCATION Allows an application to access fine (e.g., GPS) location
String ACCESS_LOCATION_EXTRA_COMMANDS Allows an application to access extra location provider commands
String ACCESS_MOCK_LOCATION Allows an application to create mock location providers for testing
String ACCESS_NETWORK_STATE Allows applications to access information about networks
String ACCESS_SURFACE_FLINGER Allows an application to use SurfaceFlinger's low level features
String ACCESS_WIFI_STATE Allows applications to access information about Wi-Fi networks
String ACCOUNT_MANAGER Allows applications to call into AccountAuthenticators.
String AUTHENTICATE_ACCOUNTS Allows an application to act as an AccountAuthenticator for the AccountManager
String BATTERY_STATS Allows an application to collect battery statistics
String BIND_APPWIDGET Allows an application to tell the AppWidget service which application can access AppWidget's data.
String BIND_DEVICE_ADMIN Must be required by device administration receiver, to ensure that only the system can interact with it.
String BIND_INPUT_METHOD Must be required by an InputMethodService, to ensure that only the system can bind to it.
String BIND_WALLPAPER Must be required by a WallpaperService, to ensure that only the system can bind to it.
String BLUETOOTH Allows applications to connect to paired bluetooth devices
String BLUETOOTH_ADMIN Allows applications to discover and pair bluetooth devices
String BRICK Required to be able to disable the device (very dangerous!).
String BROADCAST_PACKAGE_REMOVED Allows an application to broadcast a notification that an application package has been removed.
String BROADCAST_SMS Allows an application to broadcast an SMS receipt notification
String BROADCAST_STICKY Allows an application to broadcast sticky intents.
String BROADCAST_WAP_PUSH Allows an application to broadcast a WAP PUSH receipt notification
String CALL_PHONE Allows an application to initiate a phone call without going through the Dialer user interface for the user to confirm the call being placed.
String CALL_PRIVILEGED Allows an application to call any phone number, including emergency numbers, without going through the Dialer user interface for the user to confirm the call being placed.
String CAMERA Required to be able to access the camera device.
String CHANGE_COMPONENT_ENABLED_STATE Allows an application to change whether an application component (other than its own) is enabled or not.
String CHANGE_CONFIGURATION Allows an application to modify the current configuration, such as locale.
String CHANGE_NETWORK_STATE Allows applications to change network connectivity state
String CHANGE_WIFI_MULTICAST_STATE Allows applications to enter Wi-Fi Multicast mode
String CHANGE_WIFI_STATE Allows applications to change Wi-Fi connectivity state
String CLEAR_APP_CACHE Allows an application to clear the caches of all installed applications on the device.
String CLEAR_APP_USER_DATA Allows an application to clear user data
String CONTROL_LOCATION_UPDATES Allows enabling/disabling location update notifications from the radio.
String DELETE_CACHE_FILES Allows an application to delete cache files.
String DELETE_PACKAGES Allows an application to delete packages.
String DEVICE_POWER Allows low-level access to power management
String DIAGNOSTIC Allows applications to RW to diagnostic resources.
String DISABLE_KEYGUARD Allows applications to disable the keyguard
String DUMP Allows an application to retrieve state dump information from system services.
String EXPAND_STATUS_BAR Allows an application to expand or collapse the status bar.
String FACTORY_TEST Run as a manufacturer test application, running as the root user.
String FLASHLIGHT Allows access to the flashlight
String FORCE_BACK Allows an application to force a BACK operation on whatever is the top activity.
String GET_ACCOUNTS Allows access to the list of accounts in the Accounts Service
String GET_PACKAGE_SIZE Allows an application to find out the space used by any package.
String GET_TASKS Allows an application to get information about the currently or recently running tasks: a thumbnail representation of the tasks, what activities are running in it, etc.
String GLOBAL_SEARCH This permission can be used on content providers to allow the global search system to access their data.
String HARDWARE_TEST Allows access to hardware peripherals.
String INJECT_EVENTS Allows an application to inject user events (keys, touch, trackball) into the event stream and deliver them to ANY window.
String INSTALL_LOCATION_PROVIDER Allows an application to install a location provider into the Location Manager
String INSTALL_PACKAGES Allows an application to install packages.
String INTERNAL_SYSTEM_WINDOW Allows an application to open windows that are for use by parts of the system user interface.
String INTERNET Allows applications to open network sockets.
String KILL_BACKGROUND_PROCESSES Allows an application to call killBackgroundProcesses(String).
String MANAGE_ACCOUNTS Allows an application to manage the list of accounts in the AccountManager
String MANAGE_APP_TOKENS Allows an application to manage (create, destroy, Z-order) application tokens in the window manager.
String MASTER_CLEAR
String MODIFY_AUDIO_SETTINGS Allows an application to modify global audio settings
String MODIFY_PHONE_STATE Allows modification of the telephony state - power on, mmi, etc.
String MOUNT_FORMAT_FILESYSTEMS Allows formatting file systems for removable storage.
String MOUNT_UNMOUNT_FILESYSTEMS Allows mounting and unmounting file systems for removable storage.
String NFC Allows applications to directly communicate over NFC
String PERSISTENT_ACTIVITY This constant is deprecated. This functionality will be removed in the future; please do not use. Allow an application to make its activities persistent.
String PROCESS_OUTGOING_CALLS Allows an application to monitor, modify, or abort outgoing calls.
String READ_CALENDAR Allows an application to read the user's calendar data.
String READ_CONTACTS Allows an application to read the user's contacts data.
String READ_FRAME_BUFFER Allows an application to take screen shots and more generally get access to the frame buffer data
String READ_HISTORY_BOOKMARKS Allows an application to read (but not write) the user's browsing history and bookmarks.
String READ_INPUT_STATE Allows an application to retrieve the current state of keys and switches.
String READ_LOGS Allows an application to read the low-level system log files.
String READ_PHONE_STATE Allows read only access to phone state.
String READ_SMS Allows an application to read SMS messages.
String READ_SYNC_SETTINGS Allows applications to read the sync settings
String READ_SYNC_STATS Allows applications to read the sync stats
String REBOOT Required to be able to reboot the device.
String RECEIVE_BOOT_COMPLETED Allows an application to receive the ACTION_BOOT_COMPLETED that is broadcast after the system finishes booting.
String RECEIVE_MMS Allows an application to monitor incoming MMS messages, to record or perform processing on them.
String RECEIVE_SMS Allows an application to monitor incoming SMS messages, to record or perform processing on them.
String RECEIVE_WAP_PUSH Allows an application to monitor incoming WAP push messages.
String RECORD_AUDIO Allows an application to record audio
String REORDER_TASKS Allows an application to change the Z-order of tasks
String RESTART_PACKAGES This constant is deprecated. The restartPackage(String) API is no longer supported.
String SEND_SMS Allows an application to send SMS messages.
String SET_ACTIVITY_WATCHER Allows an application to watch and control how activities are started globally in the system.
String SET_ALARM Allows an application to broadcast an Intent to set an alarm for the user.
String SET_ALWAYS_FINISH Allows an application to control whether activities are immediately finished when put in the background.
String SET_ANIMATION_SCALE Modify the global animation scaling factor.
String SET_DEBUG_APP Configure an application for debugging.
String SET_ORIENTATION Allows low-level access to setting the orientation (actually rotation) of the screen.
String SET_PREFERRED_APPLICATIONS This constant is deprecated. No longer useful, see addPackageToPreferred(String) for details.
String SET_PROCESS_LIMIT Allows an application to set the maximum number of (not needed) application processes that can be running.
String SET_TIME Allows applications to set the system time
String SET_TIME_ZONE Allows applications to set the system time zone
String SET_WALLPAPER Allows applications to set the wallpaper
String SET_WALLPAPER_HINTS Allows applications to set the wallpaper hints
String SIGNAL_PERSISTENT_PROCESSES Allow an application to request that a signal be sent to all persistent processes
String STATUS_BAR Allows an application to open, close, or disable the status bar and its icons.
String SUBSCRIBED_FEEDS_READ Allows an application to allow access the subscribed feeds ContentProvider.
String SUBSCRIBED_FEEDS_WRITE
String SYSTEM_ALERT_WINDOW Allows an application to open windows using the type TYPE_SYSTEM_ALERT, shown on top of all other applications.
String UPDATE_DEVICE_STATS Allows an application to update device statistics.
String USE_CREDENTIALS Allows an application to request authtokens from the AccountManager
String USE_SIP Allows an application to use SIP service
String VIBRATE Allows access to the vibrator
String WAKE_LOCK Allows using PowerManager WakeLocks to keep processor from sleeping or screen from dimming
String WRITE_APN_SETTINGS Allows applications to write the apn settings
String WRITE_CALENDAR Allows an application to write (but not read) the user's calendar data.
String WRITE_CONTACTS Allows an application to write (but not read) the user's contacts data.
String WRITE_EXTERNAL_STORAGE Allows an application to write to external storage
String WRITE_GSERVICES Allows an application to modify the Google service map.
String WRITE_HISTORY_BOOKMARKS Allows an application to write (but not read) the user's browsing history and bookmarks.
String WRITE_SECURE_SETTINGS Allows an application to read or write the secure system settings.
String WRITE_SETTINGS Allows an application to read or write the system settings.
String WRITE_SMS Allows an application to write SMS messages.
String WRITE_SYNC_SETTINGS Allows applications to write the sync settings

'안드로이드' 카테고리의 다른 글

Device를 Rotate시 꼭 알아두어야 할사항.  (0) 2011.01.27
AndroidManifest  (0) 2011.01.26
ViewSwitcher 예제 코드  (0) 2011.01.26
안드로이드 날짜 포맷  (0) 2011.01.26
List View 구현시 유의할 점.  (0) 2011.01.26

+ Recent posts