------

[ AD ] Port Monitor ( Try to use a Best WebSite Monitoring Tool )

------

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
	<translate android:fromXDelta="100%p" android:toXDelta="0%p" android:duration="300"/>
	<alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" />
</set>



	
	



<alpha/>
android:fromAlpha : 시작 투명도
android:toAlpha : 종료 투명도
0.0 투명
1.0 불투명
android:duration 1/1000초 milliseconds


startAnimation( AnimationUtils.loadAnimation(mContext, R.anim.left_out) );
startAnimation( AnimationUtils.loadAnimation(mContext, R.anim.left_out) );


   <!-- ListActivity의 기본 ListView로 지정 -->
   <ListView
    android:layoutAnimation="@anim/layout_bottom_to_top_slide"
       android:id="@id/android:list"             
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:divider="#00000000"
    android:background="#88FFFFFF"
    />

/res/anim/layout_bottom_top_slide.xml
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
     android:delay="80%"
     android:animation="@anim/fade" />


/res/anim/fade.xml
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
       android:interpolator="@android:anim/accelerate_interpolator"
       android:fromAlpha="0.0" android:toAlpha="1.0"
       android:duration="1000" />

 
 
작성 : jameroid.tistory.com

// in main Activity

somethingView.startAnimation(AnimationUtils.loadAnimation(game, R.anim.shake));


res/anim/shake.xml 추가

public class KeyEvent implements Parcelable {
    // key codes
    public static final int KEYCODE_UNKNOWN         = 0;
    public static final int KEYCODE_SOFT_LEFT       = 1;
    public static final int KEYCODE_SOFT_RIGHT      = 2;
    public static final int KEYCODE_HOME            = 3;
    public static final int KEYCODE_BACK            = 4;
    public static final int KEYCODE_CALL            = 5;
    public static final int KEYCODE_ENDCALL         = 6;
    public static final int KEYCODE_0               = 7;
    public static final int KEYCODE_1               = 8;
    public static final int KEYCODE_2               = 9;
    public static final int KEYCODE_3               = 10;
    public static final int KEYCODE_4               = 11;
    public static final int KEYCODE_5               = 12;
    public static final int KEYCODE_6               = 13;
    public static final int KEYCODE_7               = 14;
    public static final int KEYCODE_8               = 15;
    public static final int KEYCODE_9               = 16;
    public static final int KEYCODE_STAR            = 17;
    public static final int KEYCODE_POUND           = 18;
    public static final int KEYCODE_DPAD_UP         = 19;
    public static final int KEYCODE_DPAD_DOWN       = 20;
    public static final int KEYCODE_DPAD_LEFT       = 21;
    public static final int KEYCODE_DPAD_RIGHT      = 22;
    public static final int KEYCODE_DPAD_CENTER     = 23;
    public static final int KEYCODE_VOLUME_UP       = 24;
    public static final int KEYCODE_VOLUME_DOWN     = 25;
    public static final int KEYCODE_POWER           = 26;
    public static final int KEYCODE_CAMERA          = 27;
    public static final int KEYCODE_CLEAR           = 28;
    public static final int KEYCODE_A               = 29;
    public static final int KEYCODE_B               = 30;
    public static final int KEYCODE_C               = 31;
    public static final int KEYCODE_D               = 32;
    public static final int KEYCODE_E               = 33;
    public static final int KEYCODE_F               = 34;
    public static final int KEYCODE_G               = 35;
    public static final int KEYCODE_H               = 36;
    public static final int KEYCODE_I               = 37;
    public static final int KEYCODE_J               = 38;
    public static final int KEYCODE_K               = 39;
    public static final int KEYCODE_L               = 40;
    public static final int KEYCODE_M               = 41;
    public static final int KEYCODE_N               = 42;
    public static final int KEYCODE_O               = 43;
    public static final int KEYCODE_P               = 44;
    public static final int KEYCODE_Q               = 45;
    public static final int KEYCODE_R               = 46;
    public static final int KEYCODE_S               = 47;
    public static final int KEYCODE_T               = 48;
    public static final int KEYCODE_U               = 49;
    public static final int KEYCODE_V               = 50;
    public static final int KEYCODE_W               = 51;
    public static final int KEYCODE_X               = 52;
    public static final int KEYCODE_Y               = 53;
    public static final int KEYCODE_Z               = 54;
    public static final int KEYCODE_COMMA           = 55;
    public static final int KEYCODE_PERIOD          = 56;
    public static final int KEYCODE_ALT_LEFT        = 57;
    public static final int KEYCODE_ALT_RIGHT       = 58;
    public static final int KEYCODE_SHIFT_LEFT      = 59;
    public static final int KEYCODE_SHIFT_RIGHT     = 60;
    public static final int KEYCODE_TAB             = 61;
    public static final int KEYCODE_SPACE           = 62;
    public static final int KEYCODE_SYM             = 63;
    public static final int KEYCODE_EXPLORER        = 64;
    public static final int KEYCODE_ENVELOPE        = 65;
    public static final int KEYCODE_ENTER           = 66;
    public static final int KEYCODE_DEL             = 67;
    public static final int KEYCODE_GRAVE           = 68;
    public static final int KEYCODE_MINUS           = 69;
    public static final int KEYCODE_EQUALS          = 70;
    public static final int KEYCODE_LEFT_BRACKET    = 71;
    public static final int KEYCODE_RIGHT_BRACKET   = 72;
    public static final int KEYCODE_BACKSLASH       = 73;
    public static final int KEYCODE_SEMICOLON       = 74;
    public static final int KEYCODE_APOSTROPHE      = 75;
    public static final int KEYCODE_SLASH           = 76;
    public static final int KEYCODE_AT              = 77;
    public static final int KEYCODE_NUM             = 78;
    public static final int KEYCODE_HEADSETHOOK     = 79;
    public static final int KEYCODE_FOCUS           = 80;   // *Camera* focus
    public static final int KEYCODE_PLUS            = 81;
    public static final int KEYCODE_MENU            = 82;
    public static final int KEYCODE_NOTIFICATION    = 83;
    public static final int KEYCODE_SEARCH          = 84;
    public static final int KEYCODE_MEDIA_PLAY_PAUSE= 85;
    public static final int KEYCODE_MEDIA_STOP      = 86;
    public static final int KEYCODE_MEDIA_NEXT      = 87;
    public static final int KEYCODE_MEDIA_PREVIOUS  = 88;
    public static final int KEYCODE_MEDIA_REWIND    = 89;
    public static final int KEYCODE_MEDIA_FAST_FORWARD = 90;
    public static final int KEYCODE_MUTE            = 91;

    // NOTE: If you add a new keycode here you must also add it to:
    //  isSystem()
    //  frameworks/base/include/ui/KeycodeLabels.h
    //  tools/puppet_master/PuppetMaster/nav_keys.py
    //  frameworks/base/core/res/res/values/attrs.xml
    //  commands/monkey/Monkey.java
    //  emulator?
    //
    //  Also Android currently does not reserve code ranges for vendor-
    //  specific key codes.  If you have new key codes to have, you
    //  MUST contribute a patch to the open source project to define
    //  those new codes.  This is intended to maintain a consistent
    //  set of key code definitions across all Android devices.
  
    private static final int LAST_KEYCODE           = KEYCODE_MUTE;
   
    /**
     * @deprecated There are now more than MAX_KEYCODE keycodes.
     * Use {@link #getMaxKeyCode()} instead.
     */
    @Deprecated
    public static final int MAX_KEYCODE             = 84;

    /**
     * {@link #getAction} value: the key has been pressed down.
     */
    public static final int ACTION_DOWN             = 0;
    /**
     * {@link #getAction} value: the key has been released.
     */
    public static final int ACTION_UP               = 1;
    /**
     * {@link #getAction} value: multiple duplicate key events have
     * occurred in a row, or a complex string is being delivered.  If the
     * key code is not {#link {@link #KEYCODE_UNKNOWN} then the
     * {#link {@link #getRepeatCount()} method returns the number of times
     * the given key code should be executed.
     * Otherwise, if the key code {@link #KEYCODE_UNKNOWN}, then
     * this is a sequence of characters as returned by {@link #getCharacters}.
     */
    public static final int ACTION_MULTIPLE         = 2;

    /**
     * <p>This mask is used to check whether one of the ALT meta keys is pressed.</p>
     *
     * @see #isAltPressed()
     * @see #getMetaState()
     * @see #KEYCODE_ALT_LEFT
     * @see #KEYCODE_ALT_RIGHT
     */
    public static final int META_ALT_ON = 0x02;

    /**
     * <p>This mask is used to check whether the left ALT meta key is pressed.</p>
     *
     * @see #isAltPressed()
     * @see #getMetaState()
     * @see #KEYCODE_ALT_LEFT
     */
    public static final int META_ALT_LEFT_ON = 0x10;

    /**
     * <p>This mask is used to check whether the right the ALT meta key is pressed.</p>
     *
     * @see #isAltPressed()
     * @see #getMetaState()
     * @see #KEYCODE_ALT_RIGHT
     */
    public static final int META_ALT_RIGHT_ON = 0x20;

    /**
     * <p>This mask is used to check whether one of the SHIFT meta keys is pressed.</p>
     *
     * @see #isShiftPressed()
     * @see #getMetaState()
     * @see #KEYCODE_SHIFT_LEFT
     * @see #KEYCODE_SHIFT_RIGHT
     */
    public static final int META_SHIFT_ON = 0x1;

    /**
     * <p>This mask is used to check whether the left SHIFT meta key is pressed.</p>
     *
     * @see #isShiftPressed()
     * @see #getMetaState()
     * @see #KEYCODE_SHIFT_LEFT
     */
    public static final int META_SHIFT_LEFT_ON = 0x40;

    /**
     * <p>This mask is used to check whether the right SHIFT meta key is pressed.</p>
     *
     * @see #isShiftPressed()
     * @see #getMetaState()
     * @see #KEYCODE_SHIFT_RIGHT
     */
    public static final int META_SHIFT_RIGHT_ON = 0x80;

    /**
     * <p>This mask is used to check whether the SYM meta key is pressed.</p>
     *
     * @see #isSymPressed()
     * @see #getMetaState()
     */
    public static final int META_SYM_ON = 0x4;

    /**
     * This mask is set if the device woke because of this key event.
     */
    public static final int FLAG_WOKE_HERE = 0x1;
   
    /**
     * This mask is set if the key event was generated by a software keyboard.
     */
    public static final int FLAG_SOFT_KEYBOARD = 0x2;
   
    /**
     * This mask is set if we don't want the key event to cause us to leave
     * touch mode.
     */
    public static final int FLAG_KEEP_TOUCH_MODE = 0x4;
   
    /**
     * This mask is set if an event was known to come from a trusted part
     * of the system.  That is, the event is known to come from the user,
     * and could not have been spoofed by a third party component.
     */
    public static final int FLAG_FROM_SYSTEM = 0x8;
   
    /**
     * This mask is used for compatibility, to identify enter keys that are
     * coming from an IME whose enter key has been auto-labelled "next" or
     * "done".  This allows TextView to dispatch these as normal enter keys
     * for old applications, but still do the appropriate action when
     * receiving them.
     */
    public static final int FLAG_EDITOR_ACTION = 0x10;
   
    /**
     * When associated with up key events, this indicates that the key press
     * has been canceled.  Typically this is used with virtual touch screen
     * keys, where the user can slide from the virtual key area on to the
     * display: in that case, the application will receive a canceled up
     * event and should not perform the action normally associated with the
     * key.  Note that for this to work, the application can not perform an
     * action for a key until it receives an up or the long press timeout has
     * expired.
     */
    public static final int FLAG_CANCELED = 0x20;
   
    /**
     * This key event was generated by a virtual (on-screen) hard key area.
     * Typically this is an area of the touchscreen, outside of the regular
     * display, dedicated to "hardware" buttons.
     */
    public static final int FLAG_VIRTUAL_HARD_KEY = 0x40;
   
    /**
     * This flag is set for the first key repeat that occurs after the
     * long press timeout.
     */
    public static final int FLAG_LONG_PRESS = 0x80;
   
    /**
     * Set when a key event has {@link #FLAG_CANCELED} set because a long
     * press action was executed while it was down.
     */
    public static final int FLAG_CANCELED_LONG_PRESS = 0x100;
   
    /**
     * Set for {@link #ACTION_UP} when this event's key code is still being
     * tracked from its initial down.  That is, somebody requested that tracking
     * started on the key down and a long press has not caused
     * the tracking to be canceled.
     */
    public static final int FLAG_TRACKING = 0x200;
   
    /**
     * Private control to determine when an app is tracking a key sequence.
     * @hide
     */
    public static final int FLAG_START_TRACKING = 0x40000000;
   
    /**
     * Returns the maximum keycode.
     */
    public static int getMaxKeyCode() {
        return LAST_KEYCODE;
    }

    /**
     * Get the character that is produced by putting accent on the character
     * c.
     * For example, getDeadChar('`', 'e') returns &egrave;.
     */
    public static int getDeadChar(int accent, int c) {
        return KeyCharacterMap.getDeadChar(accent, c);
    }
   
    static final boolean DEBUG = false;
    static final String TAG = "KeyEvent";
   
    private int mMetaState;
    private int mAction;
    private int mKeyCode;
    private int mScancode;
    private int mRepeatCount;
    private int mDeviceId;
    private int mFlags;
    private long mDownTime;
    private long mEventTime;
    private String mCharacters;

    public interface Callback {
        /**
         * Called when a key down event has occurred.  If you return true,
         * you can first call {@link KeyEvent#startTracking()
         * KeyEvent.startTracking()} to have the framework track the event
         * through its {@link #onKeyUp(int, KeyEvent)} and also call your
         * {@link #onKeyLongPress(int, KeyEvent)} if it occurs.
         *
         * @param keyCode The value in event.getKeyCode().
         * @param event Description of the key event.
         *
         * @return If you handled the event, return true.  If you want to allow
         *         the event to be handled by the next receiver, return false.
         */
        boolean onKeyDown(int keyCode, KeyEvent event);

        /**
         * Called when a long press has occurred.  If you return true,
         * the final key up will have {@link KeyEvent#FLAG_CANCELED} and
         * {@link KeyEvent#FLAG_CANCELED_LONG_PRESS} set.  Note that in
         * order to receive this callback, someone in the event change
         * <em>must</em> return true from {@link #onKeyDown} <em>and</em>
         * call {@link KeyEvent#startTracking()} on the event.
         *
         * @param keyCode The value in event.getKeyCode().
         * @param event Description of the key event.
         *
         * @return If you handled the event, return true.  If you want to allow
         *         the event to be handled by the next receiver, return false.
         */
        boolean onKeyLongPress(int keyCode, KeyEvent event);

        /**
         * Called when a key up event has occurred.
         *
         * @param keyCode The value in event.getKeyCode().
         * @param event Description of the key event.
         *
         * @return If you handled the event, return true.  If you want to allow
         *         the event to be handled by the next receiver, return false.
         */
        boolean onKeyUp(int keyCode, KeyEvent event);

        /**
         * Called when multiple down/up pairs of the same key have occurred
         * in a row.
         *
         * @param keyCode The value in event.getKeyCode().
         * @param count Number of pairs as returned by event.getRepeatCount().
         * @param event Description of the key event.
         *
         * @return If you handled the event, return true.  If you want to allow
         *         the event to be handled by the next receiver, return false.
         */
        boolean onKeyMultiple(int keyCode, int count, KeyEvent event);
    }

    /**
     * Create a new key event.
     *
     * @param action Action code: either {@link #ACTION_DOWN},
     * {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}.
     * @param code The key code.
     */
    public KeyEvent(int action, int code) {
        mAction = action;
        mKeyCode = code;
        mRepeatCount = 0;
    }

    /**
     * Create a new key event.
     *
     * @param downTime The time (in {@link android.os.SystemClock#uptimeMillis})
     * at which this key code originally went down.
     * @param eventTime The time (in {@link android.os.SystemClock#uptimeMillis})
     * at which this event happened.
     * @param action Action code: either {@link #ACTION_DOWN},
     * {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}.
     * @param code The key code.
     * @param repeat A repeat count for down events (> 0 if this is after the
     * initial down) or event count for multiple events.
     */
    public KeyEvent(long downTime, long eventTime, int action,
                    int code, int repeat) {
        mDownTime = downTime;
        mEventTime = eventTime;
        mAction = action;
        mKeyCode = code;
        mRepeatCount = repeat;
    }

    /**
     * Create a new key event.
     *
     * @param downTime The time (in {@link android.os.SystemClock#uptimeMillis})
     * at which this key code originally went down.
     * @param eventTime The time (in {@link android.os.SystemClock#uptimeMillis})
     * at which this event happened.
     * @param action Action code: either {@link #ACTION_DOWN},
     * {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}.
     * @param code The key code.
     * @param repeat A repeat count for down events (> 0 if this is after the
     * initial down) or event count for multiple events.
     * @param metaState Flags indicating which meta keys are currently pressed.
     */
    public KeyEvent(long downTime, long eventTime, int action,
                    int code, int repeat, int metaState) {
        mDownTime = downTime;
        mEventTime = eventTime;
        mAction = action;
        mKeyCode = code;
        mRepeatCount = repeat;
        mMetaState = metaState;
    }

    /**
     * Create a new key event.
     *
     * @param downTime The time (in {@link android.os.SystemClock#uptimeMillis})
     * at which this key code originally went down.
     * @param eventTime The time (in {@link android.os.SystemClock#uptimeMillis})
     * at which this event happened.
     * @param action Action code: either {@link #ACTION_DOWN},
     * {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}.
     * @param code The key code.
     * @param repeat A repeat count for down events (> 0 if this is after the
     * initial down) or event count for multiple events.
     * @param metaState Flags indicating which meta keys are currently pressed.
     * @param device The device ID that generated the key event.
     * @param scancode Raw device scan code of the event.
     */
    public KeyEvent(long downTime, long eventTime, int action,
                    int code, int repeat, int metaState,
                    int device, int scancode) {
        mDownTime = downTime;
        mEventTime = eventTime;
        mAction = action;
        mKeyCode = code;
        mRepeatCount = repeat;
        mMetaState = metaState;
        mDeviceId = device;
        mScancode = scancode;
    }

    /**
     * Create a new key event.
     *
     * @param downTime The time (in {@link android.os.SystemClock#uptimeMillis})
     * at which this key code originally went down.
     * @param eventTime The time (in {@link android.os.SystemClock#uptimeMillis})
     * at which this event happened.
     * @param action Action code: either {@link #ACTION_DOWN},
     * {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}.
     * @param code The key code.
     * @param repeat A repeat count for down events (> 0 if this is after the
     * initial down) or event count for multiple events.
     * @param metaState Flags indicating which meta keys are currently pressed.
     * @param device The device ID that generated the key event.
     * @param scancode Raw device scan code of the event.
     * @param flags The flags for this key event
     */
    public KeyEvent(long downTime, long eventTime, int action,
                    int code, int repeat, int metaState,
                    int device, int scancode, int flags) {
        mDownTime = downTime;
        mEventTime = eventTime;
        mAction = action;
        mKeyCode = code;
        mRepeatCount = repeat;
        mMetaState = metaState;
        mDeviceId = device;
        mScancode = scancode;
        mFlags = flags;
    }

    /**
     * Create a new key event for a string of characters.  The key code,
     * action, and repeat could will automatically be set to
     * {@link #KEYCODE_UNKNOWN}, {@link #ACTION_MULTIPLE}, and 0 for you.
     *
     * @param time The time (in {@link android.os.SystemClock#uptimeMillis})
     * at which this event occured.
     * @param characters The string of characters.
     * @param device The device ID that generated the key event.
     * @param flags The flags for this key event
     */
    public KeyEvent(long time, String characters, int device, int flags) {
        mDownTime = time;
        mEventTime = time;
        mCharacters = characters;
        mAction = ACTION_MULTIPLE;
        mKeyCode = KEYCODE_UNKNOWN;
        mRepeatCount = 0;
        mDeviceId = device;
        mFlags = flags;
    }

    /**
     * Make an exact copy of an existing key event.
     */
    public KeyEvent(KeyEvent origEvent) {
        mDownTime = origEvent.mDownTime;
        mEventTime = origEvent.mEventTime;
        mAction = origEvent.mAction;
        mKeyCode = origEvent.mKeyCode;
        mRepeatCount = origEvent.mRepeatCount;
        mMetaState = origEvent.mMetaState;
        mDeviceId = origEvent.mDeviceId;
        mScancode = origEvent.mScancode;
        mFlags = origEvent.mFlags;
        mCharacters = origEvent.mCharacters;
    }

    /**
     * Copy an existing key event, modifying its time and repeat count.
     *
     * @deprecated Use {@link #changeTimeRepeat(KeyEvent, long, int)}
     * instead.
     *
     * @param origEvent The existing event to be copied.
     * @param eventTime The new event time
     * (in {@link android.os.SystemClock#uptimeMillis}) of the event.
     * @param newRepeat The new repeat count of the event.
     */
    @Deprecated
    public KeyEvent(KeyEvent origEvent, long eventTime, int newRepeat) {
        mDownTime = origEvent.mDownTime;
        mEventTime = eventTime;
        mAction = origEvent.mAction;
        mKeyCode = origEvent.mKeyCode;
        mRepeatCount = newRepeat;
        mMetaState = origEvent.mMetaState;
        mDeviceId = origEvent.mDeviceId;
        mScancode = origEvent.mScancode;
        mFlags = origEvent.mFlags;
        mCharacters = origEvent.mCharacters;
    }

    /**
     * Create a new key event that is the same as the given one, but whose
     * event time and repeat count are replaced with the given value.
     *
     * @param event The existing event to be copied.  This is not modified.
     * @param eventTime The new event time
     * (in {@link android.os.SystemClock#uptimeMillis}) of the event.
     * @param newRepeat The new repeat count of the event.
     */
    public static KeyEvent changeTimeRepeat(KeyEvent event, long eventTime,
            int newRepeat) {
        return new KeyEvent(event, eventTime, newRepeat);
    }
   
    /**
     * Create a new key event that is the same as the given one, but whose
     * event time and repeat count are replaced with the given value.
     *
     * @param event The existing event to be copied.  This is not modified.
     * @param eventTime The new event time
     * (in {@link android.os.SystemClock#uptimeMillis}) of the event.
     * @param newRepeat The new repeat count of the event.
     * @param newFlags New flags for the event, replacing the entire value
     * in the original event.
     */
    public static KeyEvent changeTimeRepeat(KeyEvent event, long eventTime,
            int newRepeat, int newFlags) {
        KeyEvent ret = new KeyEvent(event);
        ret.mEventTime = eventTime;
        ret.mRepeatCount = newRepeat;
        ret.mFlags = newFlags;
        return ret;
    }
   
    /**
     * Copy an existing key event, modifying its action.
     *
     * @param origEvent The existing event to be copied.
     * @param action The new action code of the event.
     */
    private KeyEvent(KeyEvent origEvent, int action) {
        mDownTime = origEvent.mDownTime;
        mEventTime = origEvent.mEventTime;
        mAction = action;
        mKeyCode = origEvent.mKeyCode;
        mRepeatCount = origEvent.mRepeatCount;
        mMetaState = origEvent.mMetaState;
        mDeviceId = origEvent.mDeviceId;
        mScancode = origEvent.mScancode;
        mFlags = origEvent.mFlags;
        // Don't copy mCharacters, since one way or the other we'll lose it
        // when changing the action.
    }

    /**
     * Create a new key event that is the same as the given one, but whose
     * action is replaced with the given value.
     *
     * @param event The existing event to be copied.  This is not modified.
     * @param action The new action code of the event.
     */
    public static KeyEvent changeAction(KeyEvent event, int action) {
        return new KeyEvent(event, action);
    }
   
    /**
     * Create a new key event that is the same as the given one, but whose
     * flags are replaced with the given value.
     *
     * @param event The existing event to be copied.  This is not modified.
     * @param flags The new flags constant.
     */
    public static KeyEvent changeFlags(KeyEvent event, int flags) {
        event = new KeyEvent(event);
        event.mFlags = flags;
        return event;
    }
   
    /**
     * Don't use in new code, instead explicitly check
     * {@link #getAction()}.
     *
     * @return If the action is ACTION_DOWN, returns true; else false.
     *
     * @deprecated
     * @hide
     */
    @Deprecated public final boolean isDown() {
        return mAction == ACTION_DOWN;
    }

    /**
     * Is this a system key?  System keys can not be used for menu shortcuts.
     *
     * TODO: this information should come from a table somewhere.
     * TODO: should the dpad keys be here?  arguably, because they also shouldn't be menu shortcuts
     */
    public final boolean isSystem() {
        switch (mKeyCode) {
        case KEYCODE_MENU:
        case KEYCODE_SOFT_RIGHT:
        case KEYCODE_HOME:
        case KEYCODE_BACK:
        case KEYCODE_CALL:
        case KEYCODE_ENDCALL:
        case KEYCODE_VOLUME_UP:
        case KEYCODE_VOLUME_DOWN:
        case KEYCODE_MUTE:
        case KEYCODE_POWER:
        case KEYCODE_HEADSETHOOK:
        case KEYCODE_MEDIA_PLAY_PAUSE:
        case KEYCODE_MEDIA_STOP:
        case KEYCODE_MEDIA_NEXT:
        case KEYCODE_MEDIA_PREVIOUS:
        case KEYCODE_MEDIA_REWIND:
        case KEYCODE_MEDIA_FAST_FORWARD:
        case KEYCODE_CAMERA:
        case KEYCODE_FOCUS:
        case KEYCODE_SEARCH:
            return true;
        default:
            return false;
        }
    }


    /**
     * <p>Returns the state of the meta keys.</p>
     *
     * @return an integer in which each bit set to 1 represents a pressed
     *         meta key
     *
     * @see #isAltPressed()
     * @see #isShiftPressed()
     * @see #isSymPressed()
     * @see #META_ALT_ON
     * @see #META_SHIFT_ON
     * @see #META_SYM_ON
     */
    public final int getMetaState() {
        return mMetaState;
    }

    /**
     * Returns the flags for this key event.
     *
     * @see #FLAG_WOKE_HERE
     */
    public final int getFlags() {
        return mFlags;
    }

    /**
     * Returns true if this key code is a modifier key.
     *
     * @return whether the provided keyCode is one of
     * {@link #KEYCODE_SHIFT_LEFT} {@link #KEYCODE_SHIFT_RIGHT},
     * {@link #KEYCODE_ALT_LEFT}, {@link #KEYCODE_ALT_RIGHT}
     * or {@link #KEYCODE_SYM}.
     */
    public static boolean isModifierKey(int keyCode) {
        return keyCode == KEYCODE_SHIFT_LEFT || keyCode == KEYCODE_SHIFT_RIGHT
                || keyCode == KEYCODE_ALT_LEFT || keyCode == KEYCODE_ALT_RIGHT
                || keyCode == KEYCODE_SYM;
    }

    /**
     * <p>Returns the pressed state of the ALT meta key.</p>
     *
     * @return true if the ALT key is pressed, false otherwise
     *
     * @see #KEYCODE_ALT_LEFT
     * @see #KEYCODE_ALT_RIGHT
     * @see #META_ALT_ON
     */
    public final boolean isAltPressed() {
        return (mMetaState & META_ALT_ON) != 0;
    }

    /**
     * <p>Returns the pressed state of the SHIFT meta key.</p>
     *
     * @return true if the SHIFT key is pressed, false otherwise
     *
     * @see #KEYCODE_SHIFT_LEFT
     * @see #KEYCODE_SHIFT_RIGHT
     * @see #META_SHIFT_ON
     */
    public final boolean isShiftPressed() {
        return (mMetaState & META_SHIFT_ON) != 0;
    }

    /**
     * <p>Returns the pressed state of the SYM meta key.</p>
     *
     * @return true if the SYM key is pressed, false otherwise
     *
     * @see #KEYCODE_SYM
     * @see #META_SYM_ON
     */
    public final boolean isSymPressed() {
        return (mMetaState & META_SYM_ON) != 0;
    }

    /**
     * Retrieve the action of this key event.  May be either
     * {@link #ACTION_DOWN}, {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}.
     *
     * @return The event action: ACTION_DOWN, ACTION_UP, or ACTION_MULTIPLE.
     */
    public final int getAction() {
        return mAction;
    }

    /**
     * For {@link #ACTION_UP} events, indicates that the event has been
     * canceled as per {@link #FLAG_CANCELED}.
     */
    public final boolean isCanceled() {
        return (mFlags&FLAG_CANCELED) != 0;
    }
   
    /**
     * Call this during {@link Callback#onKeyDown} to have the system track
     * the key through its final up (possibly including a long press).  Note
     * that only one key can be tracked at a time -- if another key down
     * event is received while a previous one is being tracked, tracking is
     * stopped on the previous event.
     */
    public final void startTracking() {
        mFlags |= FLAG_START_TRACKING;
    }
   
    /**
     * For {@link #ACTION_UP} events, indicates that the event is still being
     * tracked from its initial down event as per
     * {@link #FLAG_TRACKING}.
     */
    public final boolean isTracking() {
        return (mFlags&FLAG_TRACKING) != 0;
    }
   
    /**
     * For {@link #ACTION_DOWN} events, indicates that the event has been
     * canceled as per {@link #FLAG_LONG_PRESS}.
     */
    public final boolean isLongPress() {
        return (mFlags&FLAG_LONG_PRESS) != 0;
    }
   
    /**
     * Retrieve the key code of the key event.  This is the physical key that
     * was pressed, <em>not</em> the Unicode character.
     *
     * @return The key code of the event.
     */
    public final int getKeyCode() {
        return mKeyCode;
    }

    /**
     * For the special case of a {@link #ACTION_MULTIPLE} event with key
     * code of {@link #KEYCODE_UNKNOWN}, this is a raw string of characters
     * associated with the event.  In all other cases it is null.
     *
     * @return Returns a String of 1 or more characters associated with
     * the event.
     */
    public final String getCharacters() {
        return mCharacters;
    }
   
    /**
     * Retrieve the hardware key id of this key event.  These values are not
     * reliable and vary from device to device.
     *
     * {@more}
     * Mostly this is here for debugging purposes.
     */
    public final int getScanCode() {
        return mScancode;
    }

    /**
     * Retrieve the repeat count of the event.  For both key up and key down
     * events, this is the number of times the key has repeated with the first
     * down starting at 0 and counting up from there.  For multiple key
     * events, this is the number of down/up pairs that have occurred.
     *
     * @return The number of times the key has repeated.
     */
    public final int getRepeatCount() {
        return mRepeatCount;
    }

    /**
     * Retrieve the time of the most recent key down event,
     * in the {@link android.os.SystemClock#uptimeMillis} time base.  If this
     * is a down event, this will be the same as {@link #getEventTime()}.
     * Note that when chording keys, this value is the down time of the
     * most recently pressed key, which may <em>not</em> be the same physical
     * key of this event.
     *
     * @return Returns the most recent key down time, in the
     * {@link android.os.SystemClock#uptimeMillis} time base
     */
    public final long getDownTime() {
        return mDownTime;
    }

    /**
     * Retrieve the time this event occurred,
     * in the {@link android.os.SystemClock#uptimeMillis} time base.
     *
     * @return Returns the time this event occurred,
     * in the {@link android.os.SystemClock#uptimeMillis} time base.
     */
    public final long getEventTime() {
        return mEventTime;
    }

    /**
     * Return the id for the keyboard that this event came from.  A device
     * id of 0 indicates the event didn't come from a physical device and
     * maps to the default keymap.  The other numbers are arbitrary and
     * you shouldn't depend on the values.
     *
     * @see KeyCharacterMap#load
     */
    public final int getDeviceId() {
        return mDeviceId;
    }

    /**
     * Renamed to {@link #getDeviceId}.
     *
     * @hide
     * @deprecated
     */
    public final int getKeyboardDevice() {
        return mDeviceId;
    }

    /**
     * Get the primary character for this key.  In other words, the label
     * that is physically printed on it.
     */
    public char getDisplayLabel() {
        return KeyCharacterMap.load(mDeviceId).getDisplayLabel(mKeyCode);
    }
   
    /**
     * <p>
     * Returns the Unicode character that the key would produce.
     * </p><p>
     * Returns 0 if the key is not one that is used to type Unicode
     * characters.
     * </p><p>
     * If the return value has bit
     * {@link KeyCharacterMap#COMBINING_ACCENT}
     * set, the key is a "dead key" that should be combined with another to
     * actually produce a character -- see {@link #getDeadChar} --
     * after masking with
     * {@link KeyCharacterMap#COMBINING_ACCENT_MASK}.
     * </p>
     */
    public int getUnicodeChar() {
        return getUnicodeChar(mMetaState);
    }
   
    /**
     * <p>
     * Returns the Unicode character that the key would produce.
     * </p><p>
     * Returns 0 if the key is not one that is used to type Unicode
     * characters.
     * </p><p>
     * If the return value has bit
     * {@link KeyCharacterMap#COMBINING_ACCENT}
     * set, the key is a "dead key" that should be combined with another to
     * actually produce a character -- see {@link #getDeadChar} -- after masking
     * with {@link KeyCharacterMap#COMBINING_ACCENT_MASK}.
     * </p>
     */
    public int getUnicodeChar(int meta) {
        return KeyCharacterMap.load(mDeviceId).get(mKeyCode, meta);
    }
   
    /**
     * Get the characters conversion data for the key event..
     *
     * @param results a {@link KeyData} that will be filled with the results.
     *
     * @return whether the key was mapped or not.  If the key was not mapped,
     *         results is not modified.
     */
    public boolean getKeyData(KeyData results) {
        return KeyCharacterMap.load(mDeviceId).getKeyData(mKeyCode, results);
    }
   
    /**
     * The same as {@link #getMatch(char[],int) getMatch(chars, 0)}.
     */
    public char getMatch(char[] chars) {
        return getMatch(chars, 0);
    }
   
    /**
     * If one of the chars in the array can be generated by the keyCode of this
     * key event, return the char; otherwise return '\0'.
     * @param chars the characters to try to find
     * @param modifiers the modifier bits to prefer.  If any of these bits
     *                  are set, if there are multiple choices, that could
     *                  work, the one for this modifier will be set.
     */
    public char getMatch(char[] chars, int modifiers) {
        return KeyCharacterMap.load(mDeviceId).getMatch(mKeyCode, chars, modifiers);
    }
   
    /**
     * Gets the number or symbol associated with the key.  The character value
     * is returned, not the numeric value.  If the key is not a number, but is
     * a symbol, the symbol is retuned.
     */
    public char getNumber() {
        return KeyCharacterMap.load(mDeviceId).getNumber(mKeyCode);
    }
   
    /**
     * Does the key code of this key produce a glyph?
     */
    public boolean isPrintingKey() {
        return KeyCharacterMap.load(mDeviceId).isPrintingKey(mKeyCode);
    }
   
    /**
     * @deprecated Use {@link #dispatch(Callback, DispatcherState, Object)} instead.
     */
    @Deprecated
    public final boolean dispatch(Callback receiver) {
        return dispatch(receiver, null, null);
    }
   
    /**
     * Deliver this key event to a {@link Callback} interface.  If this is
     * an ACTION_MULTIPLE event and it is not handled, then an attempt will
     * be made to deliver a single normal event.
     *
     * @param receiver The Callback that will be given the event.
     * @param state State information retained across events.
     * @param target The target of the dispatch, for use in tracking.
     *
     * @return The return value from the Callback method that was called.
     */
    public final boolean dispatch(Callback receiver, DispatcherState state,
            Object target) {
        switch (mAction) {
            case ACTION_DOWN: {
                mFlags &= ~FLAG_START_TRACKING;
                if (DEBUG) Log.v(TAG, "Key down to " + target + " in " + state
                        + ": " + this);
                boolean res = receiver.onKeyDown(mKeyCode, this);
                if (state != null) {
                    if (res && mRepeatCount == 0 && (mFlags&FLAG_START_TRACKING) != 0) {
                        if (DEBUG) Log.v(TAG, "  Start tracking!");
                        state.startTracking(this, target);
                    } else if (isLongPress() && state.isTracking(this)) {
                        try {
                            if (receiver.onKeyLongPress(mKeyCode, this)) {
                                if (DEBUG) Log.v(TAG, "  Clear from long press!");
                                state.performedLongPress(this);
                                res = true;
                            }
                        } catch (AbstractMethodError e) {
                        }
                    }
                }
                return res;
            }
            case ACTION_UP:
                if (DEBUG) Log.v(TAG, "Key up to " + target + " in " + state
                        + ": " + this);
                if (state != null) {
                    state.handleUpEvent(this);
                }
                return receiver.onKeyUp(mKeyCode, this);
            case ACTION_MULTIPLE:
                final int count = mRepeatCount;
                final int code = mKeyCode;
                if (receiver.onKeyMultiple(code, count, this)) {
                    return true;
                }
                if (code != KeyEvent.KEYCODE_UNKNOWN) {
                    mAction = ACTION_DOWN;
                    mRepeatCount = 0;
                    boolean handled = receiver.onKeyDown(code, this);
                    if (handled) {
                        mAction = ACTION_UP;
                        receiver.onKeyUp(code, this);
                    }
                    mAction = ACTION_MULTIPLE;
                    mRepeatCount = count;
                    return handled;
                }
                return false;
        }
        return false;
    }

    /**
     * Use with {@link KeyEvent#dispatch(Callback, DispatcherState, Object)}
     * for more advanced key dispatching, such as long presses.
     */
    public static class DispatcherState {
        int mDownKeyCode;
        Object mDownTarget;
        SparseIntArray mActiveLongPresses = new SparseIntArray();
       
        /**
         * Reset back to initial state.
         */
        public void reset() {
            if (DEBUG) Log.v(TAG, "Reset: " + this);
            mDownKeyCode = 0;
            mDownTarget = null;
            mActiveLongPresses.clear();
        }
       
        /**
         * Stop any tracking associated with this target.
         */
        public void reset(Object target) {
            if (mDownTarget == target) {
                if (DEBUG) Log.v(TAG, "Reset in " + target + ": " + this);
                mDownKeyCode = 0;
                mDownTarget = null;
            }
        }
       
        /**
         * Start tracking the key code associated with the given event.  This
         * can only be called on a key down.  It will allow you to see any
         * long press associated with the key, and will result in
         * {@link KeyEvent#isTracking} return true on the long press and up
         * events.
         *
         * <p>This is only needed if you are directly dispatching events, rather
         * than handling them in {@link Callback#onKeyDown}.
         */
        public void startTracking(KeyEvent event, Object target) {
            if (event.getAction() != ACTION_DOWN) {
                throw new IllegalArgumentException(
                        "Can only start tracking on a down event");
            }
            if (DEBUG) Log.v(TAG, "Start trackingt in " + target + ": " + this);
            mDownKeyCode = event.getKeyCode();
            mDownTarget = target;
        }
       
        /**
         * Return true if the key event is for a key code that is currently
         * being tracked by the dispatcher.
         */
        public boolean isTracking(KeyEvent event) {
            return mDownKeyCode == event.getKeyCode();
        }
       
        /**
         * Keep track of the given event's key code as having performed an
         * action with a long press, so no action should occur on the up.
         * <p>This is only needed if you are directly dispatching events, rather
         * than handling them in {@link Callback#onKeyLongPress}.
         */
        public void performedLongPress(KeyEvent event) {
            mActiveLongPresses.put(event.getKeyCode(), 1);
        }
       
        /**
         * Handle key up event to stop tracking.  This resets the dispatcher state,
         * and updates the key event state based on it.
         * <p>This is only needed if you are directly dispatching events, rather
         * than handling them in {@link Callback#onKeyUp}.
         */
        public void handleUpEvent(KeyEvent event) {
            final int keyCode = event.getKeyCode();
            if (DEBUG) Log.v(TAG, "Handle key up " + event + ": " + this);
            int index = mActiveLongPresses.indexOfKey(keyCode);
            if (index >= 0) {
                if (DEBUG) Log.v(TAG, "  Index: " + index);
                event.mFlags |= FLAG_CANCELED | FLAG_CANCELED_LONG_PRESS;
                mActiveLongPresses.removeAt(index);
            }
            if (mDownKeyCode == keyCode) {
                if (DEBUG) Log.v(TAG, "  Tracking!");
                event.mFlags |= FLAG_TRACKING;
                mDownKeyCode = 0;
                mDownTarget = null;
            }
        }
    }
   
    public String toString() {
        return "KeyEvent{action=" + mAction + " code=" + mKeyCode
            + " repeat=" + mRepeatCount
            + " meta=" + mMetaState + " scancode=" + mScancode
            + " mFlags=" + mFlags + "}";
    }

    public static final Parcelable.Creator<KeyEvent> CREATOR
            = new Parcelable.Creator<KeyEvent>() {
        public KeyEvent createFromParcel(Parcel in) {
            return new KeyEvent(in);
        }

        public KeyEvent[] newArray(int size) {
            return new KeyEvent[size];
        }
    };

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(mAction);
        out.writeInt(mKeyCode);
        out.writeInt(mRepeatCount);
        out.writeInt(mMetaState);
        out.writeInt(mDeviceId);
        out.writeInt(mScancode);
        out.writeInt(mFlags);
        out.writeLong(mDownTime);
        out.writeLong(mEventTime);
    }

    private KeyEvent(Parcel in) {
        mAction = in.readInt();
        mKeyCode = in.readInt();
        mRepeatCount = in.readInt();
        mMetaState = in.readInt();
        mDeviceId = in.readInt();
        mScancode = in.readInt();
        mFlags = in.readInt();
        mDownTime = in.readLong();
        mEventTime = in.readLong();
    }
}

어플리케이션 구성품
Application Components
  1. Activating components: intents : 컴포넌트 활성화(실행) : 인텐트
  2. Shutting down components : 컴포넌트 죽이기
  3. The manifest file  : 명세서 파일
  4. Intent filters : 활성화 필터


Application Components


안드로이드의 중심 특징은 하나의 애플리케이션이 다른 애플리케이션의 엘리먼트를(단, 그 엘리먼트의 애플리케이션이 사용을 허가하는 조건하에서) 사용할 수 있다는 것이다.

예를 들어 만약 여러분의 애플리케이션이 이미지 스크롤 리스트를 표시할 필요가 있고, 다른 애플리케이션이 그에 알맞은 스크롤러scroller를 개발했고 또한 그것을 다른 애플리케이션이 사용할 수 있도록 만들어 놓았다면, 여러분은 자신의 스크롤러를 별도로 개발하지 않고 이미 있는 스크롤러가 그 작업을 수행할 수 있도록 호출할 수 있다. 이를 위해, 여러분의 애플리케이션은 다른 애플리케이션의 코드를 통합하거나 링크하지는 않는다. 오히려 그것이 필요할 때 다른 애플리케이션 내에 있는 해당 영역piece을 간단하게 구동start-up시킬 수 있다.


A central feature of Android is that one application can make use of elements of other applications (provided those applications permit it).

For example, if your application needs to display a scrolling list of images and another application has developed a suitable scroller and made it available to others, you can call upon that scroller to do the work, rather than develop your own. Your application doesn't incorporate the code of the other application or link to it. Rather, it simply starts up that piece of the other application when the need arises.

이런 작업을 위해서는, 어떤 애플리케이션의 특정 영역이 필요해 질 때 시스템은 애플리케이션 프로세스를 시작할 수 있어야 하며, 그리고 그 영역에 대한 Java 오브젝트를 인스턴스화 할 수 있어야 한다. 그러므로 다른 대부분 시스템에서의 애플리케이션과는 달리, 안드로이드는 애플리케이션 안의 모든 것들에 대한 하나의 시작점entry point을 가지지 않는다(예를 들어 main() 함수가 없음). 대신에, 안드로이드 애플리케이션에는 시스템이 그것을 필요로 할 때 인스턴스화하고 실행할 수 있는 기본적인 컴포넌트들이 존재한다.

안드로이드 애플리케이션에는 네 가지 유형의 컴포넌트가 존재한다.

For this to work, the system must be able to start an application process when any part of it is needed, and instantiate the Java objects for that part. Therefore, unlike applications on most other systems, Android applications don't have a single entry point for everything in the application (no main() function, for example). Rather, they have essential components that the system can instantiate and run as needed.

There are four types of components:

Activities

액티비티는 사용자가 착수할 수 있는 하나의 포커스된 시도에 대한 비쥬얼사용자 인터페이스를 나타낸다.

예를 들어 액티비티는 사용자들이 선택할 수 있는 메뉴 아이템 리스트를 나타내거나, 사진과 함께 그것의 캡션caption을 나타낼 수도 있다. 텍스트 메시징 애플리케이션은, 메시지를 보내기 위한 컨택contact 리스트를 보여주는 하나의 액티비티와 선택된 컨택contact에 대해 메시지를 작성하는 두 번째 액티비티, 그리고 오래된 메시지들을 다시 보거나 설정을 바꾸기 위한 나머지 액티비티를 가질 수 있다. 이들 액티비티들은 하나의 결합된 사용자 인터페이스를 형성하기 위해 함께 동작함에도 불구하고, 각각의 액티비티는 다른 액티비티와 독립되어 있다. 각각의 액티비티는 Activity 베이스 클래스의 서브클래스로 구현된다.

하나의 애플리케이션은 단지 한 개의 액티비티로 구성될 수도 있으며, 또한 앞서 간단히 언급했던 텍스트 메시징 애플리케이션처럼 몇 개의 액티비티를 포함하고 있을 수도 있다. 당연히 애플리케이션을 구성하는 액티비티가 무엇인지 그리고 얼마나 많은 액티비티가 그곳에 있는 지는, 그 애플리케이션과 그것의 디자인에 의존적이다. 일반적으로 액티비티들 중 하나에는, 그 애플리케이션이 시작됐을 때 사용자에게 보여질 수 있도록 첫 번째 액티비티라는 표시가 붙게 된다. 하나의 액티비티에서 또 다른 액티비티로의 이동은, 현재 액티비티가 다음번 액티비티를 시작함으로써 이루어진다.

각각의 액티비티에는 그리기draw가 가능한 하나의 디폴트 윈도우가 부여된다. 일반적으로 윈도우는 스크린 전체를 채우지만 스크린보다 작을 수도 있고, 다른 윈도우 그 위에 떠있을 수도 있다. 하나의 액티비티는 또한 추가적인 윈도우를 사용할 수 있다 - 예를 들어 액티비티의 한복판에서 사용자 응답을 요청하는 팝업 다이얼로그dialog라든지, 또는 스크린 상에서 특정 아이템을 선택할 때 사용자에게 필수적인 정보를 표시하는 윈도우가 그것이다.

윈도우 내의 비쥬얼visual 컨텐트는 - 베이스 뷰 클래스로부터 파생된 오브젝트들인 - 뷰View들의 계층구조hierarchy에 의해 만들어진다. 각각의 뷰는 윈도우 내의 하나의 특정 직사각형 영역을 제어한다. 부모Parent 뷰은 그것들의 자식들children의 레이아웃을 포함하고 구조화한다. 계층구조의 최하단의 뷰는 그것들이 제어하는 직사각형 영역을 그리며, 그 영역에 국한된 사용자 액션에 대한 책임을 진다. 이와 같이 뷰는 액티비티와 사용자 간의 상호작용이 이루어지는 영역이다. 예를 들어 하나의 뷰는 작은 이미지를 보여줄 수도 있고, 사용자가 그 이미지를 만질 때 특정 액션을 일으킬 수도 있다. 안드로이드는 여러분이 사용할 수 있는 - 버튼, 텍스트 필드, 스크롤 바, 메뉴 아이템, 체크 박스, 그리고 추가적인 것들을 포함해서 - 이미 만들어진 많은 뷰를 가지고 있다.

뷰 계층구조는 Activity.setContentView() 메쏘드에 의해 액티비티의 윈도우 내에 위치하게 된다. 그 컨텐트 뷰는 그 계층구조의 최상위에 있는 뷰view 오브젝트이다(뷰와 계층구조에 대한 더 많은 정보에 대해서는, 3장. “사용자 인터페이스”를 보라).


 

Activities
An activity presents a visual user interface for one focused endeavor the user can undertake. For example, an activity might present a list of menu items users can choose from or it might display photographs along with their captions. A text messaging application might have one activity that shows a list of contacts to send messages to, a second activity to write the message to the chosen contact, and other activities to review old messages or change settings. Though they work together to form a cohesive user interface, each activity is independent of the others. Each one is implemented as a subclass of the Activity base class.

An application might consist of just one activity or, like the text messaging application just mentioned, it may contain several. What the activities are, and how many there are depends, of course, on the application and its design. Typically, one of the activities is marked as the first one that should be presented to the user when the application is launched. Moving from one activity to another is accomplished by having the current activity start the next one.

Each activity is given a default window to draw in. Typically, the window fills the screen, but it might be smaller than the screen and float on top of other windows. An activity can also make use of additional windows — for example, a pop-up dialog that calls for a user response in the midst of the activity, or a window that presents users with vital information when they select a particular item on-screen.

The visual content of the window is provided by a hierarchy of views — objects derived from the base View class. Each view controls a particular rectangular space within the window. Parent views contain and organize the layout of their children. Leaf views (those at the bottom of the hierarchy) draw in the rectangles they control and respond to user actions directed at that space. Thus, views are where the activity's interaction with the user takes place. For example, a view might display a small image and initiate an action when the user taps that image. Android has a number of ready-made views that you can use — including buttons, text fields, scroll bars, menu items, check boxes, and more.

A view hierarchy is placed within an activity's window by the Activity.setContentView() method. The content view is the View object at the root of the hierarchy. (See the separate User Interface document for more information on views and the hierarchy.)

Services

서비스는 비쥬얼한 사용자 인터페이스를 가지지 않는다.

하지만 오히려 정해지지 않은 시간동안 백그라운드background에서 실행된다. 예를 들어 서비스는 사용자가 다른 일에 주의를 기울이는 동안에 백그라운드 음악을 재생할 수 있다. 또한 그것은 네트워크 상에서 데이터를 가져오거나, 또는 어떤 것을 계산해서 그 결과를 필요로 하는 액티비티에게 제공할 수도 있다. 각각의 서비스는 Service 베이스 클래스를 확장extend한다.

이것의 기본적인 예제는 재생 목록에서 음악을 재생하는 미디어 플레이어이다. 아마도 그 플레이어 애플리케이션은 사용자에게 음악을 선택할 수 있게 하고 그것을 재생하는, 하나 또는 그 이상의 액티비티를 가지고 있을 수 있다. 하지만 음악 재생 그 자체는 액티비티에 의해 제어되어서는 안된다. 왜냐하면 사용자가 플레이어 화면을 벗어난 후, 다른 어떤 것을 실행한 이후에도 그 음악이 계속 재생되길 기대할 것이기 때문이다. 음악이 계속 재생되게 하기 위해, 미디어 플레이어 액티비티는 백그라운드에서 실행되는 하나의 서비스를 시작할 수 있다. 시스템은 심지어 그 서비스를 시작했던 액티비티가 스크린에서 사라진 후 조차도 음악 재생 서비스를 계속 유지할 것이다.

실행되고 있는 서비스에 접속connect하는 것(바인드하는 것)이 (그리고 만약 아직 실행되지 않았다면, 그 서비스를 실행하는 것이) 가능하다. 그것에 접속되어 있는 동안, 여러분은 그 서비스가 제공하는 인터페이스를 통해 서비스와 커뮤니케이션할 수 있다. 음악 서비스의 경우, 이러한 인터페이스는 사용자에게 음악을 일시 멈추고, 되감고, 정지시키고, 다시 재생하는 것을 가능하게 한다.

액티비티와 다른 컴포넌트 처럼, 서비스도 애플리케이션 프로세스의 메인 쓰레드 내에서 실행된다. 그러므로 서비스가 다른 컴포넌트 또는 사용자 인터페이스에 의해 방해받지 않도록 하기 위해서 음악 재생같이 시간을 요하는 작업들을 위해서는 종종 또 다른 쓰레드를 만들어서 작동시킨다. 이 부분에 대해서는 추후 언급되는 “프로세스와 쓰레드”를 보라.

Services
A service doesn't have a visual user interface, but rather runs in the background for an indefinite period of time. For example, a service might play background music as the user attends to other matters, or it might fetch data over the network or calculate something and provide the result to activities that need it. Each service extends the Service base class.

A prime example is a media player playing songs from a play list. The player application would probably have one or more activities that allow the user to choose songs and start playing them. However, the music playback itself would not be handled by an activity because users will expect the music to keep playing even after they leave the player and begin something different. To keep the music going, the media player activity could start a service to run in the background. The system would then keep the music playback service running even after the activity that started it leaves the screen.

It's possible to connect to (bind to) an ongoing service (and start the service if it's not already running). While connected, you can communicate with the service through an interface that the service exposes. For the music service, this interface might allow users to pause, rewind, stop, and restart the playback.

Like activities and the other components, services run in the main thread of the application process. So that they won't block other components or the user interface, they often spawn another thread for time-consuming tasks (like music playback). See Processes and Threads, later.

Broadcast receivers
 브로드캐스트 리시버는 아무 것도 하지 않는 컴포넌트지만, 브로드캐스트 공지를 수신하고 응답한다.

많은 브로드캐스트는 시스템 코드에서 발생된다 - 예를 들어 시간대가 바뀌었다, 배터리가 부족하다, 사진이 찍혔다, 사용자가 언어 설정을 바꾸었다 등이 그것이다. 애플리케이션 또한 브로드캐스트를 발생시킬 수 있다 - 예를 들어 다른 애플리케이션에게 어떤 데이터가 디바이스에 다운로드되었고, 그것들이 그것을 사용하는 것이 가능하다는 것을 알게 할 수 있다.

애플리케이션은 중요하다고 여겨지는 임의의 공지에 응답할 수 있는 임의의 수의 브로드캐스트 리시버를 가질 수 있다. 모든 리시버는 Broadcast Receiver 베이스 클래스를 확장extend한다.

브로드캐스트 리시버는 사용자 인터페이스를 보여주지 않는다. 하지만 그것이 수신한 정보에 응답하는 액티비티를 시작하거나, 또는 사용자에게 알려주기 위해 노티피케이션 매니저notification manager를 사용할 수 있다. 노티피케이션은 여러가지 방법으로 사용자의 주의를 끌 수 있다 - 배경조명 발광, 디바이스 진동, 사운드 재생 등이 있다. 그것은 일반적으로 상태바status bar 내에 아이콘을 상주시켜 놓으며, 사용자는 그 메시지를 얻기 위해 그것을 오픈할 수 있다.


 
Broadcast receivers
A broadcast receiver is a component that does nothing but receive and react to broadcast announcements. Many broadcasts originate in system code — for example, announcements that the timezone has changed, that the battery is low, that a picture has been taken, or that the user changed a language preference. Applications can also initiate broadcasts — for example, to let other applications know that some data has been downloaded to the device and is available for them to use.

An application can have any number of broadcast receivers to respond to any announcements it considers important. All receivers extend the BroadcastReceiver base class.

Broadcast receivers do not display a user interface. However, they may start an activity in response to the information they receive, or they may use the NotificationManager to alert the user. Notifications can get the user's attention in various ways — flashing the backlight, vibrating the device, playing a sound, and so on. They typically place a persistent icon in the status bar, which users can open to get the message.

Content providers

컨텐트 프로바이더는 다른 애플리케이션에게 유용한 특정 애플리케이션의 데이터 집합을 만든다.

그 데이터는 파일 시스템 내, SQLite 데이터베이스 내, 또는 의미있는 다른 어떤 방식으로 저장될 수도 있다. 컨텐트 프로바이더는 자신이 제어하는 타입의 데이터를 다른 애플리케이션이 얻고 저장할 수 있도록 하게 하는 표준 메쏘드 집합set을 구현하기 위해, ContentProvider 베이스 클래스를 확장extend한다. 하지만 애플리케이션은 이러한 메쏘드를 직접적으로 호출하지 않는다. 대신 애플리케이션은 컨텐트 리졸버ContentResolver 오브젝트를 사용하여 그것의 메쏘드를 호출한다. 컨텐트 리졸버는 어떤 컨텐트 프로바이더와도 대화할 수 있으며, 그것과 관련된 임의의 프로세스 간 통신(IPC, interprocess communication)을 관리하기 위해 프로바이더와 협력한다. 컨텐트 프로바이더 사용법에 관한 더 많은 정보는 7장. 컨텐트 프로바이더를 보라.
Content providers
A content provider makes a specific set of the application's data available to other applications. The data can be stored in the file system, in an SQLite database, or in any other manner that makes sense. The content provider extends the ContentProvider base class to implement a standard set of methods that enable other applications to retrieve and store data of the type it controls. However, applications do not call these methods directly. Rather they use a ContentResolver object and call its methods instead. A ContentResolver can talk to any content provider; it cooperates with the provider to manage any interprocess communication that's involved.

See the separate Content Providers document for more information on using content providers.

특정 컴포넌트에 의해 처리되어야 하는 요청이 있을 때마다, 안드로이드는 그 컴포넌트의 애플리케이션 프로세스가 실행되도록 하며, 필요하다면 그것을 시작하기도 한다. 그리고 그 컴포넌트에 맞는 인스턴스가 사용가능해지도록 하며, 필요하다면 그 인스턴스를 생성도 한다.


Whenever there's a request that should be handled by a particular component, Android makes sure that the application process of the component is running, starting it if necessary, and that an appropriate instance of the component is available, creating the instance if necessary.



Activating components: intents (시작)

Content providers are activated when they're targeted by a request from a ContentResolver. The other three components — activities, services, and broadcast receivers — are activated by asynchronous messages called intents. An intent is an Intent object that holds the content of the message. For activities and services, it names the action being requested and specifies the URI of the data to act on, among other things. For example, it might convey a request for an activity to present an image to the user or let the user edit some text. For broadcast receivers, the Intent object names the action being announced. For example, it might announce to interested parties that the camera button has been pressed.

There are separate methods for activating each type of component:

  • An activity is launched (or given something new to do) by passing an Intent object to Context.startActivity() or Activity.startActivityForResult(). The responding activity can look at the initial intent that caused it to be launched by calling its getIntent() method. Android calls the activity's onNewIntent() method to pass it any subsequent intents.

    One activity often starts the next one. If it expects a result back from the activity it's starting, it calls startActivityForResult() instead of startActivity(). For example, if it starts an activity that lets the user pick a photo, it might expect to be returned the chosen photo. The result is returned in an Intent object that's passed to the calling activity's onActivityResult() method.

  • A service is started (or new instructions are given to an ongoing service) by passing an Intent object to Context.startService(). Android calls the service's onStart() method and passes it the Intent object.

    Similarly, an intent can be passed to Context.bindService() to establish an ongoing connection between the calling component and a target service. The service receives the Intent object in an onBind() call. (If the service is not already running, bindService() can optionally start it.) For example, an activity might establish a connection with the music playback service mentioned earlier so that it can provide the user with the means (a user interface) for controlling the playback. The activity would call bindService() to set up that connection, and then call methods defined by the service to affect the playback.

    A later section, Remote procedure calls, has more details about binding to a service.

  • An application can initiate a broadcast by passing an Intent object to methods like Context.sendBroadcast(), Context.sendOrderedBroadcast(), and Context.sendStickyBroadcast() in any of their variations. Android delivers the intent to all interested broadcast receivers by calling their onReceive() methods.

For more on intent messages, see the separate article, Intents and Intent Filters.

Shutting down components 종료

컨텐트 프로바이더는 컨텐트 리졸버의 요청에 응답하는 동안에만 활성화되어 있다.
그리고 브로드캐스트 리시버도 브로드캐스트 메시지에 응답하는 동안에만 활성화되어 있다.
그러므로 이러한 컴포넌트는 명시적으로 종료시켜야 할 필요가 없다.


A content provider is active only while it's responding to a request from a ContentResolver. And a broadcast receiver is active only while it's responding to a broadcast message. So there's no need to explicitly shut down these components.


반면, 액티비티는 사용자 인터페이스를 제공한다.
이것은 사용자와 오랜시간 동안 대화를 하며 활성화 상태로 남아 있다. 심지어는 대화가 지속될 수 있는 한, 그것이 사용되지 않는idle 상태에도 활성화 상태로 남는다.
유사하게, 서비스 또한 오랜 시간동안 실행 상태로 남아 있다.
그래서 안드로이드는 어떤 규칙적인 방식으로 액티비티와 서비스를 종료시키기 위한 메쏘드를 가지고 있다.

Activities, on the other hand, provide the user interface.
They're in a long-running conversation with the user and may remain active, even when idle, as long as the conversation continues.
Similarly, services may also remain running for a long time.
So Android has methods to shut down activities and services in an orderly way:

  • 액티비티는 finish() 메쏘드의 호출을 통해 스스로 종료될 수 있다.
    그리고 finishActivity()를 호출함으로써, 다른 액티비티(startActivityForResult()를 사용해서 시작된 액티비티)를 종료시킬 수도 있다.
  • 서비스는 stopSelf() 메쏘드의 호출이나 Context.stopService()를 호출함으로써 종료될 수 있다.
    • An activity can be shut down by calling its finish() method.
      One activity can shut down another activity (one it started with startActivityForResult()) by calling finishActivity().
    • A service can be stopped by calling its stopSelf() method, or by calling Context.stopService().

     

    또한, 컴포넌트는 그것이 더 이상 사용되지 않을 때, 또는 안드로이드가 더 많은 활성화된 컴포넌트를 위해 메모리를 회수해야 할 때 시스템에 의해 종료될 수 있다.
    이후에 나오는 “컴포넌트 생명주기” 섹션에서 그것이 일어나는 경우를 좀 더 상세히 논의할 것이다.

    Components might also be shut down by the system when they are no longer being used or when Android must reclaim memory for more active components. A later section, Component Lifecycles, discusses this possibility and its ramifications in more detail.

    The manifest file

    안드로이드는 애플리케이션의 컴포넌트를 시작하기 전에, 컴포넌트의 존재를 인식해야 한다.
    그러므로 애플리케이션은 매니페스트 파일에 그것들의 컴포넌트를 선언한다.
    그리고 그 매니페스트 파일은 안드로이드 패키지, .apk 파일 내에 포함된다.
    이 패키지는 애플리케이션의 코드, 파일, 리소스 또한 보유하고 있다.


    Before Android can start an application component, it must learn that the component exists.
    Therefore, applications declare their components in a manifest file that's bundled into the Android package,
    the .apk file that also holds the application's code, files, and resources.

    The manifest is a structured XML file and is always named AndroidManifest.xml for all applications. It does a number of things in addition to declaring the application's components, such as naming any libraries the application needs to be linked against (besides the default Android library) and identifying any permissions the application expects to be granted.

    But the principal task of the manifest is to inform Android about the application's components. For example, an activity might be declared as follows:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest . . . >
       
    <application . . . >
           
    <activity android:name="com.example.project.FreneticActivity"
                     
    android:icon="@drawable/small_pic.png"
                     
    android:label="@string/freneticLabel"
                      . . .  
    >
           
    </activity>
            . . .
       
    </application>
    </manifest>



    The name attribute of the <activity> element names the Activity subclass that implements the activity. The icon and label attributes point to resource files containing an icon and label that can be displayed to users to represent the activity.

    The other components are declared in a similar way — <service> elements for services, <receiver> elements for broadcast receivers, and <provider> elements for content providers. Activities, services, and content providers that are not declared in the manifest are not visible to the system and are consequently never run. However, broadcast receivers can either be declared in the manifest, or they can be created dynamically in code (as BroadcastReceiver objects) and registered with the system by calling Context.registerReceiver().

    For more on how to structure a manifest file for your application, see The AndroidManifest.xml File.

    Intent filters

    An Intent object can explicitly name a target component. If it does, Android finds that component (based on the declarations in the manifest file) and activates it. But if a target is not explicitly named, Android must locate the best component to respond to the intent. It does so by comparing the Intent object to the intent filters of potential targets. A component's intent filters inform Android of the kinds of intents the component is able to handle. Like other essential information about the component, they're declared in the manifest file. Here's an extension of the previous example that adds two intent filters to the activity:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest . . . >
       
    <application . . . >
           
    <activity android:name="com.example.project.FreneticActivity"
                     
    android:icon="@drawable/small_pic.png"
                     
    android:label="@string/freneticLabel"
                      . . .  
    >
               
    <intent-filter . . . >
                   
    <action android:name="android.intent.action.MAIN" />
                   
    <category android:name="android.intent.category.LAUNCHER" />
               
    </intent-filter>
               
    <intent-filter . . . >
                   
    <action android:name="com.example.project.BOUNCE" />
                   
    <data android:mimeType="image/jpeg" />
                   
    <category android:name="android.intent.category.DEFAULT" />
               
    </intent-filter>
           
    </activity>
            . . .
       
    </application>
    </manifest>

    예제의 첫 번째 필터, 즉 “android.intent.action.MAIN” 액션과 “android.intent.category.LAUNCHER” 카테고리로 구성된 필터는 일반적인 것이다. 이것은 디바이스에서 사용자가 실행할 수 있는 애플리케이션 리스트를 스크린에 보여주는 애플리케이션 런처launcher에 그 액티비티가 표시되게 한다. 달리 말하면, 그 액티비티가 애플리케이션의 시작점이고, 사용자가 런처에서 애플리케이션을 선택했을 때 그들이 처음으로 보게 될 액티비티라는 것을 의미한다.


    The first filter in the example — the combination of the action "android.intent.action.MAIN" and the category "android.intent.category.LAUNCHER" — is a common one. It marks the activity as one that should be represented in the application launcher, the screen listing applications users can launch on the device. In other words, the activity is the entry point for the application, the initial one users would see when they choose the application in the launcher.

    The second filter declares an action that the activity can perform on a particular type of data.

    A component can have any number of intent filters, each one declaring a different set of capabilities. If it doesn't have any filters, it can be activated only by intents that explicitly name the component as the target.

    For a broadcast receiver that's created and registered in code, the intent filter is instantiated directly as an IntentFilter object. All other filters are set up in the manifest.

    For more on intent filters, see a separate document, Intents and Intent Filters.

    안드로이드 애플리케이션은 Java 프로그래밍 언어로 작성된다. 컴파일된 Java 코드 - 애플리케이션에 필요한 임의의 데이터와 리소스 파일과 함께 -  는 SDK에 존재하는 aapt 도구에 의해 안드로이드 패키지로 묶여지며, 이렇게 하나로 압축된 아카이브archive 파일에는 .apk 접미사가 부쳐진다.

    이 파일은 모바일 디바이스에 안드로이드 애플리케이션을 배포하고 설치하기 위한 수단이다(사용자들이 자신의 모바일 디바이스에 다운로드하게 되는 파일이 바로 이 파일이다).

    하나의 .apk 파일 안에 있는 모든 코드는 하나의 애플리케이션으로 간주된다.

    Android applications are written in the Java programming language. The compiled Java code — along with any data and resource files required by the application — is bundled by the aapt tool into an Android package, an archive file marked by an .apk suffix.

    This file is the vehicle for distributing the application and installing it on mobile devices; it's the file users download to their devices.

    All the code in a single .apk file is considered to be one application.


    다양한 방법으로 각각의 안드로이드 애플리케이션은 그것 자신의 세계 내에서in its own world 존속한다.


    In many ways, each Android application lives in its own world:

  • 디폴트로 모든 애플리케이션은 자신의 리눅스 프로세스 내에서 실행된다.

    안드로이드는 임의의 애플리케이션 코드가 실행될 필요가 있을 때 그 프로세스를 시작시키며, 그것이 더 이상 필요치 않고 다른 애플리케이션이 시스템 자원을 요구할 때 그 프로세스를 종료시킨다 .

  • By default, every application runs in its own Linux process. Android starts the process when any of the application's code needs to be executed, and shuts down the process when it's no longer needed and system resources are required by other applications.

     

  • 각각의 프로세스는 자기 자신의 Java 가상머신을 가진다.

    그러므로 애플리케이션 코드는 다른 모든 애플리케이션 코드와는 격리되어 실행된다.
  • Each process has its own virtual machine (VM), so application code runs in isolation from the code of all other applications.

     

  • 디폴트로 각각의 애플리케이션에는 고유한 리눅스 유저user ID가 부여된다.

    애플리케이션을 구성하는 파일들은 해당 사용자와 해당 애플리케이션 그 자신에게만 보여지도록 퍼미션permission이 설정된다 - 비록, 다른 애플리케이션에게도 그 파일을 보여줄 방법이 있기는 하지만.
  • By default, each application is assigned a unique Linux user ID. Permissions are set so that the application's files are visible only to that user and only to the application itself — although there are ways to export them to other applications as well.

     

    두 개의 애플리케이션에 대해 동일한 유저user ID를 공유할 수 있도록 배치하는 것이 가능하다.

    그런 경우에 두 개의 애플리케이션은 각자 다른 애플리케이션의 파일을 볼 수 있을 것이다. 시스템 자원을 절약하기 위해 동일한 ID를 가지는 애플리케이션은 또한 동일한 리눅스 프로세스 안에서 실행되도록 배치되며, 동일한 가상머신을 공유한다.

    It's possible to arrange for two applications to share the same user ID, in which case they will be able to see each other's files. To conserve system resources, applications with the same ID can also arrange to run in the same Linux process, sharing the same VM.


    출처 : http://www.kandroid.org/guide/topics/fundamentals.html

    번역 : jameroid.tistory.com
    분류 : Android Basics
    출처 : http://developer.android.com/guide/basics/what-is-android.html


    안드로이드 런타임


    안드로이드는 자바 프로그래밍 언어의 핵심 라이브러리 안에서 가능한 기능들을 제공하는 핵심 라이브러의 세트를 포함한다. 

    모른 안드로이드 어플이케이션은 자신의 프로세스 안에서 실행되며, 달빅 가상머신의 자신 인스턴을 가지고 있다.

    달빅는 디바이스가 다수의 VM의 효율적으로 수행할 수 있도록 만들어 (쓰여) 졌다.
    달빅 VM은 최소 메모리 발자국을 최적화한 달빅실행화일(.dex)형식으로 된 파일을 수행한다.
    VM은 등록 방식이다, (제공되는 dx tool에 의해 .dex형식으로 변환된)자바 언어 컴파일어에 의해 컴파일된
    클래스를 실행한다.


    달빅 VM은 쓰레딩과 하위 메모리 관리와 같은 것을 기능적으로 통제하는 리눅스 커널에 의지한다.


    Android Runtime

    Android includes a set of core libraries that provides most of the functionality available in the core libraries of the Java programming language.

    Every Android application runs in its own process, with its own instance of the Dalvik virtual machine. Dalvik has been written so that a device can run multiple VMs efficiently. The Dalvik VM executes files in the Dalvik Executable (.dex) format which is optimized for minimal memory footprint. The VM is register-based, and runs classes compiled by a Java language compiler that have been transformed into the .dex format by the included "dx" tool.

    The Dalvik VM relies on the Linux kernel for underlying functionality such as threading and low-level memory management.


    리눅스 커널

    안드로이는 보안, 메모리 관리, 프로세스 관리, 네트웍 스택 그리고 드라이버 모델과 같은 중추 시스템은 리눅스
    버젼 2.6에 기초한다.


    Linux Kernel

    Android relies on Linux version 2.6 for core system services such as security, memory management, process management, network stack, and driver model. The kernel also acts as an abstraction layer between the hardware and the rest of the software stack.


    번역 : jameroid.tistory.com
    분류 : Android Basics
    출처 : http://developer.android.com/guide/basics/what-is-android.html


    라이브러리들

    안드로이드는 안드로이드 시스템의 다양한 컴포넌트에 사용되는 c/c++라이브러리 세트를 포함한다.
    이런 능력은 안드로이드 어플리케이션 프레임웍(AAF)을 통해 개발자에게 노출되다.
    핵심 라이브러리 몇개는 아래에 리스트 되었다
    - System C library
      : 표준 C 시스템 라이브러리(libc)의 BSD에서 유래한 구현물, 리눅스 기초의 임베디드 장비에 맞춰진
    - Media Libraries
      : PacketVideo의 OpenCORE 기초위에; 라이브러리는 ,MPEG4/H.264/MP3/AAC/AMR/JPG/PNG,
        정지 이미지들과 마찬가지로 많은 대중적인 오디오와  비디오 포맷의 재생과 녹음을  지원한다
    - Surface Manager
      : 화면 하부 시스템의 접근과  다수의 어플리케이션에서 2D와 3D그래픽 층을 한결같이 구성하는 것을 관리한다.
    - LibWebCore
      : 안드로이드 브라우저와 내장웹뷰등의 현대적인 웹 브라우저 엔진
    - SGL
      : 2D 그래픽 엔지의 기초
    - 3D Libraries
      : OpenGL ES 1.0 APIS위에 기초하는 구현물; 라이브러리는 하드웨어 3D가속(가용한곳에) 또는 높게 최적화된 3D
      소프트웨어 래스터를 포함하여 사용한다.
    - Free Type
      : 비트맵과 벡터 폰트 표현 방식
    - SQLite
      : 강력하고 가벼운 RDB 엔진이 모든 어플리케이션에게 가용하다.



    Libraries

    Android includes a set of C/C++ libraries used by various components of the Android system. These capabilities are exposed to developers through the Android application framework. Some of the core libraries are listed below:

    • System C library - a BSD-derived implementation of the standard C system library (libc), tuned for embedded Linux-based devices
    • Media Libraries - based on PacketVideo's OpenCORE; the libraries support playback and recording of many popular audio and video formats, as well as static image files, including MPEG4, H.264, MP3, AAC, AMR, JPG, and PNG
    • Surface Manager - manages access to the display subsystem and seamlessly composites 2D and 3D graphic layers from multiple applications
    • LibWebCore - a modern web browser engine which powers both the Android browser and an embeddable web view
    • SGL - the underlying 2D graphics engine
    • 3D libraries - an implementation based on OpenGL ES 1.0 APIs; the libraries use either hardware 3D acceleration (where available) or the included, highly optimized 3D software rasterizer
    • FreeType - bitmap and vector font rendering
    • SQLite - a powerful and lightweight relational database engine available to all applications


    안드로이드는
         OS(운영체제)와 미들웨어 그리고 핵심(기본) 어플리케이션 를 포함한
         모바일 디바이스를 위한 소프트웨어 스택이다. ( 주)Stack : 차곡차곡 쌓이다 ).

    안드로이드 SDK는
         Java 프로그래밍 언어를 사용해서 안드로이드 플랫폼위에
         어플리케이션 개발 시작에 필요한  도구와 API들을 제공한다. 

    What is Android?

    Android is a software stack for mobile devices that includes an operating system, middleware and key applications. The Android SDK provides the tools and APIs necessary to begin developing applications on the Android platform using the Java programming language.

    특징들
    - 어플리케이션 프레임웍 :  컴포턴트의 교체와 재새용을 가능하게 한다.
    - 달빅 가상 머신 : 모바일 디바이스을 위해 최적화 되었다.
    - 내장된 브라우저 : 공개소스 WebKit 엔진을 기초로 한다.
    - 최적화된 그래픽 : 맞춤 2D 그래픽 라이브, OpenGL ES1.0 규격을 기초한 3D그래픽으로 로 강해졌다.
    - SQLite : 구조적 데이타 저장을 위해
    - 미디어 지원 : 오디오, 비디오 그리고 정지 이미지 포맷  (MPEG4, H.264, MP3, AAC, JPG, PNG, GIF)
    - (하드웨어 의존) GSM 기술
    - (하드웨어 의존) 블루투스, EDGE, 3G 와 WiFI
    - (하드웨어 의존) 카메라, GPS, 나침반(compass) 그리고 가속도계(accelerometer)
    - 풍부한 개발 환경 : 디바이스 에뮬레이터(장비모방),디버그 툴, 메모리와 성능 분석(performance profiling)
                              그리고 이클립스 IDE를 위한 플러그인 을 포함한다.


    Features

    • Application framework enabling reuse and replacement of components
    • Dalvik virtual machine optimized for mobile devices
    • Integrated browser based on the open source WebKit engine
    • Optimized graphics powered by a custom 2D graphics library; 3D graphics based on the OpenGL ES 1.0 specification (hardware acceleration optional)
    • SQLite for structured data storage
    • Media support for common audio, video, and still image formats (MPEG4, H.264, MP3, AAC, AMR, JPG, PNG, GIF)
    • GSM Telephony (hardware dependent)
    • Bluetooth, EDGE, 3G, and WiFi (hardware dependent)
    • Camera, GPS, compass, and accelerometer (hardware dependent)
    • Rich development environment including a device emulator, tools for debugging, memory and performance profiling, and a plugin for the Eclipse IDE
    안드로이드 아키텍쳐
      : 아래 그림도료는 안드로이드 운영시스텝ㅁ의 주요 구성품(컴포턴트)을 보여준다



    Applications  --- 사용자가 접하는 화면들....

    안드로이드는 이메일 클라이언트와 SMS프로그램, 달력, 지도, 웹브라우저, 연락처 그리고 기타등등을 포함하는
    핵심 어플리케이션을 한 셋트로 구성되어 있다.
    모든 어플리케이션은 자바 프로그래밍 언어를 사용해서 쓰여졌다(만들어 졌다).

    Applications

    Android will ship with a set of core applications including an email client, SMS program, calendar, maps, browser, contacts, and others. All applications are written using the Java programming language.



    어플리케이션 프레임웍

    개방형 개발 플랫폼을 제공함으로써, 안드로이드는 개발자들에게 최고로 풍부하고 혁신적인 어플리케이션을
    만들수 있는 능력을 제공한다

    개발자들은 디바이스 하드웨어의 잇점을 갖거나 위치 정보에 접근하거나 백그라운드 서비스를 수행, 알람 설정
    그리고 상태바에 알림을 추가하고 그리고 더 많은 것들이 모두 무료이다.

    개발자들은 핵심 어플리케이션이 사용하는 동일한 프레임웍 API를 모두 접근한다.
    어플리케이션 구조는 컴포넌트의 간편한 재사용을 위해 디자인 되었다. 
    아무  어플리케이션(프레임웍에 의해 강제되지 )이나 그것의 능력을 공개할 수 있고, 이런 능력을
    다른 어플리케이션에서도 활용할 수 있다.
    동일한 매커니즘은 유저에 의해서 컴포넌트가 대체되는 것도 허용된다.

    모든 서비스 구성 일체와 시스템의 어플리케이션은 밑에 있으며, 포함한다 :
    - 풍부하고 확장할 수 있는 뷰는 리스트,그리드, 텍스트박스, 버튼 그리고 내장되는 웹 브라우저들은
    어플리케이션 개발에 활용될수 있다.
    - Content Providers는 자신의 데이타를 공유하거나 ,어플리케이션이 다른 어플리케이션으로 부터 데이타를 접근할 수 있다.(주소록 같은)
    - Resource Manager코드가 아닌 리소스, 일테면 현지 언어들, 그림들, 배치 파일들을 접근하는 것을 제공한다. 
    - Notification Manager모픈 어플이케이션이 상태바 안에 맞춤 경고를 보여줄 수 있다.
    - Activity Manager는 어플리케이션의 생명주기를 관리하고 맞춤 네비게이션 백스택을 제공한다.

    더 자세한 것들과 어플리케이션을 구경하면서 지나가려면, 노트패드 설명서를 보라.

    Application Framework

    By providing an open development platform, Android offers developers the ability to build extremely rich and innovative applications. Developers are free to take advantage of the device hardware, access location information, run background services, set alarms, add notifications to the status bar, and much, much more.

    Developers have full access to the same framework APIs used by the core applications. The application architecture is designed to simplify the reuse of components; any application can publish its capabilities and any other application may then make use of those capabilities (subject to security constraints enforced by the framework). This same mechanism allows components to be replaced by the user.

    Underlying all applications is a set of services and systems, including:

    • A rich and extensible set of Views that can be used to build an application, including lists, grids, text boxes, buttons, and even an embeddable web browser
    • Content Providers that enable applications to access data from other applications (such as Contacts), or to share their own data
    • A Resource Manager, providing access to non-code resources such as localized strings, graphics, and layout files
    • A Notification Manager that enables all applications to display custom alerts in the status bar
    • An Activity Manager that manages the lifecycle of applications and provides a common navigation backstack

    For more details and a walkthrough of an application, see the Notepad Tutorial.


     



    // SDCARD에서 Bitmap을 만들고, ImageView에 불러온다.
    // FILE
     
    public class TestImages extends Activity {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            ImageView image = (ImageView) findViewById(R.id.test_image);
            Bitmap bMap = BitmapFactory.decodeFile("/sdcard/test2.png");
            image.setImageBitmap(bMap);
        }
    }

    public class TestImages extends Activity {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            ImageView image = (ImageView) findViewById(R.id.test_image);
            Bitmap bMap = BitmapFactory.decodeFile("/sdcard/test2.png");
            image.setImageBitmap(bMap);
        }
    }
    
    

    // SDCARD에서 스트림으로 읽어 들이기
    // STREAM
    public class TestImages extends Activity {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            ImageView image = (ImageView) findViewById(R.id.test_image);
            FileInputStream in;
            BufferedInputStream buf;
            try {
                in = new FileInputStream("/sdcard/test2.png");
                buf = new BufferedInputStream(in);
                Bitmap bMap = BitmapFactory.decodeStream(buf);
                image.setImageBitmap(bMap);
                if (in != null) {
             in.close();
                }
                if (buf != null) {
             buf.close();
                }
            } catch (Exception e) {
                Log.e("Error reading file", e.toString());
            }
        }
    }
    public class TestImages extends Activity {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            ImageView image = (ImageView) findViewById(R.id.test_image);
            FileInputStream in;
            BufferedInputStream buf;
            try {
                in = new FileInputStream("/sdcard/test2.png");
                buf = new BufferedInputStream(in);
                Bitmap bMap = BitmapFactory.decodeStream(buf);
                image.setImageBitmap(bMap);
                if (in != null) {
             in.close();
                }
                if (buf != null) {
             buf.close();
                }
            } catch (Exception e) {
                Log.e("Error reading file", e.toString());
            }
        }
    }
    
    

    // XML
    public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            ImageView image = (ImageView) findViewById(R.id.test_image);
            Bitmap bMap =
                   BitmapFactory.decodeResource(getResources(), R.drawable.icon);
            image.setImageBitmap(bMap);
        }


    public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            ImageView image = (ImageView) findViewById(R.id.test_image);
            Bitmap bMap = 
                   BitmapFactory.decodeResource(getResources(), R.drawable.icon);
            image.setImageBitmap(bMap);
        }
    
    

    // creates a bitmap from an array of bytes
    public class TestImages extends Activity {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            ImageView image = (ImageView) findViewById(R.id.test_image);
            FileInputStream in;
            BufferedInputStream buf;
            try {
                in = new FileInputStream("/sdcard/test2.png");
                buf = new BufferedInputStream(in);
                byte[] bMapArray= new byte[buf.available()];
                buf.read(bMapArray);
                Bitmap bMap =
                    BitmapFactory.decodeByteArray(bMapArray, 0, bMapArray.length);
                image.setImageBitmap(bMap);
                if (in != null) {
             in.close();
                }
                if (buf != null) {
             buf.close();
                }
            } catch (Exception e) {
                Log.e("Error reading file", e.toString());
            }
        }
    }

    public class TestImages extends Activity {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            ImageView image = (ImageView) findViewById(R.id.test_image);
            FileInputStream in;
            BufferedInputStream buf;
            try {
                in = new FileInputStream("/sdcard/test2.png");
                buf = new BufferedInputStream(in);
                byte[] bMapArray= new byte[buf.available()];
                buf.read(bMapArray);
                Bitmap bMap = 
                    BitmapFactory.decodeByteArray(bMapArray, 0, bMapArray.length);
                image.setImageBitmap(bMap);
                if (in != null) {
             in.close();
                }
                if (buf != null) {
             buf.close();
                }
            } catch (Exception e) {
                Log.e("Error reading file", e.toString());
            }
        }
    }
    
    




    public class Hello extends Activity {
     
     SharedPreferences preferences;
     private EditText text;
     
     // onCreate(Bundle) is where you initialize
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
         
            super.onCreate(savedInstanceState);
               
            // setContentView(int) with a layout resource defining your UI
            setContentView(R.layout.main);
           
           
            // findViewById(int) to retrieve the widget int
            // that UI that you need to interact with programmatically
            text = (EditText)findViewById(R.id.EditText01);   
            text.setText("눌린 버튼이 없습니다.");
           
            Button button = (Button)findViewById(R.id.Button04);

            // init preference
            preferences =
                PreferenceManager.getDefaultSharedPreferences(this);

            button.setOnClickListener(new OnClickListener(){
             @Override
             public void onClick(View v){
              String username = preferences.getString("username", "n/a");
              String password = preferences.getString("password", "n/a");

              Toast.makeText(Hello.this, "U: "+username+
              " P:  "+password, Toast.LENGTH_LONG).show();

             }
            }); // setOnClickListener
      
        }

     // XML을 통해서 버튼과 연결된다.
        public void myClickHandler(View view)
        {
         switch(view.getId())
         {
         case R.id.Button01:
          text.setText("첫번째 버튼 눌림");
          break;
         case R.id.Button02:
          text.setText("두번째 버튼 눌림");
          break;
         case R.id.Button03:
          text.setText("세번째 버튼 눌림");
          break;
         }
        }

        // 메뉴 생성후에 추가
        @Override
        public boolean onCreateOptionsMenu(Menu menu)
        {
         MenuInflater inflater = getMenuInflater();
         inflater.inflate(R.menu.menu, menu);
         return true;
        }

        //메뉴아이템 생성후에 추가
        @Override
        public boolean onOptionsItemSelected(MenuItem item)
        {
         switch(item.getItemId())
         {
         case R.id.preferences:
          Intent i = new Intent(Hello.this,Preferences.class);
          startActivity(i);

          Toast.makeText(Hello.this,"관리할수",
                  Toast.LENGTH_LONG).show();

          break;
         }
         return true;
        }
       
    }




    public class Preferences extends PreferenceActivity {
     @Override
     public void onCreate(Bundle savedInstanceState)
     {
      super.onCreate(savedInstanceState);
      addPreferencesFromResource(R.xml.preferences);
     }
    }

    + Recent posts