<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>continue_deve.log</title>
        <link>https://velog.io/</link>
        <description>Lv.1 개발자</description>
        <lastBuildDate>Tue, 08 Dec 2020 08:33:02 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>continue_deve.log</title>
            <url>https://images.velog.io/images/continue_deve/profile/94e35156-054a-4b6b-9d2a-03327b4e56c3/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. continue_deve.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/continue_deve" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Chap7. 함수적 종속과 정규화]]></title>
            <link>https://velog.io/@continue_deve/Chap7.-%ED%95%A8%EC%88%98%EC%A0%81-%EC%A2%85%EC%86%8D%EA%B3%BC-%EC%A0%95%EA%B7%9C%ED%99%94</link>
            <guid>https://velog.io/@continue_deve/Chap7.-%ED%95%A8%EC%88%98%EC%A0%81-%EC%A2%85%EC%86%8D%EA%B3%BC-%EC%A0%95%EA%B7%9C%ED%99%94</guid>
            <pubDate>Tue, 08 Dec 2020 08:33:02 GMT</pubDate>
            <description><![CDATA[<h2 id="함수적-종속">함수적 종속</h2>
<h3 id="정의">정의</h3>
<h3 id="특성">특성</h3>
<h3 id="키와-함수적-종속의-관계">키와 함수적 종속의 관계</h3>
<h3 id="함수적-종속의-유지-방법">함수적 종속의 유지 방법</h3>
<h2 id="정규화">정규화</h2>
<h3 id="데이터-중복의-문제점">데이터 중복의 문제점</h3>
<h3 id="정규형">정규형</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[C) 라즈베리파이 DB 연동]]></title>
            <link>https://velog.io/@continue_deve/C-%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-DB-%EC%97%B0%EB%8F%99</link>
            <guid>https://velog.io/@continue_deve/C-%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-DB-%EC%97%B0%EB%8F%99</guid>
            <pubDate>Mon, 07 Dec 2020 02:46:35 GMT</pubDate>
            <description><![CDATA[<h2 id="조건">조건</h2>
<ol>
<li><p>mariadb에 lab10이라는 테이블을 만들고 측정 시간, 디지털 조도 센서 및 디지털 근접 센서값을 저장하도록 테이블을 구성한다.</p>
</li>
<li><p>측정시간, 조도 센서 및 근접 센서 값을 3초 간격으로 측정하여 lab10 테이블에 저장하도록 demodb.cpp 코드를 수정하여 실행한다. (demodb.cpp코드를 먼저 backup 받을 것)</p>
</li>
<li><p>실행 결과를 mariadb에서 확인한다.</p>
</li>
</ol>
<h2 id="과정">과정</h2>
<h4 id="mariadb에-lab10이라는-테이블을-만들고-측정-시간-디지털-조도-센서-및-디지털-근접-센서값을-저장하도록-테이블을-구성한다">mariadb에 lab10이라는 테이블을 만들고 측정 시간, 디지털 조도 센서 및 디지털 근접 센서값을 저장하도록 테이블을 구성한다.</h4>
<pre><code>$ mysql -u root -p
Enter password : root

MariaDB&gt; create database demofarmdb;
Query OK, 1 row affected (0.00sec)

MariaDB&gt; use demofarmdb;
Database changed;

MariaDB&gt; create table lab10(time char(19) primary key, lightsensor int, neardetect int);
Query OK, 0 rows affected (0.03sec)</code></pre><h4 id="측정시간-조도-센서-및-근접-센서-값을-3초-간격으로-측정하여-lab10-테이블에-저장하도록-demodbcpp-코드를-수정하여-실행한다-demodbcpp코드를-먼저-backup-받을-것">측정시간, 조도 센서 및 근접 센서 값을 3초 간격으로 측정하여 lab10 테이블에 저장하도록 demodb.cpp 코드를 수정하여 실행한다. (demodb.cpp코드를 먼저 backup 받을 것)</h4>
<pre><code>#define LIGHTSEN_OUT 2  //gpio27 - J13 connect
#define COLLISION 3

int get_light_sensor();
int get_neardetect_sensor();

#define DBHOST &quot;localhost&quot;
#define DBUSER &quot;root&quot;
#define DBPASS &quot;root&quot;
#define DBNAME &quot;demofarmdb&quot;

MYSQL *connector;
MYSQL_RES *result;
MYSQL_ROW row;

int main (void)
{
  int adcChannel  = 0;
  int adcValue[8] = {0};

  if(wiringPiSetupGpio() == -1)
  {
    fprintf (stdout, &quot;Unable to start wiringPi: %s\n&quot;, strerror(errno));
    return 1 ;
  }

  if(wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED) == -1) //아날로그를 디지털로 변환하는 부분인데 실제로 이 코드에서는 사용하고 있지 않습니다
  {
    fprintf (stdout, &quot;wiringPiSPISetup Failed: %s\n&quot;, strerror(errno));
    return 1 ;
  }

  pinMode(CS_MCP3208, OUTPUT);

  // MySQL connection                //db붙이는 기능은 이 밑에 두줄 복사
  connector = mysql_init(NULL);
  if (!mysql_real_connect(connector, DBHOST, DBUSER, DBPASS, DBNAME, 3306, NULL, 0))
  {
    fprintf(stderr, &quot;%s\n&quot;, mysql_error(connector));
    return 0;
  }

  printf(&quot;MySQL(rpidb) opened.\n&quot;);

  while(1) //sensor값을 수집하는 부분
  {
    char query[1024];
    adcValue[0] = get_light_sensor(); // Illuminance Sensor
    adcValue[1] = get_neardetect_sensor(); // neardetect Sensor

    //adcValue[7] = 27*pow((double)(adcValue[7]*VCC/4095), -1.10);

    sprintf(query,&quot;insert into lab10 values (now(),%d,%d)&quot;, adcValue[0],adcValue[1]);

    if(mysql_query(connector, query))
    {
      fprintf(stderr, &quot;%s\n&quot;, mysql_error(connector));
      printf(&quot;Write DB error\n&quot;);
    }

    delay(3000);
  }

  mysql_close(connector);

  return 0;
}


int wiringPicheck(void)
{
    if (wiringPiSetup () == -1)
    {
        fprintf(stdout, &quot;Unable to start wiringPi: %s\n&quot;, strerror(errno));
        return 1 ;
    }
}

int get_light_sensor(void)
{
    // sets up the wiringPi library
    if (wiringPiSetup () &lt; 0) 
    {
        fprintf (stderr, &quot;Unable to setup wiringPi: %s\n&quot;, strerror (errno));
        return 1;
    }

    if(digitalRead(LIGHTSEN_OUT))    //day
        return 1;
    else //night
        return 0;
}

int get_neardetect_sensor(void)
{
    if (wiringPiSetup() &lt; 0)
    {
        fprintf(stderr, &quot;Unable to setup wiringPi: %s\n&quot;, strerror(errno));
        return 1;
    }

    if (digitalRead(COLLISION))
        retun 1;
    else
        return 0;
}</code></pre><p>// 원본 demodb.cpp를 개조하긴 했는데 맞는진 모르겠다.
// 장비에 실행해보고 수정할 것.</p>
<h4 id="실행-결과를-mariadb에서-확인한다">실행 결과를 mariadb에서 확인한다.</h4>
<p><a href="http://192.168.1.7/phpmyadmin/%EC%97%90">http://192.168.1.7/phpmyadmin/에</a> 접속하여 확인.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[C)라즈베리파이 시그널 처리]]></title>
            <link>https://velog.io/@continue_deve/C%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-%EC%8B%9C%EA%B7%B8%EB%84%90-%EC%B2%98%EB%A6%AC</link>
            <guid>https://velog.io/@continue_deve/C%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-%EC%8B%9C%EA%B7%B8%EB%84%90-%EC%B2%98%EB%A6%AC</guid>
            <pubDate>Sat, 05 Dec 2020 09:30:22 GMT</pubDate>
            <description><![CDATA[<p>특정 프로세스가 다른 프로세스에게 보내는 신호.
인터럽트와 반대로 소프트웨어적인 이벤트에 속한다.</p>
<ul>
<li>시그널 처리 순서</li>
</ul>
<ol>
<li>시그널을 받은 프로세스는 현재의 수행 제어 흐름을 정지</li>
<li>시그널 처리기를 실행</li>
<li>시그널 처리가 끝난 후 원래의 수행 제어 흐름을 회복<br>

</li>
</ol>
<h3 id="시그널-처리-프로그램-예-1---핸들러">시그널 처리 프로그램 예 1 - 핸들러</h3>
<pre><code>#include &lt;stdio.h&gt;
#include &lt;signal.h&gt;

int alarmFlag = 1;

void alarmHandler() {
    printf(&quot;An alarm clock signal was received \n&quot;);
    alarmFlag = 0;
}

void main() {
    signal(SIGALARM, alarmHandler);
    alarm(3);
    printf(&quot;Looping... \n&quot;);
    while(alarmFlag)
        pause();
    printf(&quot;Loop ends due to alarm signal \n&quot;);
}</code></pre><p>signal(SIGALRM, alarmHandler); // 시그널 처리기 설치.
<strong>: SIGALRM에 해당되면 핸들러 실행.</strong>
// 기본형 : signal(int signum, void(*handler function)(int))
// SIGALRM = 알람 클락 시그널로 해당 알람이 끝나면 발생되는 시그널</p>
<p>alarm(3);
: 3초 동안 알람 실행</p>
<p>while(alarmFlag)
ㅤㅤpause();
: alarmFlag가 1이면 대기.</p>
<p><strong>결론 : alarm이 울리고 3초가 지나면 SIGALRM이 발동되어 alarmHandler가 호출되어 alarmFlag가 0이 되면 main함수가 종료된다.</strong>
<br></p>
<h3 id="시그널-처리-프로그램-예-2---이전-처리기">시그널 처리 프로그램 예 2 - 이전 처리기</h3>
<pre><code>#include &lt;stdio.h&gt;
#include &lt;signal.h&gt;

void main() {
    void (*oldHandler)();
    printf(&quot;I can be Control-C&#39;ed \n&quot;);
    sleep(3);

    oldHandler = signal(SIGINT, SIG_IGN);
    printf(&quot;I&#39;m protected from Control-C now \n&quot;);
    sleep(3);

    signal(SIGINT, oldHandler);
    printf(&quot;I can be Control-C&#39;ed again \n&quot;);
    sleep(3);
    printf(&quot;Bye! \n&quot;);
}</code></pre><p>sleep(3);
: 3초간 작업 대기 상태로.</p>
<p>oldHandler = signal(SIGINT, SIG_IGN);
: 이전 처리기 값을 oldHandler에 저장한다.
// SIGINT : 인터럽트로 Ctrl+c 입력 시 발생하는 시그널.
// SIG_IGN : 시그널을 무시하도록 설정. 단, SIGKILL과 SIGSTOP은 무시할 수 없다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Chap5. 무결성과 보안]]></title>
            <link>https://velog.io/@continue_deve/Chap5.-%EB%AC%B4%EA%B2%B0%EC%84%B1%EA%B3%BC-%EB%B3%B4%EC%95%88</link>
            <guid>https://velog.io/@continue_deve/Chap5.-%EB%AC%B4%EA%B2%B0%EC%84%B1%EA%B3%BC-%EB%B3%B4%EC%95%88</guid>
            <pubDate>Fri, 04 Dec 2020 07:12:10 GMT</pubDate>
            <description><![CDATA[<h2 id="무결성-제약">무결성 제약</h2>
<h3 id="무결성-제약의-유형">무결성 제약의 유형</h3>
<p>무결성(integrity) 
: 저장된 데이터가 실제 세계에 존재하는 정보들을 모순 없이 반영하는 성질.
= 갖추어야 할 제약 조건을 항상 만족하도록 보장하는 성질.
= 무결성 제약(constraint) 또는 무결성 규칙(rule)
<br></p>
<p>Q. 데이터 베이스에서 이러한 무결성 제약 조건들을 만족시키려면 어떻게 해야할까?
A1. 데이터 삽입, 삭제, 수정시 수동으로 검증한다.
-&gt; 데이터 양이 방대하거나 변경 빈도가 높을 경우 거의 불가능하다.</p>
<p>A2. DBMS가 자동으로 보장해준다.
<br></p>
<p>대략적인 무결성 제약 유형<img src="https://images.velog.io/images/continue_deve/post/4f245a98-28d6-4744-bfc2-a4d24cc5769b/image.png" alt=""></p>
<h3 id="기본적-무결성-제약">기본적 무결성 제약</h3>
<p>: 관계형 데이터 모델의 정의로부터 규정된 제약들.
(기본키와 외래키를 정의할 때 반드시 지켜져야 할 규칙으로부터 시작)</p>
<h4 id="기본키-무결성-제약-primary-key-integrity-constraint">기본키 무결성 제약 (primary key integrity constraint)</h4>
<p>: 테이블에서 레코드들은 반드시 유일하게 식별될 수 있어야 한다.</p>
<ul>
<li><p>정의 : 기본키는 널 값을 가질 수 없으며 기본키의 값이 동일한 레코드가 하나의 테이블에 동시에 두 개 이상 존재할 수 없다.</p>
</li>
<li><p>사용자가 기본키를 정의하여 테이블을 생성하면 기본키 무결성 제약은 DBMS에서 자동적으로 검증된다. (제약을 위반하는 레코드가 입력되면 자동적으로 거부됨)</p>
<br>

</li>
</ul>
<h4 id="참조-무결성-제약-referential-integrity-constraint">참조 무결성 제약 (referential integrity constraint)</h4>
<p>: 한 테이블의 레코드가 다른 테이블을 참조할 때, 참조되는 테이블에 해당 레코드가 반드시 존재하거나, 참조할 레코드가 없는 경우 널 값을 가져야 한다는 제약이다. (== 외래키 조건)</p>
<ul>
<li><p>실제 존재하지 않는 잘못된 값이 저장되지 않도록 보정하는 수단.</p>
</li>
<li><p>참조 무결성 제약은 삽입, 삭제, 수정 등의 연산에 의해 위배될 수 있는데, 위배 시 해당 연산을 DBMS에서 실행 거부한다.</p>
<br>

</li>
</ul>
<h3 id="테이블-무결성-제약">테이블 무결성 제약</h3>
<h4 id="not-null">NOT NULL</h4>
<p>사용 : 특정 필드에 대해서 널 값의 입력을 허용하지 않아야 하는 경우.</p>
<p>ex. 주민등록번호처럼 반드시 존재해야 하는 값.</p>
<pre><code>create table student
(
    stu_id    varchar2(10),
    resident_id     varchar2(14)     not null
)</code></pre><ul>
<li><p>not null로 지정된 필드에 널 값이 입력되면 해당 연산을 거부한다.</p>
</li>
<li><p>기본키로 정의된 필드는 명시적으로 not null 조건을 굳이 설정하지 않아도 된다. (내부적으로 허용하지 않기 때문)</p>
<br>

</li>
</ul>
<h4 id="unique">UNIQUE</h4>
<p>: 테이블 내에서 중복된 값을 갖지 않고 유일하게 식별되도록 하는 제약 조건. </p>
<ul>
<li><p>기본키의 개념과 유사</p>
</li>
<li><p>결국 unique조건을 부여할 수 있는 필드들은 해당 테이블의 후보키를 의미한다.</p>
</li>
<li><p>널 값의 입력을 허용한다.</p>
</li>
<li><p>두 개 이상의 필드에 동시 설정 가능하다.</p>
</li>
</ul>
<blockquote>
<p>constraint &lt;제약식명&gt; unique (&lt;필드리스트&gt;)</p>
</blockquote>
<p>ex1. 기본적인 부여 : resident_id의 중복을 허용하지 않음</p>
<pre><code>create table student
(
    stu_id    varchar2(10),
    resident_id    varchar2(14),
    constraint  uc_rid  unique  (resident_id)
)</code></pre><p>ex2. 간단하게 표현 가능</p>
<pre><code>create table student
(
    stu_id    varchar2(10),
    resident_id    varchar2(14) unique
)</code></pre><p>ex3. 두 개 이상의 필드 
: family_name과 given_name이 동시에 중복되는 경우를 허용하지 않음.</p>
<pre><code>create table student
(
    stu_id    varchar2(10),
    resident_id    varchar2(14),
    family_name    varchar2(10),
    given_name    varchar2(10),
    constraint  uc_rid  unique  (family_name, given_name)
)</code></pre><br>

<h4 id="check">CHECK</h4>
<ul>
<li>도메인 제약 : 각 필드의 값은 정의된 도메인에 속한 값만 허용된다. (테이블을 생성할 때 지정한 데이터 타입이 도메인이 된다)</li>
</ul>
<p>사용 : 도메인 제약 이외에도 좀 더 세부적으로 허용할 값의 범위를 지정할 때.</p>
<blockquote>
<p>constraint &lt;제약식명&gt; check (&lt;조건식&gt;)</p>
</blockquote>
<p>// 조건식에는 앞서 말한 필드에 대한 더 세부적인 조건이 들어간다.
// 간단한 표현도 가능하다.</p>
<p>ex. year는 1부터 4까지의 정수이고, address는 {&#39;서울&#39;,&#39;부산&#39;} 하나여야 한다는 조건이 추가된 student 테이블</p>
<pre><code>create table student
(
    stu_id    varchra2(10),
    year    int,
    address    varchar2(10),
    constraint  chk1  check  (year &gt;= 1 and
                      year &lt;= 4 and
                      address in (&#39;서울&#39;, &#39;부산&#39;))</code></pre><br>

<h4 id="default">DEFAULT</h4>
<p>사용 : 레코드를 삽입할 때 필드에 대한 값이 정해지지 않았을 경우 사전에 정해놓은 값으로 입력하도록 지정할 때.</p>
<ul>
<li>값이 정해지지 않으면 일반적으로는 널 값이 입력되지만 default로 사전에 입력될 값을 정해놓으면 그 값이 입력된다.</li>
</ul>
<p>ex1. year의 default값을 1로 지정</p>
<pre><code>create table student
(
    year    int    default 1
)</code></pre><p>ex2. alter table문을 이용할 경우</p>
<pre><code>alter table student
alter column year set default 1</code></pre><p>//default 해제는 alter column year drop default</p>
<p>+) alter column~ 문법은 대부분의 DBMS에서 지원하지만 
오라클에서는 지원하지 않는다. 
오라클에서는
modify (year int default 1)
modify (year int deault null) 을 사용해야 한다.
<br></p>
<h4 id="제약에-대해서">제약에 대해서</h4>
<ul>
<li><p>장점
잘못된 데이터들이 존재할 가능성을 원천적으로 막을 강력한 수단.</p>
</li>
<li><p>단점
예외적인 데이터가 발생했을 때 처리하기 까다로움.
무결성 제약을 검사하는 DBMS의 전체적인 성능저하 가능성.</p>
<br>

</li>
</ul>
<h3 id="기타-무결성-제약">기타 무결성 제약</h3>
<p>데이터 자체의 유효성을 검증하는 것이 아닌 제약 조건일 경우 주장이나 트리거와 같은 명령을 통해 무결성을 보장할 수 있다.</p>
<h4 id="주장assertion">주장(assertion)</h4>
<blockquote>
<p>create assertion &lt;주장이름&gt; check &lt;조건식&gt;</p>
</blockquote>
<p>ex. &quot;교수는 한 학기에 3강좌 이상을 강의할 수 없다&quot;</p>
<pre><code>create assertion assert1 check
    (not exists (select    count(*)
             from    class
             group by    year, semester, prof_id) &gt; 3)
    )</code></pre><p>// not exists는 검색결과에 최소한 하나 이상의 레코드가 존재하는지의 여부를 표현할 수 있다. (하나라도 존재하면 거짓)</p>
<ul>
<li><p>주장 명령문 실행 시 데이터베이스는 현재 저장된 데이터들에 대해 해당 조건이 만족되는지 검증한다.</p>
</li>
<li><p>이후 발생되는 데이터에 대해서도 주장의 조건이 만족되는지 감시하는 역할도 한다.</p>
</li>
<li><p>주장의 조건이 복잡할 경우 시스템 부하의 원인이 된다.</p>
<br>

</li>
</ul>
<h4 id="응용-프로그램에서의-무결성-제약">응용 프로그램에서의 무결성 제약</h4>
<p>앞서 소개한 무결성 제약 방법을 사용하지 않을 땐,
응용 프로그램에서 직접 무결성을 보장하는 코드를 삽입하는 방법이 있다.</p>
<ul>
<li><p>DBMS에서 제공하는 방법을 사용하는 것이 가장 간단하고 편리한 방법이지만, DBMS만으로 제어가 불가능한 복잡한 제약을 구현할 때 사용.</p>
</li>
<li><p>응용 프로그램에서 직접 검증함으로써 데이터베이스에 집중된 부하를 분산하는 효과를 얻을 수도 있다.</p>
<br>

</li>
</ul>
<h2 id="데이터베이스-보안">데이터베이스 보안</h2>
<p>이론적으로 100% 완벽한 보안은 불가능하기 때문에, 데이터의 중요도에 따라 다양한 수준에서의 보안 정책이 이루어져야 한다.</p>
<p>사용자의 권한 제어는 가장 낮은 수준의 보안이지만, 반대로 가장 핵심적이고 기초적안 보안 방법이다.</p>
<h3 id="데이터베이스에서의-사용-권한">데이터베이스에서의 사용 권한</h3>
<p>데이터베이스의 사용 권한이란?
: 사용자가 특정 객체에 대해 특정 연상을 실행할 수 있는 권리.
(특정 객체 : 테이블, 뷰, 필드 등)</p>
<h4 id="권한-제어가-가능한-연산의-종류">권한 제어가 가능한 연산의 종류</h4>
<ul>
<li><p>데이터 접근 관련 연산 (DML)
: 데이터룰 변경 또는 참조하는 모든 행위.
ex. SQL의 select, insert, delete, update연산</p>
</li>
<li><p>스키마 관련 연산 (DDL)
: 스키마를 수정하는 연산.
ex. SQL의 create table, alter table, drop table, create index 등</p>
</li>
</ul>
<h4 id="데이터베이스의-사용자-부류">데이터베이스의 사용자 부류</h4>
<ul>
<li><p>데이터베이스 관리자
: DBMS내의 모든 객체에 대해 모든 종류의 권한을 갖고, 일반 사용자에게 일부 또는 모든 권한을 부여하거나 회수할 수 있다.</p>
</li>
<li><p>객체 소유자(owner)
: 특정 사용자가 객체를 생성했으면 그 사용자가 해당 객체의 소유자가 된다. 소유자는 해당 객체에 대해 DBA와 같이 모든 권한을 갖는다.</p>
</li>
<li><p>기타 사용자
: 기본적으로 객체에 대한 일체의 사용권한이 없다.
DBA나 객체 소유자로부터 권한을 부여받을 수 있다.</p>
</li>
</ul>
<p>+) 실제 권한이 부여되는 연산의 종류는 매우 다양하며 DBMS마다 별도로 정의.
<br></p>
<h3 id="sql에서의-권한-제어">SQL에서의 권한 제어</h3>
<h4 id="grant">GRANT</h4>
<p>: SQL의 권한 부여 명령문.</p>
<blockquote>
<p>grant &lt;권한리스트&gt; on &lt;객체명&gt; to &lt;사용자리스트&gt;</p>
</blockquote>
<ul>
<li><p>&lt;권한리스트&gt; : 권한의 종류에 대한 리스트
; 한 개 이상의 권한을 포함할 수 있다.
ex. select, insert, delete, update, references</p>
</li>
<li><p>&lt;객체명&gt; : 대상이 되는 객체</p>
</li>
<li><p>&lt;사용자리스트&gt; : 권한을 부여받는 사용자들의 리스트</p>
</li>
</ul>
<p>= &lt;사용자리스트&gt;에게 &lt;객체명&gt;에 대한 &lt;권한리스트&gt;를 실행할 권리를 부여.</p>
<p>ex1. 기본형</p>
<pre><code>grant select, delete on student to kim</code></pre><p>ex2. 특정 필드 제한 허용</p>
<pre><code>grant select (stu_id) on student to kim</code></pre><p>select, update는 특별히 테이블 내의 특정 필드에 대해서만 연산을 허용할 수 있다. 위 코드는 stu_id에 대해서만 select연산을 허용한다는 의미.
<br></p>
<p>ex3. references</p>
<pre><code>grant references (dept_id) on department to kim</code></pre><p>전제상황 :
department (lee소유)
kim이 department의 dept_id를 참조하는 student테이블을 만들고자 함.
이 때 kim은 department에 대한 권한이 없으므로 외래키 정의가 불가함.
그래서 lee는 kim에게 department를 참조할 수 있는 권한을 주고자 함.</p>
<p>reference는 lee가 kim에게 department 참조 권한을 줄 때 사용가능.
<br></p>
<p>ex4. public</p>
<pre><code>grant select on student to public</code></pre><p>모든 사용자에게 &lt;권한리스트&gt;의 권한 부여.
<br></p>
<p>ex5. all privileges</p>
<pre><code>grant all privileges on student to lee</code></pre><p>모든 종류의 권한을 하나의 명령으로 부여하는 키워드.</p>
<p>+) grant문은  데이터 접근에 관련한 권한을 제어할 수 있음을 알았다.
일부 DBMS들은 스키마 관련 연산도 grant문으로 부여할 수 있다.
(뒤에 나오는 오라클에서의 사용자 권한 제어)
<br></p>
<h4 id="with-grant-option">WITH GRANT OPTION</h4>
<p>: 부여받은 권한을 다른 사용자에게 전파할 수 있는 옵션.
(GRANT는 부여 받은 명령을 실행만 할 수 있는 자격을 얻는다)</p>
<p>ex. 기본형</p>
<pre><code>grant select on student to kim with grant option</code></pre><p>// select권한을 부여받은 kim은</p>
<pre><code>grant select on student to chang</code></pre><p>// chang에게 select권한을 부여할 수 있다.
// chang은 다른 사용자에게 권한 부여를 할 수 없다.</p>
<ul>
<li>남용될 경우 권한 부여에 대한 추적이 매우 어려워져 보안문제 야기가능.</li>
<li>사용이 권장되진 않음.<br>

</li>
</ul>
<h4 id="revoke">REVOKE</h4>
<p>: 다른 사용자에게 부여한 권한을 회수하는 명령. (revoke : 취소)</p>
<blockquote>
<p>revoke &lt;권한리스트&gt; on &lt;객체명&gt; from &lt;사용자리스트&gt;</p>
</blockquote>
<ul>
<li>revoke문은 연쇄적인 권한 회수로 이어질 수 있다는 점을 주의!
ex. lee에게 with grant option으로 권한을 부여받은 kim이 chang에게 부여한 권한도 kim의 권한이 회수되면 같이 회수된다.<br>

</li>
</ul>
<h3 id="롤role">롤(role)</h3>
<p>: 권한에 따른 사용자 그룹.
; 원칙적으로 데이터베이스 관리자만이 생성할 수 있다.</p>
<p>권한별로 사용자 그룹을 만들어 그룹에 권한을 부여하는 방법은 권한 부여에서 단순히 반복되는 작업을 줄여준다.</p>
<ul>
<li><p>롤 생성</p>
<blockquote>
<p>create role &lt;롤이름&gt;</p>
</blockquote>
<pre><code>  ex. create role employee</code></pre></li>
<li><p>사용자에 롤 배정</p>
<blockquote>
<p>grant &lt;롤리스트&gt; to &lt;사용자리스트&gt;</p>
</blockquote>
<pre><code>  ex. grant employee, manager to park</code></pre><p>// &lt;롤리스트&gt;에는 하나 이상의 롤들이 사용될 수 있다. 즉, 사용자는 하나 이상의 롤에 배정 될 수 있다.</p>
<br>
</li>
<li><p>롤에 권한 부여</p>
<pre><code>ex. grant select on student to employee</code></pre></li>
<li><p>배정된 롤에서 특정 사용자 배제</p>
<blockquote>
<p>revoke &lt;롤리스트&gt; from &lt;사용자리스트&gt;</p>
</blockquote>
<pre><code>  ex. revoke manager from choi</code></pre></li>
<li><p>롤 자제를 삭제</p>
<blockquote>
<p>drop role manager</p>
</blockquote>
</li>
</ul>
<br>

<h3 id="뷰를-이용한-권한-제어">뷰를 이용한 권한 제어</h3>
<p>: 필드뿐만 아니라 레코드 일부에 대해서도 접근제어가 가능해져 더 강력한 보안이 가능하다. </p>
<p>; 특정 테이블에서 일부 필드 혹은 일부 레코드에 대해서만 접근을 허용할 경우 이 부분들을 뷰로 정의하고, 그 다음 사용자에게 정의된 뷰에 대해 접근 권한을 부여하고 실제 테이블에 대한 접근을 차단한다면 사용자에게 감추고 싶은 부분에 대한 보안이 자연스럽게 구현된다.</p>
<ul>
<li>뷰
: 논리적 스키마 또는 테이블로부터 정의된 가상 테이블
; 복잡한 스키마를 사용자에게 간단한 형태로 보이게 하는 단순화 기능
; 강력한 보안의 수단</li>
</ul>
<p>+) 뷰를 사용하지 않는 단순한 grant문만으로는 필드에 대해서만 접근제어 가능.</p>
<h2 id="오라클에서의-무결성과-보안">오라클에서의 무결성과 보안</h2>
<h3 id="오라클에서의-무결성-제약">오라클에서의 무결성 제약</h3>
<p>오라클은 기본 무결성 제약과 테이블의 무결성 제약 기능을 모두 제공한다.</p>
<p>department 테이블을 참조하는 외래키가 정의된 student테이블과 department 테이블을 생성할 때 생성 순서와 레코드 삽입 순서를 주의해야한다. (둘 다 department 먼저)</p>
<h4 id="기본적-무결성-제약의-보장">기본적 무결성 제약의 보장</h4>
<ul>
<li><p>기본키 무결성 제약
: 중복되는 레코드 삽입 거부</p>
</li>
<li><p>참조 무결성 제약
: 참조하는 테이블의 기본키에 존재하지 않는 외래키 삽입 거부.
; 이 외에도 참조되는 레코드나 테이블의 삭제 거부.</p>
</li>
</ul>
<h4 id="테이블-무결성-제약의-보장">테이블 무결성 제약의 보장</h4>
<ul>
<li>NOT NULL</li>
<li>UNIQUE</li>
<li>CHECK</li>
<li>DEFAULT
: default가 지정된 필드에 의도적으로 널 값을 삽입할 경우에는 널 값이 입력된다.<br>

</li>
</ul>
<h3 id="오라클에서의-사용자-권한-제어">오라클에서의 사용자 권한 제어</h3>
<h4 id="오라클의-권한-종류">오라클의 권한 종류</h4>
<p>: 시스템 전반에 대한 접근 권한을 제어하는 기능을 갖고 있다.
크게 시스템 권한 / 객체 권한으로 나뉜다.</p>
<ul>
<li><p>시스템 권한 (system privileges)
: 사용자의 생성, 테이블이나 테이블스페이스의 생성 등과 같이 주로 시스템의 자원을 관리할 수 있는 권한.<br>
; 오라클에서는 그 종류가 100개가 넘는다.
; 기본적으로 DBA 계정인 sys, system은 모든 시스템 권한을 갖고있다.<br>
ex. create user/drop user, create session(로그인 권한), create table/drop any table/select any table, create view/drop any view, create tablespace/drop tablespace, create role/drop any role</p>
<br>
</li>
<li><p>객체 권한 (object privileges)
: 해당 객체에 대해 select, insert, delete, update등과 같은 DML을 실행할 수 있는 권한.</p>
<br>

</li>
</ul>
<h4 id="사용자-계정-생성과-권한-관리">사용자 계정 생성과 권한 관리</h4>
<ul>
<li>사용자 계정 생성과 GRANT
오라클에서는 계정을 생성했다고 해서 이 계정으로 로그인이나 테이블 생성이 곧바로 불가능하다.</li>
<li><blockquote>
<p>system계정으로 접속하여 권한을 부여해주어야 한다.</p>
</blockquote>
</li>
</ul>
<p>+) 오라클에서 다른 사용자가 소유한 테이블에 대해 테이블 이름을 명시할 때는 &#39;소유자명.테이블명&#39;과 같이 테이블 이름 앞에 소유자명까지 기입해야 한다. </p>
<ul>
<li><p>WITH GRANT OPTION</p>
</li>
<li><p>REVOKE
: 권한을 회수하고 select를 하게되면 &#39;테이블 또는 뷰가 존재하지 않습니다&#39;라는 에러 메시지가 뜨는데 이는 실제로 존재하지 않는다는 것이 아니라 사용자에게 테이블의 존재를 알리지 않는 것을 의미한다.</p>
</li>
</ul>
<p>+) 오라클의 with admin option
: 시스템 권한을 전파할 때 사용한다. (with grant option은 객체 권한 전파시 사용)
<br></p>
<h4 id="롤의-생성과-관리">롤의 생성과 관리</h4>
<ul>
<li>오라클의 기본적인 롤 종류
: 오라클은 설치할 때 기본적으로 정의된 롤들이 있다.
기본 롤의 종류로는 connect, resource, dba가 있다. <img src="https://images.velog.io/images/continue_deve/post/14073443-c901-4338-842d-0b933ba520ce/image.png" alt=""></li>
</ul>
<p>일반적으로 사용자를 생성하면 특별한 제한이 없는 한 connect와 resource롤을 부여한다.
<br></p>
<ul>
<li>롤의 생성과 사용자 배정
: 오라클에서 create role문은 DBA또는 DBA로부터 롤을 생성하는 권한을 부여받은 사용자만이 실행할 수 있다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[이벤트 처리 - 메소드 재정의 / 위젯 처리 / 레이아웃 터치(ACTION_DOWN)]]></title>
            <link>https://velog.io/@continue_deve/%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%B2%98%EB%A6%AC-%EB%A9%94%EC%86%8C%EB%93%9C-%EC%9E%AC%EC%A0%95%EC%9D%98-%EC%9C%84%EC%A0%AF-%EC%B2%98%EB%A6%AC-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83-%ED%84%B0%EC%B9%98ACTIONDOWN</link>
            <guid>https://velog.io/@continue_deve/%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%B2%98%EB%A6%AC-%EB%A9%94%EC%86%8C%EB%93%9C-%EC%9E%AC%EC%A0%95%EC%9D%98-%EC%9C%84%EC%A0%AF-%EC%B2%98%EB%A6%AC-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83-%ED%84%B0%EC%B9%98ACTIONDOWN</guid>
            <pubDate>Wed, 11 Nov 2020 13:51:40 GMT</pubDate>
            <description><![CDATA[<p>Chap7. 인터페이스 기초04- 이벤트 (Event)
패키지명 : chap7_prac3</p>
<p>화면을 터치하면 메소드 재정의(onTouchEvent)를 통한 이벤트 처리</p>
<p>화면을 터치하고 있으면 layout의 textView가 &quot;Layout Touch Down&quot;
화면에서 손을 떼면 layout의 textView가 &quot;Layout Touch Up&quot;</p>
<p>버튼을 누르면 위젯 이벤트 처리</p>
<p><img src="https://images.velog.io/images/continue_deve/post/8b01c97d-1829-4123-b897-a70308a9f9e6/64.gif" alt=""></p>
<h3 id="전체-코드">전체 코드</h3>
<ul>
<li>MainActivity.java<pre><code>package ddwucom.mobile.chap7_prac3;
</code></pre></li>
</ul>
<p>import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;</p>
<p>import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;</p>
<p>public class MainActivity extends AppCompatActivity {</p>
<pre><code>@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ConstraintLayout layout = findViewById(R.id.layout);

    final TextView textView = findViewById(R.id.textView);

    layout.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                textView.setText(&quot;Layout Touch Down&quot;);
                return true;
            } else if (event.getAction() == MotionEvent.ACTION_UP) {
                textView.setText(&quot;Layout Touch Up&quot;);
            }
            return false;
        }
    });
}

// 메소드 재정의
public boolean onTouchEvent(MotionEvent event) {
    Toast.makeText(this, &quot;메소드 재정의&quot;, Toast.LENGTH_SHORT).show();
    return false;
}

// 위젯 이벤트 처리
public void onClick (View v) {
    Toast.makeText(MainActivity.this, &quot;위젯 이벤트 처리&quot;, Toast.LENGTH_SHORT).show();
}</code></pre><p>}</p>
<pre><code>- activity_main.xml</code></pre><?xml version="1.0" encoding="utf-8"?>
<p>&lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=&quot;<a href="http://schemas.android.com/apk/res/android&quot;">http://schemas.android.com/apk/res/android&quot;</a>
    xmlns:app=&quot;<a href="http://schemas.android.com/apk/res-auto&quot;">http://schemas.android.com/apk/res-auto&quot;</a>
    xmlns:tools=&quot;<a href="http://schemas.android.com/tools&quot;">http://schemas.android.com/tools&quot;</a>
    android:id=&quot;@+id/layout&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    tools:context=&quot;.MainActivity&quot;&gt;</p>
<pre><code>&lt;TextView
    android:id=&quot;@+id/textView&quot;
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:layout_marginTop=&quot;32dp&quot;
    android:text=&quot;Hello World!&quot;
    app:layout_constraintLeft_toLeftOf=&quot;parent&quot;
    app:layout_constraintRight_toRightOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/button&quot; /&gt;

&lt;Button
    android:id=&quot;@+id/button&quot;
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:layout_marginTop=&quot;32dp&quot;
    android:onClick=&quot;onClick&quot;
    android:text=&quot;Button&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toTopOf=&quot;parent&quot; /&gt;</code></pre><p>&lt;/androidx.constraintlayout.widget.ConstraintLayout&gt;</p>
<pre><code>
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[리스너 인터페이스를 구현하여 이벤트 처리 (Listener Interface)]]></title>
            <link>https://velog.io/@continue_deve/%EB%A6%AC%EC%8A%A4%EB%84%88-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EB%A5%BC-%EA%B5%AC%ED%98%84%ED%95%98%EC%97%AC-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%B2%98%EB%A6%AC-Listener-Interface</link>
            <guid>https://velog.io/@continue_deve/%EB%A6%AC%EC%8A%A4%EB%84%88-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EB%A5%BC-%EA%B5%AC%ED%98%84%ED%95%98%EC%97%AC-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%B2%98%EB%A6%AC-Listener-Interface</guid>
            <pubDate>Wed, 11 Nov 2020 13:17:11 GMT</pubDate>
            <description><![CDATA[<p>Chap7. 인터페이스 기초04- 이벤트 (Event)
패키지명 : chap7_prac, chap7_prac2</p>
<h2 id="chap7_prac">chap7_prac</h2>
<p>유형1. 별도의 리스너 인터페이스 구현 클래스 작성
유형2. Activity가 리스너 인터페이스 직접 구현
유형4. 익명 내부 클래스로 구현 - 별도의 클래스 없이 인터페이스에서 직접 객체 생성
유형5. 익명 내부 클래스의 임시 객체로 구현 - 객체 이름 없이 인터페이스 구현 및 등록</p>
<h3 id="유형1-별도의-리스너-인터페이스-구현-클래스-작성">유형1. 별도의 리스너 인터페이스 구현 클래스 작성</h3>
<pre><code>public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button1 = findViewById(R.id.button);

        MyClick myClick = new MyClick();    //인터페이스는 대문자로 시작, 내부 구현 메소드는 소문자로 시작
        button1.setOnClickListener(myClick);
    }

    class MyClick implements View.OnClickListener {
        @Override
        public void onClick(View view) {
            Toast.makeText(MainActivity.this, &quot;유형1&quot;, Toast.LENGTH_SHORT).show();
        }
    }
}</code></pre><br>

<h3 id="유형2-activity가-리스너-인터페이스-직접-구현">유형2. Activity가 리스너 인터페이스 직접 구현</h3>
<pre><code>public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button2 = findViewById(R.id.button2);

        button2.setOnClickListener(this);   // 객체를 만들 필요없이 자기자신 호출

    }

    public void onClick(View v) {
        Toast.makeText(MainActivity.this, &quot;유형2&quot;, Toast.LENGTH_SHORT).show();
    }
}</code></pre><br>

<h3 id="유형4-익명-내부-클래스로-구현---별도의-클래스-없이-인터페이스에서-직접-객체-생성">유형4. 익명 내부 클래스로 구현 - 별도의 클래스 없이 인터페이스에서 직접 객체 생성</h3>
<pre><code>public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button3 = findViewById(R.id.button3);

        button3.setOnClickListener(myClickListener);
    }

    final View.OnClickListener myClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Toast.makeText(MainActivity.this, &quot;유형4&quot;, Toast.LENGTH_SHORT).show();
        }
    };
}</code></pre><br>

<h3 id="유형5-익명-내부-클래스의-임시-객체로-구현---객체-이름-없이-인터페이스-구현-및-등록">유형5. 익명 내부 클래스의 임시 객체로 구현 - 객체 이름 없이 인터페이스 구현 및 등록</h3>
<pre><code>public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    // implements View.OnClickListener 는 유형2

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button4 = findViewById(R.id.button4);

        button4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this, &quot;유형5&quot;, Toast.LENGTH_SHORT).show();
            }
        });
    }
}</code></pre><h3 id="전체-코드">전체 코드</h3>
<ul>
<li>MainActivity.java<pre><code>// 유형1. 별도의 리스너 인터페이스 구현 클래스 작성
// 유형2. Activity가 리스너 인터페이스 직접 구현
// 유형3. 뷰를 직접 작성할 경우 뷰에 리스너 인터페이스 구현
// 유형4. 익명 내부 클래스로 구현 - 별도의 클래스 없이 인터페이스에서 직접 객체 생성
// 유형5. 익명 내부 클래스의 임시 객체로 구현 - 객체 이름 없이 인터페이스 구현 및 등록
</code></pre></li>
</ul>
<p>package ddwucom.mobile.chap7_prac;</p>
<p>import androidx.appcompat.app.AppCompatActivity;</p>
<p>import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;</p>
<p>public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    // implements View.OnClickListener 는 유형2</p>
<pre><code>@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Button button1 = findViewById(R.id.button);
    Button button2 = findViewById(R.id.button2);
    Button button3 = findViewById(R.id.button3);
    Button button4 = findViewById(R.id.button4);

    // 유형1. 별도의 리스너 인터페이스 구현 클래스 작성
    MyClick myClick = new MyClick();    //인터페이스는 대문자로 시작, 내부 구현 메소드는 소문자로 시작
    button1.setOnClickListener(myClick);

    // 유형2. Activity가 리스너 인터페이스 직접 구현
    button2.setOnClickListener(this);   // 객체를 만들 필요없이 자기자신 호출

    // 유형4. 익명 내부 클래스로 구현 - 별도의 클래스 없이 인터페이스에서 직접 객체 생성
    button3.setOnClickListener(myClickListener);

    // 유형5. 익명 내부 클래스의 임시 객체로 구현 - 객체 이름 없이 인터페이스 구현 및 등록
    button4.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Toast.makeText(MainActivity.this, &quot;유형5&quot;, Toast.LENGTH_SHORT).show();
        }
    });
}

// 유형1. 별도의 리스너 인터페이스 구현 클래스 작성
class MyClick implements View.OnClickListener {
    @Override
    public void onClick(View view) {
        Toast.makeText(MainActivity.this, &quot;유형1&quot;, Toast.LENGTH_SHORT).show();
    }
}

// 유형2. Activity가 리스너 인터페이스 직접 구현
public void onClick(View v) {
    Toast.makeText(MainActivity.this, &quot;유형2&quot;, Toast.LENGTH_SHORT).show();
}

// 유형4. 익명 내부 클래스로 구현 - 별도의 클래스 없이 인터페이스에서 직접 객체 생성
final View.OnClickListener myClickListener = new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Toast.makeText(MainActivity.this, &quot;유형4&quot;, Toast.LENGTH_SHORT).show();
    }
};</code></pre><p>}</p>
<pre><code>- activity_main.xml
![](https://images.velog.io/images/continue_deve/post/aace8662-57b3-46e3-baa2-d2558f8aebd1/63.PNG)</code></pre><?xml version="1.0" encoding="utf-8"?>
<p>&lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=&quot;<a href="http://schemas.android.com/apk/res/android&quot;">http://schemas.android.com/apk/res/android&quot;</a>
    xmlns:app=&quot;<a href="http://schemas.android.com/apk/res-auto&quot;">http://schemas.android.com/apk/res-auto&quot;</a>
    xmlns:tools=&quot;<a href="http://schemas.android.com/tools&quot;">http://schemas.android.com/tools&quot;</a>
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    tools:context=&quot;.MainActivity&quot;&gt;</p>
<pre><code>&lt;Button
    android:id=&quot;@+id/button&quot;
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:layout_marginTop=&quot;16dp&quot;
    android:text=&quot;별도의 리스너 인터페이스 구현&quot;
    android:textSize=&quot;24sp&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintHorizontal_bias=&quot;0.646&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toTopOf=&quot;parent&quot; /&gt;

&lt;Button
    android:id=&quot;@+id/button2&quot;
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:layout_marginTop=&quot;24dp&quot;
    android:text=&quot;Activity가 직접 구현&quot;
    android:textSize=&quot;24sp&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/button&quot; /&gt;

&lt;Button
    android:id=&quot;@+id/button3&quot;
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:layout_marginTop=&quot;24dp&quot;
    android:text=&quot;익명 내부 클래스로 구현&quot;
    android:textSize=&quot;24sp&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/button2&quot; /&gt;

&lt;Button
    android:id=&quot;@+id/button4&quot;
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:layout_marginTop=&quot;24dp&quot;
    android:text=&quot;익명 내부 클래스의 임시객체로 구현&quot;
    android:textSize=&quot;24sp&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/button3&quot; /&gt;</code></pre><p>&lt;/androidx.constraintlayout.widget.ConstraintLayout&gt;</p>
<pre><code>
&lt;br&gt;

## chap7_prac2
// 유형3. 뷰를 직접 작성할 경우 뷰에 리스너 인터페이스 구현

activity_main.xml을 사용하지않고 Custom View를 작성.
커스텀뷰는 touchListener를 실행하는 뷰를 포함한다.

앱을 실행하면 노란색인 커스텀뷰가 뜨고 해당 뷰를 터치하면 onTouch 메소드가 실행되어 토스트를 띄운다.

즉, 커스텀뷰에 &quot;implement ~리스너&quot;
메인 엑티비티에서 setOn~리스너(커스텀뷰)로 구현.

![](https://images.velog.io/images/continue_deve/post/ef7de9ab-230f-476e-9944-4224e915bea1/62.gif)

### 전체 코드
- MainActivity.java</code></pre><p>package ddwucom.mobile.chap7_prac2;</p>
<p>import androidx.appcompat.app.AppCompatActivity;</p>
<p>import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;</p>
<p>public class MainActivity extends AppCompatActivity {</p>
<pre><code>@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    MyView view = new MyView(this);
    view.setOnTouchListener(view);
    setContentView(view);
}

class MyView extends View implements View.OnTouchListener {
    public MyView(Context context) {
        super(context);
    }

    //        @Override
    protected void onDraw(Canvas canvas) {</code></pre><p>//            super.onDraw(canvas);
            canvas.drawColor(Color.YELLOW);
        }</p>
<pre><code>    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        Toast.makeText(MainActivity.this, &quot;유형3&quot;, Toast.LENGTH_SHORT).show();
        return false;
    }
}</code></pre><p>}
```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[안드로이드 인터페이스 기초 04 - 이벤트 (Event)]]></title>
            <link>https://velog.io/@continue_deve/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EA%B8%B0%EC%B4%88-04-%EC%9D%B4%EB%B2%A4%ED%8A%B8-Event</link>
            <guid>https://velog.io/@continue_deve/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EA%B8%B0%EC%B4%88-04-%EC%9D%B4%EB%B2%A4%ED%8A%B8-Event</guid>
            <pubDate>Fri, 06 Nov 2020 02:28:32 GMT</pubDate>
            <description><![CDATA[<p>Chap7. 인터페이스 기초04- 이벤트 (Event)</p>
<h2 id="event-driven-programming">Event-Driven Programming</h2>
<p>: 프로그램의 실행 흐름이 사용자 동작과 센서 입출력 등 외부 이벤트에 따라 결정되는 프로그래밍 방식.</p>
<p>; GUI프로그램에서 채택하였으며 대부분의 프로그래밍 방식으로 쓰임.
; 이벤트가 발생하면 앱의 Event Handler가 이를 전달 받아 이벤트를 처리함. ex.onClick()</p>
<h2 id="android-이벤트-처리-방식">Android 이벤트 처리 방식</h2>
<p>= Event Handler 구현 방식</p>
<h3 id="방식1-상속-메소드-재정의-이벤트-처리-메소드-재정의">방식1. 상속 메소드 재정의 (이벤트 처리 메소드 재정의)</h3>
<ul>
<li>Call-back 메소드 사용
: View의 대표적 이벤트 처리 메소드이다.</li>
</ul>
<pre><code>boolean onTouchEvent (MotionEvernt event)
boolean onKeyDown (int keyCode, keyEvent event)
boolean onKeyUp (int keyCode, KeyEvent event)
boolean onTrackballEvent (MotionEvent event)</code></pre><p>-- 개발자가 상속을 구현한 Custom View를 작성하였을 때만 사용 가능하다.
-- 이벤트에 대한 메소드가 전부 정의되어 있지 않다.
-- 앞에 on이 붙은 메소드는 대부분 콜백이다. 
(Ctrl+O - Select Method to Override/Implement 에서 찾아볼 수 있다.)</p>
<ul>
<li>View가 갖고 있는 기본 이벤트 처리 메소드를 상속받아 현재 사용하는 위젯 등에서 재정의</li>
</ul>
<p>ex. <a href="https://velog.io/@continue_deve/%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%B2%98%EB%A6%AC-%EB%A9%94%EC%86%8C%EB%93%9C-%EC%9E%AC%EC%A0%95%EC%9D%98-%EC%9C%84%EC%A0%AF-%EC%B2%98%EB%A6%AC-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83-%ED%84%B0%EC%B9%98ACTIONDOWN">(링크)</a>
<br></p>
<h3 id="방식2-listener-interface-구현-가장-기본">방식2. Listener Interface 구현 (가장 기본)</h3>
<p>: 이벤트 처리 Listener를 구현하여 이벤트 처리가 필요한 View에 등록하는 방법으로 가장 기본적인 UI 이벤트 처리 방법이다.</p>
<ul>
<li><p>모든 UI 이벤트에 대한 Interface가 준비되어 있다.
: 하나의 인터페이스 당 하나의 구현 메소드</p>
<pre><code>//인터페이스 : 구현 메소드
onTouchListener : boolean onTouch (View v , MotionEvent event)
onKeyListener : boolean onKey (View v, int keyCode, KeyEvent event)
onClickListener : void onClick (View v)
onLongClickListener : boolean onLongClick (View v)</code></pre><br>
</li>
<li><p>인터페이스 적용 방법</p>
</li>
</ul>
<ol>
<li>처리하고자 하는 UI 이벤트에 해당하는 Interface 구현</li>
<li>인터페이스 구현 클래스 작성</li>
<li>구현한 클래스에서 객체 생성</li>
<li>생성한 객체를 이벤트 처리가 필요한 View에 등록<br>
</li>
</ol>
<ul>
<li><p>Listener Interface 구현 유형
유형1. 별도의 리스너 인터페이스 구현 클래스 작성
유형2. Activity가 리스너 인터페이스 직접 구현
유형3. 뷰를 직접 작성할 경우 뷰에 리스너 인터페이스 구현
유형4. 익명 내부 클래스로 구현 
; 별도의 클래스 없이 인터페이스에서 직접 객체 생성
유형5. 익명 내부 클래스의 임시 객체로 구현
; 객체 이름 없이 인터페이스 구현 및 등록 <br>
ex. <a href="https://velog.io/@continue_deve/%EB%A6%AC%EC%8A%A4%EB%84%88-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EB%A5%BC-%EA%B5%AC%ED%98%84%ED%95%98%EC%97%AC-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%B2%98%EB%A6%AC-Listener-Interface">리스너 인터페이스를 구현하여 이벤트 처리 (Listener Interface)</a></p>
<br>
</li>
<li><p>Listener Interface 사용 시 명칭
: 명칭을 구성하는 규칙이 있어 이름을 통해 각 요소를 쉽게 유추 가능.</p>
</li>
</ul>
<p>ex.
처리하려는 UI 이벤트 명 : Click
구현할 인터페이스 명칭 : OnClickListener (대문자로 시작)
인터페이스 내부 구현 메소드 명 : onClick (소문자로 시작)
뷰의 인터페이스 등록 메소드 명칭 : View.setOnClickListener
<br></p>
<h3 id="방식3-위젯-이벤트-처리">방식3. 위젯 이벤트 처리</h3>
<p>: Click / Long Click과 같이 자주 사용하는 기본 이벤트 처리</p>
<p>; XML의 View 속성에 처리 메소드 명을 등록한 후 구현</p>
<p>ex.</p>
<ol>
<li>Click 이벤트 처리가 필요한 위젯 선택</li>
<li>design창의 Properties에서 onClick란에 메소드명 입력</li>
<li>해당 위젯이 속한 Activity에 멤버 메소드로 추가</li>
</ol>
<p>ex. <a href="https://velog.io/@continue_deve/%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%B2%98%EB%A6%AC-%EB%A9%94%EC%86%8C%EB%93%9C-%EC%9E%AC%EC%A0%95%EC%9D%98-%EC%9C%84%EC%A0%AF-%EC%B2%98%EB%A6%AC-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83-%ED%84%B0%EC%B9%98ACTIONDOWN">(링크)</a></p>
<br>

<h3 id="이벤트-핸들러의-우선-순위">이벤트 핸들러의 우선 순위</h3>
<p>하나의 이벤트에 대하여 여러 이벤트 리스너를 작성할 경우의 우선 순위</p>
<p>경우1. 구현한 이벤트 리스너가 있을 경우 우선 수행</p>
<p>경우2. 뷰 자체의 콜백 메소드를 구현하였을 경우 우선 수행 (커스텀 뷰)</p>
<p>경우3. 액티비티에 콜백 메소드를 구현하였을 경우 우선 수행
<br></p>
<p>+) 이벤트 리스너의 반환값 설정
true 반환 : 추가적인 이벤트 처리 진행을 생략
false 반환 : 이벤트 처리를 다음 순위의 리스너에게 이벤트 진행
<br></p>
<h2 id="외부-변수의-접근">외부 변수의 접근</h2>
<p>문제점 : 이벤트 핸들러는 이벤트 발생 시점에 실행되어 외부의 지역 변수 사용 시 접근범위 문제가 발생할 수 있다.</p>
<p>해결책1 : 멤버 변수로 선언한다.</p>
<ul>
<li>내부에서의 접근 위치/시점의 제한이 없어짐.</li>
<li>하지만 멤버변수가 너무 많아지지 않도록 주의해야함.</li>
</ul>
<p>해결책2 : 상수로 선언한다.</p>
<ul>
<li>상수가 앱을 종료할 때까지 유지된다.</li>
<li>멤버 변수로 선언할 필요가 없을 경우 적용할 수 있다.\<br>

</li>
</ul>
<h2 id="여러-가지-이벤트">여러 가지 이벤트</h2>
<ul>
<li><p>터치 입력
: 버튼 클릭 이외에 뷰를 터치하는 이벤트 처리
= ACTION_DOWN(화면터치), ACTION_MOVE(터치한 상태로 움직임), ACTION_UP(손가락을 뗌)
ex. <a href="https://velog.io/@continue_deve/%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%B2%98%EB%A6%AC-%EB%A9%94%EC%86%8C%EB%93%9C-%EC%9E%AC%EC%A0%95%EC%9D%98-%EC%9C%84%EC%A0%AF-%EC%B2%98%EB%A6%AC-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83-%ED%84%B0%EC%B9%98ACTIONDOWN">(링크)</a></p>
</li>
<li><p>키보드 입력
: 모바일 장비의 가상 키보드 입력 처리
; KEYCODE 값으로 입력할 키의 종류 구별
= ACTION_DOWN, ACTION_UP, ACTION_MULTIPLE</p>
</li>
<li><p>롱클릭 (롱탭)
: 뷰를 일정 시간 동안 클릭하고 있을 때 발생하는 이벤트
; 클릭과 같이 쓰는 경우 false로 처리할 것</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[버튼을 누르면 화면에 원이 그려지는 앱 - Random클래스 사용]]></title>
            <link>https://velog.io/@continue_deve/%EB%B2%84%ED%8A%BC%EC%9D%84-%EB%88%84%EB%A5%B4%EB%A9%B4-%ED%99%94%EB%A9%B4%EC%97%90-%EC%9B%90%EC%9D%B4-%EA%B7%B8%EB%A0%A4%EC%A7%80%EB%8A%94-%EC%95%B1-Random%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%82%AC%EC%9A%A9</link>
            <guid>https://velog.io/@continue_deve/%EB%B2%84%ED%8A%BC%EC%9D%84-%EB%88%84%EB%A5%B4%EB%A9%B4-%ED%99%94%EB%A9%B4%EC%97%90-%EC%9B%90%EC%9D%B4-%EA%B7%B8%EB%A0%A4%EC%A7%80%EB%8A%94-%EC%95%B1-Random%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%82%AC%EC%9A%A9</guid>
            <pubDate>Thu, 05 Nov 2020 15:49:52 GMT</pubDate>
            <description><![CDATA[<p>Chap6. 인터페이스 기초03 - Custom View, Toast, Beep, Vibration, etc
패키지명 : CustomViewTest</p>
<ul>
<li>해야할 것</li>
</ul>
<ol>
<li>초기상태에는 빈화면, 버튼을 누르면 원이 그려짐</li>
<li>Random 클래스를 사용할 것</li>
<li>CustomView를 XML 레이아웃에 배치할 것</li>
</ol>
<h3 id="1-초기상태에는-빈화면-버튼을-누르면-원이-그려짐">1. 초기상태에는 빈화면, 버튼을 누르면 원이 그려짐</h3>
<p>버튼을 누르면 x좌표 100, y좌표 100, 반지름 80의 cyan색상의 원이 표시됨.</p>
<pre><code>//MainActivity
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        MyView myView = findViewById(R.id.myView);
}

public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                myView.setCircleX(100);
                myView.setCircleY(100);
                myView.setCircleR(80);
                myView.invalidate();
                break;
        }
}

//myView
public class MyView extends View {

    int x, y ,r;

    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void setCircleX(int x) { this.x = x; }

    public void setCircleY(int y) { this.y = y; }

    public int getCircleX() { return x; }

    public int getCircleY() { return y; }

    public void setCircleR(int r) { this.r = r; }

    public int getCircleR() { return r; }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.YELLOW);

        Paint pnt = new Paint();
        pnt.setColor(Color.CYAN);

        canvas.drawCircle(getCircleX(), getCircleY(), getCircleR(), pnt);
    }
}</code></pre><ul>
<li>실행 결과
<img src="https://images.velog.io/images/continue_deve/post/2a00e1ce-c4f9-4dc2-baaa-0769716edd1f/60.gif" alt=""><br>

</li>
</ul>
<h3 id="2-random-클래스를-사용할-것">2. Random 클래스를 사용할 것</h3>
<p>x, y, r값을 random 지정</p>
<ul>
<li>Random 클래스<pre><code>Random random = new Random();
</code></pre></li>
</ul>
<p>//정수 범위 0<del>500, 0</del>800
int x = random.nextInt(500);
int y = random.nettInt(800);</p>
<p>//정수 범위 0~3
int r = (random.nextInt(3)+1) * 100;</p>
<pre><code></code></pre><p>//MainActivity
@Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        int width = myView.getWidth();
        int height = myView.getHeight();
    }</p>
<pre><code>public void onClick(View v) {
    Random random = new Random();
    switch (v.getId()) {
        case R.id.button:
            myView.setCircleX(random.nextInt(width));
            myView.setCircleY(random.nextInt(height));
            myView.setCircleR((random.nextInt(3) + 1) * 100);
            myView.invalidate();
            break;
    }
}</code></pre><pre><code>//random.nextInt(view의 사이즈)이므로 myView의 width와 height를 구해 상수화하여 대입하였다.

- 실행 결과
![](https://images.velog.io/images/continue_deve/post/04061323-a2cc-4ea1-b88c-c59ee62ffa6d/61.gif)
&lt;br&gt;

### 3. CustomView를 XML 레이아웃에 배치할 것</code></pre><p>&lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=&quot;<a href="http://schemas.android.com/apk/res/android&quot;">http://schemas.android.com/apk/res/android&quot;</a>
    xmlns:app=&quot;<a href="http://schemas.android.com/apk/res-auto&quot;">http://schemas.android.com/apk/res-auto&quot;</a>
    xmlns:tools=&quot;<a href="http://schemas.android.com/tools&quot;">http://schemas.android.com/tools&quot;</a>
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    tools:context=&quot;.MainActivity&quot;&gt;</p>
<pre><code>...

&lt;ddwucom.mobile.test05.MyView
    android:id=&quot;@+id/myView&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;0dp&quot;
    android:layout_marginStart=&quot;16dp&quot;
    android:layout_marginLeft=&quot;16dp&quot;
    android:layout_marginTop=&quot;16dp&quot;
    android:layout_marginEnd=&quot;16dp&quot;
    android:layout_marginRight=&quot;16dp&quot;
    android:layout_marginBottom=&quot;16dp&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/button&quot; /&gt;</code></pre><p>&lt;/androidx.constraintlayout.widget.ConstraintLayout&gt;</p>
<pre><code>&lt;br&gt;

### 전체코드
- MainActivity.java</code></pre><p>package ddwucom.mobile.test05;</p>
<p>import androidx.appcompat.app.AppCompatActivity;</p>
<p>import android.os.Bundle;
import android.util.Log;
import android.view.View;</p>
<p>import java.util.Random;</p>
<p>public class MainActivity extends AppCompatActivity {</p>
<pre><code>Random random = new Random();
private MyView myView;
int width, height;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    myView = findViewById(R.id.myView);
}

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    width = myView.getWidth();
    height = myView.getHeight();
}

public void onClick(View v) {

    switch (v.getId()) {
        case R.id.button:
            myView.setCircleX(random.nextInt(width));
            myView.setCircleY(random.nextInt(height));
            myView.setCircleR((random.nextInt(3) + 1) * 100);
            myView.invalidate();
            break;
    }
}</code></pre><p>}</p>
<pre><code>
- MyView.java</code></pre><p>package ddwucom.mobile.test05;</p>
<p>import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;</p>
<p>import androidx.annotation.Nullable;</p>
<p>import java.util.Random;</p>
<p>public class MyView extends View {</p>
<pre><code>int x, y ,r;

public MyView(Context context) {
    super(context);
}

public MyView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
}

public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

public void setCircleX(int x) { this.x = x; }

public void setCircleY(int y) { this.y = y; }

public int getCircleX() { return x; }

public int getCircleY() { return y; }

public void setCircleR(int r) { this.r = r; }

public int getCircleR() { return r; }

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawColor(Color.YELLOW);

    Paint pnt = new Paint();
    pnt.setColor(Color.CYAN);

    canvas.drawCircle(getCircleX(), getCircleY(), getCircleR(), pnt);
}</code></pre><p>}</p>
<pre><code>
- activity_main.xml</code></pre><?xml version="1.0" encoding="utf-8"?>
<p>&lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=&quot;<a href="http://schemas.android.com/apk/res/android&quot;">http://schemas.android.com/apk/res/android&quot;</a>
    xmlns:app=&quot;<a href="http://schemas.android.com/apk/res-auto&quot;">http://schemas.android.com/apk/res-auto&quot;</a>
    xmlns:tools=&quot;<a href="http://schemas.android.com/tools&quot;">http://schemas.android.com/tools&quot;</a>
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    tools:context=&quot;.MainActivity&quot;&gt;</p>
<pre><code>&lt;Button
    android:id=&quot;@+id/button&quot;
    android:layout_width=&quot;0dp&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:layout_marginStart=&quot;16dp&quot;
    android:layout_marginLeft=&quot;16dp&quot;
    android:layout_marginTop=&quot;16dp&quot;
    android:layout_marginEnd=&quot;16dp&quot;
    android:layout_marginRight=&quot;16dp&quot;
    android:onClick=&quot;onClick&quot;
    android:text=&quot;@string/btn_name&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toTopOf=&quot;parent&quot; /&gt;

&lt;ddwucom.mobile.test05.MyView
    android:id=&quot;@+id/myView&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;0dp&quot;
    android:layout_marginStart=&quot;16dp&quot;
    android:layout_marginLeft=&quot;16dp&quot;
    android:layout_marginTop=&quot;16dp&quot;
    android:layout_marginEnd=&quot;16dp&quot;
    android:layout_marginRight=&quot;16dp&quot;
    android:layout_marginBottom=&quot;16dp&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/button&quot; /&gt;</code></pre><p>&lt;/androidx.constraintlayout.widget.ConstraintLayout&gt;</p>
<pre><code>
- strings.xml</code></pre><resources>
    <string name="app_name">CustomViewTest</string>
    <string name="btn_name">CIRCLE DRAW</string>
</resources>

<pre><code></code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Toast, Sound, Vibration 실행 앱]]></title>
            <link>https://velog.io/@continue_deve/Toast-Sound-Vibration-%EC%8B%A4%ED%96%89-%EC%95%B1</link>
            <guid>https://velog.io/@continue_deve/Toast-Sound-Vibration-%EC%8B%A4%ED%96%89-%EC%95%B1</guid>
            <pubDate>Thu, 05 Nov 2020 15:13:43 GMT</pubDate>
            <description><![CDATA[<p>Chap6. 인터페이스 기초03 - Custom View, Toast, Beep, Vibration, etc
패키지명 : Exam01</p>
<ul>
<li>해야할 것</li>
</ul>
<ol>
<li>btnToast를 누르면 자신의 이름을 토스트로 출력</li>
<li>btnSound를 누르면 dingdong 사운드 출력</li>
<li>btnVibration을 누르면 1초간 진동</li>
</ol>
<h3 id="1-btntoast를-누르면-자신의-이름을-토스트로-출력">1. btnToast를 누르면 자신의 이름을 토스트로 출력</h3>
<pre><code>//onClick 메소드
case R.id.btnToast:
    Toast.makeText(this, &quot;SEIN&quot;, Toast.LENGTH_SHORT).show();
    break;</code></pre><h3 id="2-btnsound를-누르면-dingdong-사운드-출력">2. btnSound를 누르면 dingdong 사운드 출력</h3>
<pre><code>//onClick 메소드
case R.id.btnSound:
    SoundPool soundPool = new SoundPool(1, STREAM_MUSIC, 0);
    int sound = soundPool.load(this, R.raw.dingdong, 1);
    soundPool.play(sound, 1, 1, 0, 0, 1);
    break;</code></pre><h3 id="3-btnvibration을-누르면-1초간-진동">3. btnVibration을 누르면 1초간 진동</h3>
<pre><code>//onClick 메소드
case R.id.btnVibration:
    Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
    vibrator.vibrate(1000);
    break;</code></pre><p>심화) 다양한 진동 패턴으로 변경시켜 볼 것</p>
<pre><code>//onClick 메소드
case R.id.btnVibration:
    Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
    vibrator.vibrate(new long[] {100, 50, 200, 50}, 0);
    break;</code></pre><p>//짝수 인덱스 = 대기시간, 홀수 인덱스 = 진동 시간
//Manifest에 퍼미션 부여 잊지 말기</p>
<pre><code>&lt;uses-permission android:name=&quot;android.permission.VIBRATE&quot; /&gt;</code></pre><br>

<h3 id="전체-코드">전체 코드</h3>
<ul>
<li>MainActivity.java<pre><code>package ddwucom.mobile.test05;
</code></pre></li>
</ul>
<p>import androidx.appcompat.app.AppCompatActivity;</p>
<p>import android.content.Context;
import android.media.SoundPool;
import android.os.Bundle;
import android.os.Vibrator;
import android.view.View;
import android.widget.Toast;</p>
<p>import static android.media.AudioManager.STREAM_MUSIC;</p>
<p>public class MainActivity extends AppCompatActivity {</p>
<pre><code>SoundPool soundPool;
int sound;
Vibrator vibrator;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    soundPool = new SoundPool(1, STREAM_MUSIC, 0);
    sound = soundPool.load(this, R.raw.dingdong, 1);

    vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
}

public void onClick(View v) {
    switch (v.getId()) {
        case R.id.btnToast:
            Toast.makeText(this, &quot;SEIN&quot;, Toast.LENGTH_SHORT).show();
            break;
        case R.id.btnSound:
            soundPool.play(sound, 1, 1, 0, 0, 1);
            break;
        case R.id.btnVibration:
            vibrator.vibrate(1000);
            vibrator.vibrate(new long[] {100, 50, 200, 50}, 0);
            break;
    }
}</code></pre><p>}</p>
<pre><code>
-activity_main.xml</code></pre><?xml version="1.0" encoding="utf-8"?>
<p><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"></p>
<pre><code>&lt;Button
    android:id=&quot;@+id/btnToast&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:onClick=&quot;onClick&quot;
    android:text=&quot;TOAST&quot; /&gt;

&lt;Button
    android:id=&quot;@+id/btnSound&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:onClick=&quot;onClick&quot;
    android:text=&quot;SOUND&quot; /&gt;

&lt;Button
    android:id=&quot;@+id/btnVibration&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:onClick=&quot;onClick&quot;
    android:text=&quot;VIBRATION&quot; /&gt;</code></pre></LinearLayout>
```

<ul>
<li><p>AndroidManifest.xml</p>
<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
  package=&quot;ddwucom.mobile.test05&quot;&gt;

  &lt;uses-permission android:name=&quot;android.permission.VIBRATE&quot; /&gt;

  &lt;application
      android:allowBackup=&quot;true&quot;
      android:icon=&quot;@mipmap/ic_launcher&quot;
      android:label=&quot;@string/app_name&quot;
      android:roundIcon=&quot;@mipmap/ic_launcher_round&quot;
      android:supportsRtl=&quot;true&quot;
      android:theme=&quot;@style/AppTheme&quot;&gt;
      &lt;activity android:name=&quot;.MainActivity&quot;&gt;
          &lt;intent-filter&gt;
              &lt;action android:name=&quot;android.intent.action.MAIN&quot; /&gt;

              &lt;category android:name=&quot;android.intent.category.LAUNCHER&quot; /&gt;
          &lt;/intent-filter&gt;
      &lt;/activity&gt;
  &lt;/application&gt;
</code></pre></li>
</ul>
</manifest>
```

<p><img src="https://images.velog.io/images/continue_deve/post/a76ff94c-ce92-4f14-a8ae-3df895fd9c52/59.PNG" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CustomView를 XML 레이아웃에 선언하기]]></title>
            <link>https://velog.io/@continue_deve/CustomView%EB%A5%BC-XML-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83%EC%97%90-%EC%84%A0%EC%96%B8%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@continue_deve/CustomView%EB%A5%BC-XML-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83%EC%97%90-%EC%84%A0%EC%96%B8%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 05 Nov 2020 15:11:13 GMT</pubDate>
            <description><![CDATA[<p>Chap6. 인터페이스 기초03 - Custom View, Toast, Beep, Vibration, etc
패키지명 :chap6_prac2</p>
<h3 id="전체-코드">전체 코드</h3>
<ul>
<li><p>MainActivity.java
생성 후 수정 사항 없음.</p>
</li>
<li><p>MyView.java</p>
<pre><code>package ddwucom.mobile.chap6_prac2;
</code></pre></li>
</ul>
<p>import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.View;</p>
<p>import androidx.annotation.Nullable;</p>
<p>public class MyView extends View {
    public MyView(Context context) {
        super(context);
    }</p>
<pre><code>public MyView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); }

public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawColor(Color.YELLOW);
}</code></pre><p>}</p>
<pre><code>
- activity_main.xml</code></pre><?xml version="1.0" encoding="utf-8"?>
<p>&lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=&quot;<a href="http://schemas.android.com/apk/res/android&quot;">http://schemas.android.com/apk/res/android&quot;</a>
    xmlns:app=&quot;<a href="http://schemas.android.com/apk/res-auto&quot;">http://schemas.android.com/apk/res-auto&quot;</a>
    xmlns:tools=&quot;<a href="http://schemas.android.com/tools&quot;">http://schemas.android.com/tools&quot;</a>
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    tools:context=&quot;.MainActivity&quot;&gt;</p>
<pre><code>&lt;ddwucom.mobile.chap6_prac2.MyView
    android:id=&quot;@+id/myView&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot; /&gt;

&lt;/androidx.constraintlayout.widget.ConstraintLayout&gt;</code></pre><p>```
//반드시 Full Package를 포함한 클래스 명으로 기록하여야 한다.
ddwucom.mobile.chap6_prac2.MyView &lt;- 이 부분</p>
<p>//커스텀뷰가 레이아웃의 내부에 선언되어야 한다.</p>
<p><img src="https://images.velog.io/images/continue_deve/post/223d5bfc-c277-4b16-be72-536cbef7a13a/58.PNG" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[MainActivity의 내부클래스로 CustomView 선언하기]]></title>
            <link>https://velog.io/@continue_deve/MainActivity%EC%9D%98-%EB%82%B4%EB%B6%80%ED%81%B4%EB%9E%98%EC%8A%A4%EB%A1%9C-CustomView-%EC%84%A0%EC%96%B8%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@continue_deve/MainActivity%EC%9D%98-%EB%82%B4%EB%B6%80%ED%81%B4%EB%9E%98%EC%8A%A4%EB%A1%9C-CustomView-%EC%84%A0%EC%96%B8%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 05 Nov 2020 15:03:52 GMT</pubDate>
            <description><![CDATA[<p>Chap6. 인터페이스 기초03 - Custom View, Toast, Beep, Vibration, etc
패키지명 :chap6_prac</p>
<h3 id="전체코드">전체코드</h3>
<ul>
<li>MainActivity.java<pre><code>package ddwucom.mobile.chap6_prac;
</code></pre></li>
</ul>
<p>import androidx.appcompat.app.AppCompatActivity;</p>
<p>import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;</p>
<p>public class MainActivity extends AppCompatActivity {</p>
<pre><code>@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    MyView vw = new MyView(this);   //내부(아래)에 선언한 MyView 객체 생성
    setContentView(vw);
}

class MyView extends View {
    public MyView(Context context) {
        super(context);
    }

    public void onDraw(Canvas canvas) {
        canvas.drawColor(Color.LTGRAY);

        Paint pnt = new Paint();
        pnt.setColor(Color.BLUE);

        canvas.drawCircle(100,100,80,pnt);
    }
}</code></pre><p>}</p>
<p>```</p>
<p><img src="https://images.velog.io/images/continue_deve/post/715671f2-7fd5-4bed-b5e4-0154c27cdf75/57.PNG" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[안드로이드 인터페이스 기초 03 - Custom View, Toast, Beep, Vibration, etc]]></title>
            <link>https://velog.io/@continue_deve/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EA%B8%B0%EC%B4%88-03-Custom-View-Toast-Beep-Vibration-etc</link>
            <guid>https://velog.io/@continue_deve/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EA%B8%B0%EC%B4%88-03-Custom-View-Toast-Beep-Vibration-etc</guid>
            <pubDate>Thu, 05 Nov 2020 14:57:12 GMT</pubDate>
            <description><![CDATA[<p>Chap6. 인터페이스 기초03 - Custom View, Toast, Beep, Vibration, etc</p>
<h2 id="custom-view">Custom View</h2>
<p>: 미리 만들어 놓은 뷰가 아닌 개발자가 직접 모양 및 기능등을 정의하여 만든 뷰.</p>
<ul>
<li>View클래스를 상속받아 필요한 메소드를 재정의하여 사용해야 한다. (오버라이딩 Overriding)
: XML에서 직접 작성한 View를 사용하기 위해서는 View의 생성자를 모두 재정의해야 한다.</li>
</ul>
<p>ex.</p>
<pre><code>class MyView extends View {
    public MyView(Context context) {
            super(context);
        } //기본 생성자

        public MyView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        public Myview(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
        ...
}</code></pre><p>ex1. MainActivity의 내부클래스로 MyView(CustomView)선언하기
<a href="https://velog.io/@continue_deve/MainActivity%EC%9D%98-%EB%82%B4%EB%B6%80%ED%81%B4%EB%9E%98%EC%8A%A4%EB%A1%9C-CustomView-%EC%84%A0%EC%96%B8%ED%95%98%EA%B8%B0">(링크)</a>
ex2. CustomView를 XML 레이아웃에 선언하기
<a href="https://velog.io/@continue_deve/CustomView%EB%A5%BC-XML-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83%EC%97%90-%EC%84%A0%EC%96%B8%ED%95%98%EA%B8%B0">(링크)</a>
<br></p>
<h2 id="custom-view-사용시-그리기-절차">Custom View 사용시 그리기 절차</h2>
<ol>
<li>CustomView를 생성하여 View 클래스 상속 후 생성자, onDraw() 재정의</li>
<li>onDraw()에 그릴 내용 지정 - Paint 객체 준비 등 (그리기 도구 준비)</li>
<li>Canvas 객체의 메소드 이용 (그릴 공간 준비)</li>
<li>다시 그릴 땐 customView.invalidate()호출</li>
</ol>
<h3 id="canvas-클래스">Canvas 클래스</h3>
<p>: 그림을 그리는 영역을 담당하는 클래스</p>
<p>; 시스템에서 제공되는 클래스임.
; View 클래스의 onDraw() 메소드의 매개변수로 전달됨. (전달받은 Canvas 객체를 수정하여 그려지는 모양이 변경된다)</p>
<ul>
<li>기본 도형 출력 방법
: Canvas의 멤버 메소드 호출로 기본 도형을 출력할 수 있고, 오버로딩 되어 있으므로 매개변수 확인이 필요하다.</li>
</ul>
<pre><code>// 점 그리기
void drawPoint (float x, float y, Paint paint)

// 선 그리기
void drawLine (float startX, float startY, float stopX, float stopY, Paint paint)

// 원 그리기
void drawCircle (float cx, float cy, float radius, Paint paint)

// 사각형 그리기
void drawRect (float left, float top, float right, float bottom, Paint paint)

// 텍스트 그리기
void drawText (String text, float x, float y, Paint paint)</code></pre><br>

<h3 id="paint">Paint</h3>
<p>: Canvas에 그림을 그리기 위해 사용하는 펜 역할로 그리기에 대한 속성 정보를 지정한다.</p>
<ul>
<li><p>선 경계 부드럽게 출력하기</p>
<pre><code>paint.setAntiAlias(true);
또는
new Paint(Paint.ANTI_ALIAS_FLAG)</code></pre></li>
<li><p>색상 변경하기</p>
<ul>
<li>투명도 지정 : paint.setARGB(int a, int r, int g, int b);</li>
<li>색상 지정 : paint.setColor(Color.RED);</li>
</ul>
</li>
</ul>
<br>

<h2 id="사운드-출력">사운드 출력</h2>
<h3 id="soundpool">SoundPool</h3>
<p>: 짧은 소리 출력용 (효과음 같은)</p>
<p>; res폴더에 raw폴더 생성 후 sound파일을 복사하여 준비 후 아래코드 실행</p>
<pre><code>SoundPool soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
int sound = soundPool.load(this, R.raw.dingdong, 1);
soundPool.play(sound, 1, 1, 0, 0, 1);</code></pre><p>//new SoundPool(maxStreams, STREAM_MUSIC, srcQuality)
//load(context, sound파일주소, priority)
//play(sound, leftVolume, rightVolume, priority, loop, rate)
<br></p>
<h2 id="진동-기능-사용">진동 기능 사용</h2>
<p>: 시스템 서비스로부터 Vibrator 객체를 획득하여 진동을 발생 시킨다.</p>
<pre><code>Vibrator vibrator = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(1000); //1초 진동
//또는 vibrator.vibrate(new long[] {100, 50, 200, 50}, 0);
vibrator.cancel();</code></pre><p>//vibrate(milliseconds)
//vibrate(new long[] {100, 50, 200, 50}, repeat)</p>
<p>+) AndroidManifest.xml에 permission을 추가해야 한다.</p>
<pre><code>&lt;uses-permission android:name=&quot;android.permission.VIBRATE&quot; /&gt;</code></pre><br>

<h2 id="퍼미션-permission">퍼미션 (Permission)</h2>
<p>: 기기의 특정 기능을 사용하기 위해 앱이 받는 허가.</p>
<p>; 퍼미션을 받지 않은 상태에서 앱이 특정 기능을 사용할 경우 예외 발생.</p>
<h3 id="정책">정책</h3>
<ul>
<li>보안 위험에 따라 퍼미션 종류를 그룹으로 분류함.</li>
<li>중요한 퍼미션은 실행 중 퍼미션 사용 여부를 사용자가 결정함.</li>
</ul>
<h3 id="실행-중-퍼미션-확인-및-추가">실행 중 퍼미션 확인 및 추가</h3>
<ol>
<li><p>필요한 퍼미션을 AndroidManifest에 추가
ex. 네트워크 퍼미션을 추가한다고 했을 때
ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION</p>
<br>
</li>
<li><p>퍼미션 필요 위치에서의 퍼미션 확인</p>
<pre><code>if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) 
     != PackageManager.PERMISSION_GRANTED 
     &amp;&amp; ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) 
     != PackageManager.PERMISSION_GRANTED) {
 ActivityCompat.requestPermissions(this, 
     new String[] {Manifest.permission.ACCESS_FINE_LOCATIONS,
     Manifest.permission.ACCESS_COARSE_LOCATION},
     MY_PERMISSION_REQUEST_ACCESS_LOCATION);
 return;
}</code></pre><p>// if(조건) { 수행 }</p>
</li>
</ol>
<ul>
<li><p>Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION
: 확인 대상 퍼미션</p>
</li>
<li><p>ActivityCompat.requestPermissions(...);
: 퍼미션 확인 요청</p>
</li>
<li><p>MY_PERMISSION_REQUEST_ACCESS_LOCATION);
: 퍼미션 요청 식별 코드 (상수로 선언)</p>
</li>
</ul>
<br>

<ol start="3">
<li>퍼미션 결과 확인<pre><code>@Override
public void onRequestPermissionResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch(requestCode) {
     case MY_PERMISSION_REQUEST_ACCESS_LOCATIONS:
             if(grantResults.length &gt; 0
         &amp;&amp; grantResults[0] == PackageManager.PERMISSION_GRANTED
         &amp;&amp; grantResults[1] == PackageManager.PERMISSION_GRANTED) {
        Toast.makeText(this, &quot;Permission was granted!!!&quot;, Toast.LENGTH_SHORT).show();
     }
     else {
        Toast.makeText(this, &quot;Permission was denied!!!&quot;, Toast.LENGTH_SHORT).show();
     }
     return;
 }
}</code></pre></li>
</ol>
<p>사용자의 퍼미션 설정 정보는 내부에 저장되어 유지된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[1,2 더하기 계산기]]></title>
            <link>https://velog.io/@continue_deve/12-%EB%8D%94%ED%95%98%EA%B8%B0-%EA%B3%84%EC%82%B0%EA%B8%B0</link>
            <guid>https://velog.io/@continue_deve/12-%EB%8D%94%ED%95%98%EA%B8%B0-%EA%B3%84%EC%82%B0%EA%B8%B0</guid>
            <pubDate>Thu, 05 Nov 2020 09:32:00 GMT</pubDate>
            <description><![CDATA[<p>Chap5. 인터페이스 기초02 - 레이아웃(Layout)
패키지명 : CalculatorSample</p>
<ul>
<li>해야할 것</li>
</ul>
<ol>
<li>LinearLayout만 사용</li>
<li>모든 버튼이 하나의 메소드를 공유하여 사용 (switch문)</li>
<li>editText의 id는 etDisplay이고, 숫자를 오른쪽 정렬할 것</li>
<li>숫자 버튼을 누르면 EditText에 출력</li>
<li>+버튼을 누르면 EditText에 입력한 값을 int변수에 저장하고 EditText를 지운다</li>
<li>두번째 숫자를 입력하고 =버튼을 누르면 두번째 입력한 값을 int변수에 저장하여 먼저 입력한 값과 합한 후 EditText에 출력한다.</li>
</ol>
<h3 id="1-linearlayout만-사용">1. LinearLayout만 사용</h3>
<p>(생략)</p>
<h3 id="2-모든-버튼이-하나의-메소드를-공유하여-사용-switch문">2. 모든 버튼이 하나의 메소드를 공유하여 사용 (switch문)</h3>
<pre><code>public void onClick (View v) {
        String num = editText.getText().toString();

        switch (v.getId()) {
            case R.id.bnt_1:
                num += &quot;1&quot;;
                editText.setText(num);
                break;

            case R.id.btn_2:
                num += &quot;2&quot;;
                editText.setText(num);
                break;

            case R.id.btn_plus:
                no1 = Integer.parseInt(num);
                num = &quot;&quot;;
                editText.setText(num);
                break;

            case R.id.btn_equal:
                no2 = Integer.parseInt(num);
                int rslt = no1 + no2;
                String strRslt = Integer.toString(rslt);
                editText.setText(strRslt);
                break;
        }
    }</code></pre><h3 id="3-edittext의-id는-etdisplay이고-숫자를-오른쪽-정렬할-것">3. editText의 id는 etDisplay이고, 숫자를 오른쪽 정렬할 것 <img src="https://images.velog.io/images/continue_deve/post/8d7bed71-ced3-4779-9d24-df88d9f51a8b/55.PNG" alt=""></h3>
<p>숫자를 입력했을 때 오른쪽 정렬이 되도록 하려면 gravity를 right로 설정해주면 된다.</p>
<h3 id="4-숫자-버튼을-누르면-edittext에-출력">4. 숫자 버튼을 누르면 EditText에 출력</h3>
<p>숫자 버튼을 누를 때마다 앞의 숫자에 계속 붙여서 출력할 것</p>
<pre><code>       case R.id.bnt_1:
                num += &quot;1&quot;;
                editText.setText(num);
                break;

            case R.id.btn_2:
                num += &quot;2&quot;;
                editText.setText(num);
                break;</code></pre><p>이처럼 num에 <strong>+=</strong> 를 해주면 된다.</p>
<h3 id="5-버튼을-누르면-edittext에-입력한-값을-int변수에-저장하고-edittext를-지운다">5. +버튼을 누르면 EditText에 입력한 값을 int변수에 저장하고 EditText를 지운다</h3>
<p>String의 int변환 필요 -&gt; Integer.parseInt(문자열)</p>
<p>ex. 
String num1 = &quot;456&quot;;
int no1 = Integer.parseInt(num1);</p>
<pre><code>    case R.id.btn_plus:
                no1 = Integer.parseInt(num);
                num = &quot;&quot;;
                editText.setText(num);
                break;</code></pre><p>int no1에 첫번째 입력값을 String에서 추출하여 저장하고 num에는 공백문자열을 넣어 EditText를 비운다.</p>
<h3 id="6-두번째-숫자를-입력하고-버튼을-누르면-두번째-입력한-값을-int변수에-저장하여-먼저-입력한-값과-합한-후-edittext에-출력한다">6. 두번째 숫자를 입력하고 =버튼을 누르면 두번째 입력한 값을 int변수에 저장하여 먼저 입력한 값과 합한 후 EditText에 출력한다.</h3>
<p>=버튼을 누르기 전에 num에 있는 값을 두번째 값으로 생각하고 no2에 넣는다.</p>
<pre><code>    case R.id.btn_equal:
                no2 = Integer.parseInt(num);
                int rslt = no1 + no2;
                String strRslt = Integer.toString(rslt);
                editText.setText(strRslt);
                break;</code></pre><ul>
<li>실행 결과
<img src="https://images.velog.io/images/continue_deve/post/6f135d60-a6a2-4db2-aa14-4ce091653b71/56.gif" alt=""></li>
</ul>
<h3 id="전체-코드">전체 코드</h3>
<ul>
<li>MainActivity.java<pre><code>package ddwucom.mobile.test04;
</code></pre></li>
</ul>
<p>import androidx.appcompat.app.AppCompatActivity;</p>
<p>import android.os.Bundle;
import android.view.View;
import android.widget.EditText;</p>
<p>public class MainActivity extends AppCompatActivity {</p>
<pre><code>final static String TAG = &quot;MainActivity&quot;;

int no1, no2;
EditText editText;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    editText = (EditText) findViewById(R.id.etDisplay);
}

public void onClick (View v) {
    String num = editText.getText().toString();

    switch (v.getId()) {
        case R.id.bnt_1:
            num += &quot;1&quot;;
            editText.setText(num);
            break;

        case R.id.btn_2:
            num += &quot;2&quot;;
            editText.setText(num);
            break;

        case R.id.btn_plus:
            no1 = Integer.parseInt(num);
            num = &quot;&quot;;
            editText.setText(num);
            break;

        case R.id.btn_equal:
            no2 = Integer.parseInt(num);
            int rslt = no1 + no2;
            String strRslt = Integer.toString(rslt);
            editText.setText(strRslt);
            break;
    }
}</code></pre><p>}</p>
<pre><code>
- activity_maim.xml</code></pre><?xml version="1.0" encoding="utf-8"?>
<p><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"></p>
<pre><code>&lt;EditText
    android:id=&quot;@+id/etDisplay&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:ems=&quot;10&quot;
    android:gravity=&quot;right&quot;
    android:inputType=&quot;number&quot; /&gt;

&lt;LinearLayout
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;60dp&quot;
    android:orientation=&quot;horizontal&quot;&gt;

    &lt;Button
        android:id=&quot;@+id/bnt_1&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;match_parent&quot;
        android:layout_weight=&quot;1&quot;
        android:onClick=&quot;onClick&quot;
        android:text=&quot;1&quot; /&gt;

    &lt;Button
        android:id=&quot;@+id/btn_2&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;match_parent&quot;
        android:layout_weight=&quot;1&quot;
        android:onClick=&quot;onClick&quot;
        android:text=&quot;2&quot; /&gt;

    &lt;Button
        android:id=&quot;@+id/btn_plus&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;match_parent&quot;
        android:layout_weight=&quot;1&quot;
        android:onClick=&quot;onClick&quot;
        android:text=&quot;+&quot; /&gt;

    &lt;Button
        android:id=&quot;@+id/btn_equal&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;match_parent&quot;
        android:layout_weight=&quot;1&quot;
        android:onClick=&quot;onClick&quot;
        android:text=&quot;=&quot; /&gt;
&lt;/LinearLayout&gt;</code></pre></LinearLayout>
```

]]></description>
        </item>
        <item>
            <title><![CDATA[버튼을 눌러 LinearLayout의 orientation 바꾸기]]></title>
            <link>https://velog.io/@continue_deve/%EB%B2%84%ED%8A%BC%EC%9D%84-%EB%88%8C%EB%9F%AC-LinearLayout%EC%9D%98-orientation-%EB%B0%94%EA%BE%B8%EA%B8%B0</link>
            <guid>https://velog.io/@continue_deve/%EB%B2%84%ED%8A%BC%EC%9D%84-%EB%88%8C%EB%9F%AC-LinearLayout%EC%9D%98-orientation-%EB%B0%94%EA%BE%B8%EA%B8%B0</guid>
            <pubDate>Thu, 05 Nov 2020 08:47:23 GMT</pubDate>
            <description><![CDATA[<p>Chap5. 인터페이스 기초02 - 레이아웃(Layout)
패키지명 : Exam01</p>
<p><img src="https://images.velog.io/images/continue_deve/post/8101a8e6-15bd-4529-b905-52cf31de2834/53.PNG" alt=""></p>
<ul>
<li><p>vertical 버튼 생성
id : btnVertical
onClick : onClick
text : @string/v_btn</p>
</li>
<li><p>horizontal 버튼 생성
id : btnHorizontal
onClick : onClick
text : @string/h_btn</p>
</li>
<li><p>기본 레이아웃이 Constraint인 경우 Linear로 바꿔주기</p>
</li>
</ul>
<h3 id="onclick-메소드">onClick 메소드</h3>
<pre><code>public void onClick (View v) {
        switch (v.getId()) {
            case R.id.btnVertical:
                layout.setOrientation(LinearLayout.VERTICAL);
                break;

            case R.id.btnHorizontal:
                layout.setOrientation(LinearLayout.HORIZONTAL);
                break;
        }
}</code></pre><p>LinearLayout layout = findViewById(R.id.linearLayout); 
: onClick에서 실행하면 버튼을 누를 때마다 실행되므로 onCreate에서 실행한다.</p>
<ul>
<li>실행 결과
<img src="https://images.velog.io/images/continue_deve/post/3031d4c2-a025-42a5-bf07-4e543fdd1011/54.gif" alt=""></li>
</ul>
<h3 id="전체-코드">전체 코드</h3>
<ul>
<li>MainActivity.java<pre><code>package ddwucom.mobile.test04;
</code></pre></li>
</ul>
<p>import androidx.appcompat.app.AppCompatActivity;</p>
<p>import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;</p>
<p>public class MainActivity extends AppCompatActivity {</p>
<pre><code>final static String TAG = &quot;MainActivity&quot;;
LinearLayout layout;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    layout = findViewById(R.id.linearLayout);
}

public void onClick (View v) {
    switch (v.getId()) {
        case R.id.btnVertical:
            layout.setOrientation(LinearLayout.VERTICAL);
            break;

        case R.id.btnHorizontal:
            layout.setOrientation(LinearLayout.HORIZONTAL);
            break;
    }
}</code></pre><p>}</p>
<pre><code>
- activity_main.xml</code></pre><?xml version="1.0" encoding="utf-8"?>
<p><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"></p>
<pre><code>&lt;Button
    android:id=&quot;@+id/btnVertical&quot;
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:onClick=&quot;onClick&quot;
    android:text=&quot;@string/v_btn&quot; /&gt;

&lt;Button
    android:id=&quot;@+id/btnHorizontal&quot;
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:onClick=&quot;onClick&quot;
    android:text=&quot;@string/h_btn&quot; /&gt;</code></pre></LinearLayout>
```

<ul>
<li>string.xml<pre><code>&lt;resources&gt;
  &lt;string name=&quot;app_name&quot;&gt;Exam01&lt;/string&gt;
  &lt;string name=&quot;v_btn&quot;&gt;VERTICAL&lt;/string&gt;
  &lt;string name=&quot;h_btn&quot;&gt;HORIZONTAL&lt;/string&gt;
&lt;/resources&gt;
</code></pre></li>
</ul>
<pre><code></code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[안드로이드 인터페이스 기초 02 - 레이아웃 (Layout)]]></title>
            <link>https://velog.io/@continue_deve/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EA%B8%B0%EC%B4%88-02-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83-Layout</link>
            <guid>https://velog.io/@continue_deve/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EA%B8%B0%EC%B4%88-02-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83-Layout</guid>
            <pubDate>Thu, 05 Nov 2020 04:12:18 GMT</pubDate>
            <description><![CDATA[<p>Chap5. 인터페이스 기초02 - 레이아웃(Layout)</p>
<h2 id="layout">Layout</h2>
<p>: 뷰그룹의 일종으로 다른 view들을 내부에 배치하는 컨테이너 역할을 수행한다.</p>
<p>; 일반적으로 화면상에 직접 보이지 않는다.</p>
<p>; 주요 레이아웃 : Linear/Relative/Frame/Grid/ConstraintLayout</p>
<h2 id="linearlayout">LinearLayout</h2>
<p>: 가장 간단한 레이아웃으로 가로(horizontal) 또는 세로(vertical)의 순서대로 항목을 배치한다.</p>
<p>; 절대 선택한 방향으로 배치된다. (뷰가 차고넘쳐도)</p>
<h3 id="주요-속성">주요 속성</h3>
<ul>
<li><p>orientation
: vertical/horizontal</p>
</li>
<li><p>gravity
: 내부 항목의 수직/수평 배치 결정 
(내가 내부에 담고있는 항목의 정렬)</p>
</li>
<li><p>layout_gravity
: 레이아웃에 항목 자신의 수직/수평 방향 배치 결정
(내가 담겨져 있는 레이아웃에서의 정렬)</p>
</li>
<li><p>baselineAligned
: 레이아웃에 배치한 뷰들의 아래 부분 맞춤 활성화 여부 (기준선)</p>
</li>
<li><p>layout_weight
: 레이아웃의 공간을 어느 정도 비중으로 차지하느냐를 결정.
0일 경우 본래 크기, 1 이상이면 다른 뷰와의 비율에 따라 배치된다.</p>
</li>
<li><p>layout_margin
: 레이아웃과 뷰 사이의 간격.</p>
</li>
<li><p>padding
: 뷰와 내부 내용물 사이의 간격.</p>
<br>

</li>
</ul>
<h2 id="relativelayout">RelativeLayout</h2>
<p>: 뷰와 뷰를 담고 있는 레이아웃(부모뷰), 그리고 다른 뷰와의 상대적인 관계로 배치한다.</p>
<p>; id가 필수로 요구된다.
<br></p>
<h2 id="framelayout">FrameLayout</h2>
<p>: 레이아웃의 좌측 상단에 모든 뷰들을 겹쳐서 배치한다.</p>
<p>; app 실행 중 addView/removeView 메소드를 사용하여 뷰들을 추가 및 삭제.
; 뷰의 visibility 속성을 이용하여 한 화면에서 여러 화면을 번갈아 보여주고 싶을 때 사용한다.
<br></p>
<h2 id="그-외-레이아웃">그 외 레이아웃</h2>
<h3 id="absolutelayout">AbsoluteLayout</h3>
<p>: 배치하는 View의 좌표를 절대값으로 지정한다. </p>
<p>; Realative와 상반된 개념.
; 기기별로 다양한 해상도를 갖기 때문에 사용이 적합하지 않아 거의 쓰이지 않음.</p>
<h3 id="tablelayout">TableLayout</h3>
<p>: 표 형식으로 View를 내부에 배치.</p>
<p>; 가로 : TableRow의 개수만큼 행 생성
; 세로 : TableRow에 포함한 View의 개수만큼 열 생성</p>
<h3 id="constraintlayout">ConstraintLayout</h3>
<p>제약이 있는 레이아웃. 레이아웃의 가로, 세로에 뷰를 연결한다.
현재 안드로이드에서 가장 기본적으로 쓰이는 레이아웃. 
<br></p>
<h2 id="레이아웃의-중첩">레이아웃의 중첩</h2>
<p>: 레이아웃 안에는 뷰 뿐만 아니라 다른 레이아웃을 중첩하여 배치 가능하다. </p>
<p>; 한 화면에 여러 개의 레이아웃이 가능하다는 말.
; 레이아웃은 보이지 않기 때문에 component tree상에서 옮기는 게 편하다.
<br></p>
<h2 id="실행-중-레이아웃-속성-변경">실행 중 레이아웃 속성 변경</h2>
<p>: XML로 지정한 레이아웃 속성은 소스코드 실행 중 변경 가능하다.</p>
<h3 id="1-xml로-지정한-뷰-객체를-찾은-후-변경-메소드-호출">1. XML로 지정한 뷰 객체를 찾은 후 변경 메소드 호출</h3>
<p>ex. xml에서 지정한 id가 LinearLayout1인 레이아웃을 객체화</p>
<pre><code>LinearLayout layout = (LinearLayout)findViewbyId(R.id.LinearLayout1);</code></pre><ul>
<li>findViewById() 메소드
: <strong>xml로 정의하여 자동 변환된 뷰 요소를 찾기 위한 메소드</strong>
; View 객체 형태로 반환하므로 타입캐스팅이 필요하다. (필수는 아님)
; Activity.findViewById()는 Activity 내부의 모든 뷰에서 id를 검색하는 것이고, View.findViewById()는 특정 뷰 내부에서만 검색하는 것이다.<br>

</li>
</ul>
<h3 id="2-객체화한-뷰-객체에서-속성에-해당하는-메소드-호출">2. 객체화한 뷰 객체에서 속성에 해당하는 메소드 호출</h3>
<p>ex1. LinearLayout의 orientation을 수평으로 바꾸고 싶을 때</p>
<pre><code>layout.setOrientation(LinearLayout.HORIZONTAL);</code></pre><p>ex2. LinearLayout의 현재 orientation을 확인하고 싶을 때</p>
<pre><code>int o = layout.getOrientation();</code></pre><p>대부분의 경우 속성에 해당하는 getter/setter가 존재한다.</p>
<p>예를 들어 orientation 속성을 확인하거나 변경하려면 속성앞에 set/get을 붙여 setOrientation/getOrientation으로 표현할 수 있다.</p>
<p>get으로 값을 받을 때에는 임의의 값이나 정해진 상수값으로 지정해서 받는다.
<br></p>
<h2 id="ui-작성-방법">UI 작성 방법</h2>
<h3 id="xml-레이아웃을-이용할-경우">XML 레이아웃을 이용할 경우</h3>
<pre><code>//MainActivity.java
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
}

//activity_main.xml
&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    android:id=&quot;@+id/linearLayout&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    android:orientation=&quot;vertical&quot;&gt;

    &lt;TextView
            android:id=&quot;@id/textView1&quot;
                android:layout_width=&quot;wrap_parent&quot;
                android:layout_height=&quot;wrap_parent&quot;
                android:text=&quot;TextView&quot; /&gt;
&lt;/LinearLayout&gt;

</code></pre><h3 id="코드만으로-작성할-경우">코드만으로 작성할 경우</h3>
<pre><code>protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

        LinearLayout linear = new LinearLayout(this);
        linear.setOrientation(LinearLayout.VERTICAL);
        linear.setBackgroundColor(Color.LTGRAY);

        TextView text = new TextView(this);
        text.setText(&quot;TextView&quot;);
        text.setGravity(Gravity.CENTER);

        linear.addView(text);
        setContentView(linear);
}</code></pre><ul>
<li>두 가지 경우 setContentView를 사용하여 레이아웃을 연결하는 것은 같지만 해당 메소드의 매개변수는 다르다. (오버로딩)</li>
</ul>
<p>*오버로딩(Overloading) : 메소드 이름은 같고, 매개변수의 개수, 타입이 다른 여러 개의 메소드 정의. (반환 타입 영향X)
<br></p>
<h2 id="레이아웃-전개inflation">레이아웃 전개(inflation)</h2>
<p>: XML로 지정한 뷰는 aapt에 의해 컴파일되어 이진 형태의 자바 객체로 변환된다.
*aapt(Android Asset Packaging Tool)</p>
<h3 id="inflation">inflation</h3>
<p>: XML문서의 텍스트 형태의 뷰를 실제 자바 객체화 하는 것.</p>
<p>; XML로 정의하면 자동으로 자바 객체로 변환된다. (R에 id가 등록됨)
; Inflation 진행 후 findViewById()메소드로 해당 객체 참조 가능.
<br></p>
<h2 id="setcontentview-메소드">setContentView() 메소드</h2>
<p>: View를 전달받아 Activity에 등록하는 역할.</p>
<p>경우1. 레이아웃의 resource id를 매개변수로 전달받으면 내부에서 inflation을 수행한 후 Activity에 등록한다. (==XML이용)</p>
<p>경우2. View객체(및 params객체)를 전달받으면 View를 params 정보에 따라 Activity에 등록. (==코드에 직접)
<br></p>
<h2 id="inflation-직접-실행">Inflation 직접 실행</h2>
<p>직접 inflation을 수행해야하는 경우가 있다.
ex. 앱 실행 중 화면의 구성을 바꾸어야 할 때
ex2. 상황에 따라 서로 다른 화면 구성이 교체되어야 할 때</p>
<h3 id="방법1-inflater를-생성하여">방법1. inflater를 생성하여</h3>
<pre><code>LayoutInflater Inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout linear = (LinearLayout)inflater.inflate(R.layout.activity_main, null);
setContentView(linear);</code></pre><ul>
<li>LayoutInflater Inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
: 시스템이 제공하는 기본 서비스를 요청하는 메소드</li>
</ul>
<p>//LayoutInflater Inflater = LayoutInfalter.from(this); 
: 위 코드와 동일한 내용, 다른 생김새. this는 Context객체다. (Activity 자신)</p>
<ul>
<li>LinearLayout linear = (LinearLayout)inflater.inflate(R.layout.activity_main, null);
: null 자리에는 root view(부모뷰)가 있을 경우 지정한다.<br>

</li>
</ul>
<h3 id="방법2-inflater-없이">방법2. inflater 없이</h3>
<pre><code>LinearLayout linear = (LinearLayout)View.inflate(this, R.layout.activity_main, null);
setContentView(linear);</code></pre><p>// View가 갖고있는 정적 메소드 inflate를 사용한다.
<br></p>
<h2 id="layout-parameter">Layout Parameter</h2>
<p>: view가 레이아웃 상에 배치되는 정보를 지정한다.</p>
<p>; XML상에서 layout_XXX형태의 속성들
; 뷰 자체의 속성이 아닌 외부 레이아웃에 배치할 때 필요한 정보
; 각 레이아웃마다 사용하는 정보가 다르므로 레이아웃에 배치할 때 뷰와 함께 매개변수로 전달한다.</p>
<p>ex.</p>
<pre><code>LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
    LinearLayout.LayoutParams.WRAP_CONTENT, 
        LinearLayout.LayoutParams.WRAP_CONTENT);

linear.addView(text, params);</code></pre><br>
]]></description>
        </item>
        <item>
            <title><![CDATA[버튼을 눌러 EditText 채우기]]></title>
            <link>https://velog.io/@continue_deve/%EB%B2%84%ED%8A%BC%EC%9D%84-%EB%88%8C%EB%9F%AC-EditText-%EC%B1%84%EC%9A%B0%EA%B8%B0</link>
            <guid>https://velog.io/@continue_deve/%EB%B2%84%ED%8A%BC%EC%9D%84-%EB%88%8C%EB%9F%AC-EditText-%EC%B1%84%EC%9A%B0%EA%B8%B0</guid>
            <pubDate>Thu, 05 Nov 2020 04:04:16 GMT</pubDate>
            <description><![CDATA[<p>Chap4. 인터페이스 기초 01.View
패키지명 : MyApplication2</p>
<ul>
<li>해야할 것</li>
</ul>
<ol>
<li>Button 생성(btnOne, btnTwo, btnThree, btnClear)</li>
<li>숫자 버튼을 누르면 editText에 계속 숫자 추가</li>
<li>clear를 누를 경우 EditText의 글자를 모두 지움</li>
</ol>
<h3 id="1-button-생성btnone-btntwo-btnthree-btnclear">1. Button 생성(btnOne, btnTwo, btnThree, btnClear)</h3>
<p><img src="https://images.velog.io/images/continue_deve/post/243a3bd5-ea3b-4dfe-be76-223caf33f9b9/52.PNG" alt="">각각 id를 부여하고 onClick메소드를 연결해준다.</p>
<h3 id="2-숫자-버튼을-누르면-edittext에-계속-숫자-추가">2. 숫자 버튼을 누르면 editText에 계속 숫자 추가</h3>
<p>버튼을 누르면
-&gt; EditText의 값 읽어오기
-&gt; 누른 버튼의 값을 읽어온 값에 추가
-&gt; 추가된 값을 EditText에 출력</p>
<p>= 이것이 onClick메소드에서 실행되어야 한다.</p>
<pre><code>public void onClick(View v) {
        EditText editText = (EditText) findViewById(R.id.editText);
        String str = editText.getText().toString();
</code></pre><p>//EditText의 값을 String으로 읽어오기</p>
<pre><code>    switch (v.getId()) {
                case R.id.btnOne :
                    str += &quot;1&quot;;
                    editText.setText(str);
                    break;

            case R.id.btnTwo :
                str += &quot;2&quot;;
                editText.setText(str);
                break;

            case R.id.btnThree :
                str += &quot;3&quot;;
                editText.setText(str);
                break;
        }
}        </code></pre><p>// str += &quot;n&quot;; 으로 누른 버튼의 값을 str값에 추가
// editText.setText(str); 로 추가된 값을 editText에 추가</p>
<h3 id="3-clear를-누를-경우-edittext의-글자를-모두-지움">3. clear를 누를 경우 EditText의 글자를 모두 지움</h3>
<p>공백없는 문자열 사용</p>
<pre><code>    case R.id.btnClear :
                editText.setText(&quot;&quot;);
                break;</code></pre><h3 id="전체-코드">전체 코드</h3>
<ul>
<li>MainActivity.java<pre><code>package ddwucom.mobile.test0426_2;
</code></pre></li>
</ul>
<p>import androidx.appcompat.app.AppCompatActivity;</p>
<p>import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;</p>
<p>public class MainActivity extends AppCompatActivity {</p>
<pre><code>@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

public void onClick(View v) {
    EditText editText = (EditText) findViewById(R.id.editText);
    String str = editText.getText().toString();

    switch (v.getId()) {
            case R.id.btnOne :
                str += &quot;1&quot;;
                editText.setText(str);
                break;

        case R.id.btnTwo :
            str += &quot;2&quot;;
            editText.setText(str);
            break;

        case R.id.btnThree :
            str += &quot;3&quot;;
            editText.setText(str);
            break;

        case R.id.btnClear :
            editText.setText(&quot;&quot;);
            break;
    }
}</code></pre><p>}</p>
<pre><code>
- activity_main.xml</code></pre><?xml version="1.0" encoding="utf-8"?>
<p>&lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=&quot;<a href="http://schemas.android.com/apk/res/android&quot;">http://schemas.android.com/apk/res/android&quot;</a>
    xmlns:app=&quot;<a href="http://schemas.android.com/apk/res-auto&quot;">http://schemas.android.com/apk/res-auto&quot;</a>
    xmlns:tools=&quot;<a href="http://schemas.android.com/tools&quot;">http://schemas.android.com/tools&quot;</a>
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    tools:context=&quot;.MainActivity&quot;&gt;</p>
<pre><code>&lt;EditText
    android:id=&quot;@+id/editText&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:ems=&quot;10&quot;
    android:inputType=&quot;number&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintHorizontal_bias=&quot;1.0&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toTopOf=&quot;parent&quot;
    app:layout_constraintVertical_bias=&quot;0.0&quot; /&gt;

&lt;Button
    android:id=&quot;@+id/btnOne&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:text=&quot;ONE&quot;
    android:onClick=&quot;onClick&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintHorizontal_bias=&quot;0.498&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/editText&quot;
    app:layout_constraintVertical_bias=&quot;0.0&quot; /&gt;

&lt;Button
    android:id=&quot;@+id/btnTwo&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:text=&quot;TWO&quot;
    android:onClick=&quot;onClick&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintHorizontal_bias=&quot;0.0&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/btnOne&quot;
    app:layout_constraintVertical_bias=&quot;0.0&quot; /&gt;

&lt;Button
    android:id=&quot;@+id/btnThree&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:text=&quot;THREE&quot;
    android:onClick=&quot;onClick&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintHorizontal_bias=&quot;1.0&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/btnTwo&quot;
    app:layout_constraintVertical_bias=&quot;0.0&quot; /&gt;

&lt;Button
    android:id=&quot;@+id/btnClear&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:text=&quot;CLEAR&quot;
    android:onClick=&quot;onClick&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintHorizontal_bias=&quot;0.0&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/btnThree&quot;
    app:layout_constraintVertical_bias=&quot;0.0&quot; /&gt;</code></pre><p>&lt;/androidx.constraintlayout.widget.ConstraintLayout&gt;</p>
<p>```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로필 화면 띄우기 _ Toast, EditText]]></title>
            <link>https://velog.io/@continue_deve/%ED%94%84%EB%A1%9C%ED%95%84-%ED%99%94%EB%A9%B4-%EB%9D%84%EC%9A%B0%EA%B8%B0-Toast-EditText</link>
            <guid>https://velog.io/@continue_deve/%ED%94%84%EB%A1%9C%ED%95%84-%ED%99%94%EB%A9%B4-%EB%9D%84%EC%9A%B0%EA%B8%B0-Toast-EditText</guid>
            <pubDate>Wed, 04 Nov 2020 16:08:00 GMT</pubDate>
            <description><![CDATA[<p>Chap4. 인터페이스 기초 01.View
패키지명 : MyApplication</p>
<ul>
<li>해야할 것</li>
</ul>
<ol>
<li>ImageView - size:300/300dp</li>
<li>EditText - id:etName</li>
<li>EditText - id:etPhone</li>
<li>btnHello클릭 시 다음 문장을 Toast로 출력</li>
<li>btnExit 클릭 시 앱 종료</li>
</ol>
<h3 id="1-imageview---size300300dp">1. ImageView - size:300/300dp <img src="https://images.velog.io/images/continue_deve/post/53023c81-6a26-4d40-81c8-b82c6de37ddb/47.PNG" alt=""></h3>
<br>

<h3 id="2-edittext---idetname">2. EditText - id:etName <img src="https://images.velog.io/images/continue_deve/post/d28b6f72-232d-4b97-b1db-17b689a5e538/48.PNG" alt=""></h3>
<h3 id="3-edittext---idetphone">3. EditText - id:etPhone</h3>
<p>2번과 같은 방법.</p>
<h3 id="4-btnhello클릭-시-다음-문장을-toast로-출력">4. btnHello클릭 시 다음 문장을 Toast로 출력</h3>
<p>문장 : 안녕하세요, 저는 XXX(etName 입력값) 입니다. 전화번호는 XXX(etPhone 입력값) 입니다.</p>
<p>MainActivity에서 버튼 클릭 메소드를 만든다.</p>
<pre><code>public void onMyBtnClick(View v) {
        EditText editText1 = (EditText)findViewById(R.id.etName);
        EditText editText2 = (EditText)findViewById(R.id.etPhone);

        String text = &quot;안녕하세요, 저는 &quot; + editText1.getText().toString() + &quot;입니다.&quot;
                + &quot;전화번호는 &quot; + editText2.getText().toString() + &quot;입니다.&quot;;
        Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
    }</code></pre><p><img src="https://images.velog.io/images/continue_deve/post/a8323e55-9423-4225-89ce-948f5ffcbedd/49.PNG" alt=""> 버튼을 만들고 id를 btnHello로 설정해준다.
onClick부분에 onMyBtnClick 메소드를 연결해준다. (메소드 이름은 자유)</p>
<ul>
<li>실행결과
<img src="https://images.velog.io/images/continue_deve/post/3b603005-7d2e-4d23-9fb5-f5525ecd27dc/50.gif" alt=""><br>

</li>
</ul>
<h3 id="5-btnexit-클릭-시-앱-종료">5. btnExit 클릭 시 앱 종료</h3>
<p>finish() 사용 : Activity의 멤버 메소드로 Activity 종료 시 사용한다.
MainActivity에 메소드를 만들어주고</p>
<pre><code>public void onMyExitClick(View v)  {
        finish();
    }</code></pre><p>4번과 동일하게 btnExit의 onClick에 메소드를 연결해주면 된다.</p>
<ul>
<li>실행결과
<img src="https://images.velog.io/images/continue_deve/post/6bb4f506-0a02-407e-a395-2fac8fb329e3/51.gif" alt=""></li>
</ul>
<h3 id="전체코드">전체코드</h3>
<ul>
<li>MainActivity.java<pre><code>package ddwucom.mobile.test0426;
</code></pre></li>
</ul>
<p>import androidx.appcompat.app.AppCompatActivity;</p>
<p>import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;</p>
<p>public class MainActivity extends AppCompatActivity {</p>
<pre><code>@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

public void onMyBtnClick(View v) {
    EditText editText1 = (EditText)findViewById(R.id.etName);
    EditText editText2 = (EditText)findViewById(R.id.etPhone);

    String text = &quot;안녕하세요, 저는 &quot; + editText1.getText().toString() + &quot;입니다.&quot;
            + &quot;전화번호는 &quot; + editText2.getText().toString() + &quot;입니다.&quot;;
    Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
}

public void onMyExitClick(View v)  {
    finish();
}</code></pre><p>}</p>
<pre><code>&lt;br&gt;

- activity_main.xml</code></pre><?xml version="1.0" encoding="utf-8"?>
<p>&lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=&quot;<a href="http://schemas.android.com/apk/res/android&quot;">http://schemas.android.com/apk/res/android&quot;</a>
    xmlns:app=&quot;<a href="http://schemas.android.com/apk/res-auto&quot;">http://schemas.android.com/apk/res-auto&quot;</a>
    xmlns:tools=&quot;<a href="http://schemas.android.com/tools&quot;">http://schemas.android.com/tools&quot;</a>
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    tools:context=&quot;.MainActivity&quot;&gt;</p>
<pre><code>&lt;TextView
    android:id=&quot;@+id/textView2&quot;
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:text=&quot;Profile&quot;
    android:textColor=&quot;#000000&quot;
    android:textSize=&quot;36dp&quot;
    android:textStyle=&quot;bold&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintHorizontal_bias=&quot;0.0&quot;
    app:layout_constraintLeft_toLeftOf=&quot;parent&quot;
    app:layout_constraintRight_toRightOf=&quot;parent&quot;
    app:layout_constraintTop_toTopOf=&quot;parent&quot;
    app:layout_constraintVertical_bias=&quot;0.0&quot; /&gt;

&lt;TextView
    android:id=&quot;@+id/textView&quot;
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:text=&quot;Photo&quot;
    android:textSize=&quot;18dp&quot;
    android:textColor=&quot;#000000&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintHorizontal_bias=&quot;0.0&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/textView2&quot;
    app:layout_constraintVertical_bias=&quot;0.0&quot; /&gt;

&lt;ImageView
    android:id=&quot;@+id/imageView&quot;
    android:layout_width=&quot;300dp&quot;
    android:layout_height=&quot;300dp&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintHorizontal_bias=&quot;0.0&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/textView&quot;
    app:layout_constraintVertical_bias=&quot;0.0&quot;
    app:srcCompat=&quot;@drawable/goodluck&quot;
    tools:srcCompat=&quot;@drawable/goodluck&quot; /&gt;

&lt;TextView
    android:id=&quot;@+id/textView3&quot;
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:text=&quot;Name&quot;
    android:textColor=&quot;#000000&quot;
    android:textSize=&quot;18dp&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintHorizontal_bias=&quot;0.0&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/imageView&quot;
    app:layout_constraintVertical_bias=&quot;0.0&quot; /&gt;

&lt;EditText
    android:id=&quot;@+id/etName&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:ems=&quot;10&quot;
    android:hint=&quot;이름을 입력하시오&quot;
    android:inputType=&quot;textCapWords&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintHorizontal_bias=&quot;0.0&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/textView3&quot;
    app:layout_constraintVertical_bias=&quot;0.0&quot;&gt;

&lt;/EditText&gt;

&lt;TextView
    android:id=&quot;@+id/textView4&quot;
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:text=&quot;Phone&quot;
    android:textColor=&quot;#000000&quot;
    android:textSize=&quot;18dp&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintHorizontal_bias=&quot;0.0&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/etName&quot;
    app:layout_constraintVertical_bias=&quot;0.0&quot; /&gt;

&lt;EditText
    android:id=&quot;@+id/etPhone&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:ems=&quot;10&quot;
    android:hint=&quot;전화번호를 입력하시오&quot;
    android:inputType=&quot;phone&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintHorizontal_bias=&quot;0.0&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/textView4&quot;
    app:layout_constraintVertical_bias=&quot;0.0&quot;&gt;

&lt;/EditText&gt;

&lt;Button
    android:id=&quot;@+id/btnHello&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:text=&quot;인삿말&quot;
    android:onClick=&quot;onMyBtnClick&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintHorizontal_bias=&quot;0.498&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/etPhone&quot;
    app:layout_constraintVertical_bias=&quot;0.0&quot; /&gt;

&lt;Button
    android:id=&quot;@+id/btnExit&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:text=&quot;종료&quot;
    android:onClick=&quot;onMyExitClick&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintHorizontal_bias=&quot;0.498&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/btnHello&quot;
    app:layout_constraintVertical_bias=&quot;0.0&quot; /&gt;</code></pre><p>&lt;/androidx.constraintlayout.widget.ConstraintLayout&gt;</p>
<pre><code></code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[TextView, Button, ScrollView, ImageView의 적용]]></title>
            <link>https://velog.io/@continue_deve/TextView-Button-ScrollView-ImageView%EC%9D%98-%EC%A0%81%EC%9A%A9</link>
            <guid>https://velog.io/@continue_deve/TextView-Button-ScrollView-ImageView%EC%9D%98-%EC%A0%81%EC%9A%A9</guid>
            <pubDate>Wed, 04 Nov 2020 13:46:17 GMT</pubDate>
            <description><![CDATA[<p>Chap4. 인터페이스 기초 01.View
패키지명 : chap4_prac</p>
<ul>
<li>해야할 것</li>
</ul>
<ol>
<li>레이아웃에 3개의 버튼을 배치하고 각각 다음 방법으로 자신의 이름을 표시하시오.</li>
<li>버튼 크기를 정해진 상수 및 dp단위를 사용하여 변경하시오.</li>
<li>ScrollView를 사용하여 Text를 표시하시오.</li>
<li>이미지를 ImageView에 표시하시오.</li>
</ol>
<br>

<h3 id="1레이아웃에-3개의-버튼을-배치하고-각각-다음-방법으로-자신의-이름을-표시하시오">1.레이아웃에 3개의 버튼을 배치하고 각각 다음 방법으로 자신의 이름을 표시하시오.</h3>
<p>버튼 배치는 activity_main.xml의 design창에서 Palette에 있는 버튼 위젯을 마구 레이아웃 위로 올리면 된다. Constraint레이아웃이므로 점을 창의 끝에 대충 연결 시켜주고 간격 조절 적당히 해주고 하면 된다.</p>
<p>방법1. 속성에 직접 이름 기록 <img src="https://images.velog.io/images/continue_deve/post/b5eb9416-0059-49c1-96b2-a810513c58d3/40.PNG" alt=""></p>
<p>방법2. string.xml에 이름을 기록하고 TextView에 연결</p>
<pre><code>//string.xml
&lt;string name=&quot;button2&quot;&gt;SEIN2&lt;/string&gt;

//activity_main.xml
android:text=&quot;@string/button2&quot;</code></pre><p>방법3. code에서 직접 이름 기록</p>
<pre><code>//activity_main.xml
android:text=&quot;SEIN3&quot;</code></pre><p>그냥 activity_main.xml의 code창 열어서 냅다 써버리기.</p>
<br>

<h3 id="2버튼-크기를-정해진-상수-및-dp단위를-사용하여-변경하시오">2.버튼 크기를 정해진 상수 및 dp단위를 사용하여 변경하시오. <img src="https://images.velog.io/images/continue_deve/post/fa62a75b-fbb4-45ac-af1a-4488288b4e05/41.PNG" alt=""></h3>
<br>

<h3 id="3scrollview를-사용하여-text를-표시하시오">3.ScrollView를 사용하여 Text를 표시하시오.</h3>
<p><img src="https://images.velog.io/images/continue_deve/post/01eafb48-eea9-4eb6-8b71-b320502fb976/42.PNG" alt="">design창에서 ScrollView-LinearLayout-textView 순으로 배치.</p>
<pre><code>&lt;ScrollView
        android:id=&quot;@+id/scrollView2&quot;
        android:layout_width=&quot;0dp&quot;
        android:layout_height=&quot;0dp&quot;
        app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
        app:layout_constraintEnd_toEndOf=&quot;parent&quot;
        app:layout_constraintStart_toStartOf=&quot;parent&quot;
        app:layout_constraintTop_toBottomOf=&quot;@+id/imageView&quot;&gt;

        &lt;LinearLayout
            android:layout_width=&quot;match_parent&quot;
            android:layout_height=&quot;wrap_content&quot;
            android:orientation=&quot;vertical&quot;&gt;

            &lt;TextView
                android:id=&quot;@+id/textView&quot;
                android:layout_width=&quot;match_parent&quot;
                android:layout_height=&quot;wrap_content&quot;
                android:text=&quot;TextView&quot;
                android:textSize=&quot;45sp&quot; /&gt;
        &lt;/LinearLayout&gt;
    &lt;/ScrollView&gt;</code></pre><p>//스크롤뷰에 바로 텍스트뷰를 넣을 수 없다. 레이아웃을 껴야한다.
<br>
MainActivity에서 text를 잔뜩 넣어준다.</p>
<pre><code>String msg = &quot;Hello World!!!!!!!!!!!!\n&quot; +
                &quot;Hello World!!!!!!!!!!!!\n&quot; +
                &quot;Hello World!!!!!!!!!!!!\n&quot; +
                &quot;Hello World!!!!!!!!!!!!\n&quot; +
                &quot;Hello World!!!!!!!!!!!!\n&quot; +
                &quot;Hello World!!!!!!!!!!!!\n&quot; +
                &quot;Hello World!!!!!!!!!!!!\n&quot; +
                &quot;Hello World!!!!!!!!!!!!\n&quot; +
                &quot;Hello World!!!!!!!!!!!!\n&quot; +
                &quot;Hello World!!!!!!!!!!!!\n&quot; +
                &quot;Hello World!!!!!!!!!!!!\n&quot;;

TextView textView = findViewById(R.id.textView);
textView.setText(msg);</code></pre><ul>
<li>실행결과
<img src="https://images.velog.io/images/continue_deve/post/470fca71-b51c-494d-aef5-9e1a8968985c/43.gif" alt=""></li>
</ul>
<br>

<h3 id="4이미지를-imageview에-표시하시오">4.이미지를 ImageView에 표시하시오.</h3>
<pre><code>&lt;ImageView
        android:id=&quot;@+id/imageView&quot;
        android:src=&quot;@drawable/img_sample&quot; /&gt;</code></pre><p>이미지 파일은 Android모드에서는 여기 <img src="https://images.velog.io/images/continue_deve/post/ca2285a6-bd08-4279-b30d-fc16b0dce8f9/44.PNG" alt="">
Project모드에서는 여기 <img src="https://images.velog.io/images/continue_deve/post/eca70515-2c31-4a83-b589-988543851691/45.PNG" alt="">
design창에서는 이렇게 보인다<img src="https://images.velog.io/images/continue_deve/post/898747fc-58ed-4d6c-8ea4-8d1d534ed973/46.PNG" alt=""></p>
<h3 id="전체-코드">전체 코드</h3>
<ul>
<li>MainActivity.java<pre><code>package ddwucom.mobile.chap4_prac;
</code></pre></li>
</ul>
<p>import androidx.appcompat.app.AppCompatActivity;</p>
<p>import android.os.Bundle;
import android.widget.TextView;</p>
<p>public class MainActivity extends AppCompatActivity {</p>
<pre><code>@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    String msg = &quot;Hello World!!!!!!!!!!!!\n&quot; +
            &quot;Hello World!!!!!!!!!!!!\n&quot; +
            &quot;Hello World!!!!!!!!!!!!\n&quot; +
            &quot;Hello World!!!!!!!!!!!!\n&quot; +
            &quot;Hello World!!!!!!!!!!!!\n&quot; +
            &quot;Hello World!!!!!!!!!!!!\n&quot; +
            &quot;Hello World!!!!!!!!!!!!\n&quot; +
            &quot;Hello World!!!!!!!!!!!!\n&quot; +
            &quot;Hello World!!!!!!!!!!!!\n&quot; +
            &quot;Hello World!!!!!!!!!!!!\n&quot; +
            &quot;Hello World!!!!!!!!!!!!\n&quot;;

    TextView textView = findViewById(R.id.textView);
    textView.setText(msg);
}</code></pre><p>}</p>
<pre><code>&lt;br&gt;

- activity_main.xml</code></pre><?xml version="1.0" encoding="utf-8"?>
<p>&lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=&quot;<a href="http://schemas.android.com/apk/res/android&quot;">http://schemas.android.com/apk/res/android&quot;</a>
    xmlns:app=&quot;<a href="http://schemas.android.com/apk/res-auto&quot;">http://schemas.android.com/apk/res-auto&quot;</a>
    xmlns:tools=&quot;<a href="http://schemas.android.com/tools&quot;">http://schemas.android.com/tools&quot;</a>
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    android:background=&quot;#8BC34A&quot;
    tools:context=&quot;.MainActivity&quot;&gt;</p>
<pre><code>&lt;Button
    android:id=&quot;@+id/button3&quot;
    android:layout_width=&quot;80dp&quot;
    android:layout_height=&quot;80dp&quot;
    android:layout_marginTop=&quot;50dp&quot;
    android:layout_marginEnd=&quot;50dp&quot;
    android:layout_marginRight=&quot;50dp&quot;
    android:background=&quot;#FFEB3B&quot;
    android:text=&quot;SEIN3&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintStart_toEndOf=&quot;@+id/button2&quot;
    app:layout_constraintTop_toTopOf=&quot;parent&quot; /&gt;

&lt;Button
    android:id=&quot;@+id/button&quot;
    android:layout_width=&quot;80dp&quot;
    android:layout_height=&quot;80dp&quot;
    android:layout_marginStart=&quot;50dp&quot;
    android:layout_marginLeft=&quot;50dp&quot;
    android:layout_marginTop=&quot;50dp&quot;
    android:layout_marginEnd=&quot;6dp&quot;
    android:layout_marginRight=&quot;6dp&quot;
    android:background=&quot;#FF0000&quot;
    android:text=&quot;SEIN&quot;
    android:textColor=&quot;#FFFFFF&quot;
    app:layout_constraintEnd_toStartOf=&quot;@+id/button2&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toTopOf=&quot;parent&quot; /&gt;

&lt;Button
    android:id=&quot;@+id/button2&quot;
    android:layout_width=&quot;80dp&quot;
    android:layout_height=&quot;80dp&quot;
    android:layout_marginTop=&quot;50dp&quot;
    android:layout_marginEnd=&quot;18dp&quot;
    android:layout_marginRight=&quot;18dp&quot;
    android:background=&quot;#FF9800&quot;
    android:text=&quot;@string/button2&quot;
    app:layout_constraintEnd_toStartOf=&quot;@+id/button3&quot;
    app:layout_constraintStart_toEndOf=&quot;@+id/button&quot;
    app:layout_constraintTop_toTopOf=&quot;parent&quot; /&gt;

&lt;ImageView
    android:id=&quot;@+id/imageView&quot;
    android:layout_width=&quot;180dp&quot;
    android:layout_height=&quot;180dp&quot;
    android:layout_marginTop=&quot;50dp&quot;
    android:layout_marginBottom=&quot;50dp&quot;
    android:src=&quot;@drawable/img_sample&quot;
    app:layout_constraintBottom_toTopOf=&quot;@+id/scrollView2&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/button2&quot; /&gt;

&lt;ScrollView
    android:id=&quot;@+id/scrollView2&quot;
    android:layout_width=&quot;0dp&quot;
    android:layout_height=&quot;0dp&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toBottomOf=&quot;@+id/imageView&quot;&gt;

    &lt;LinearLayout
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:orientation=&quot;vertical&quot;&gt;

        &lt;TextView
            android:id=&quot;@+id/textView&quot;
            android:layout_width=&quot;match_parent&quot;
            android:layout_height=&quot;wrap_content&quot;
            android:text=&quot;TextView&quot;
            android:textSize=&quot;45sp&quot; /&gt;
    &lt;/LinearLayout&gt;
&lt;/ScrollView&gt;</code></pre><p>&lt;/androidx.constraintlayout.widget.ConstraintLayout&gt;</p>
<pre><code>&lt;br&gt;

- string.xml</code></pre><resources>
    <string name="app_name">chap4_prac</string>
    <string name="button2">SEIN2</string>
</resources>
```




]]></description>
        </item>
        <item>
            <title><![CDATA[안드로이드 에러 & 예외 모음 (android error & exception)]]></title>
            <link>https://velog.io/@continue_deve/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%97%90%EB%9F%AC-%EC%98%88%EC%99%B8-%EB%AA%A8%EC%9D%8C-android-error-exception</link>
            <guid>https://velog.io/@continue_deve/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%97%90%EB%9F%AC-%EC%98%88%EC%99%B8-%EB%AA%A8%EC%9D%8C-android-error-exception</guid>
            <pubDate>Wed, 04 Nov 2020 11:50:25 GMT</pubDate>
            <description><![CDATA[<h2 id="null-point-exception이-떠서-앱-실행-중단됐을-경우">null point exception이 떠서 앱 실행 중단됐을 경우</h2>
<p>해결방법  : <strong>디버거</strong> or <strong>Logcat</strong> or <strong>Log</strong> 사용으로 문제점 알아내기</p>
<ol>
<li><p>디버거 사용
Shfit + F9로 한 줄씩 디버깅하며 문제점 파악.</p>
</li>
<li><p>Logcat 사용
스택 트레이스를 읽어 문제 찾기(Stack tracing)
붉은 글씨나 Cause by, 해당 앱의 패키지 이름을 주의해서 볼 것.
<em>*참고하면 좋은 글 : <a href="https://okky.kr/article/338405">https://okky.kr/article/338405</a></em></p>
</li>
<li><p>Log 이용
Log.d (debug)
Log.i (information)
Log.e (error)</p>
</li>
</ol>
<pre><code>Log.d(&quot;test&quot;, text);</code></pre><p>//내용은 Logcat에서 test를 검색하여 확인가능</p>
<p><em>또는</em></p>
<pre><code>final static String TAG = &quot;MainActivity&quot;);
Log.d(TAG, text);</code></pre><p>//TAG로 상수처리하여 TAG를 검색하여 확인가능</p>
<br>

<h2 id="virtual-deviceavd가-실행이-안되는-경우">Virtual Device(AVD)가 실행이 안되는 경우</h2>
<p>경우-1
윈도우 계정 이름이 한글명이면 에러가 날 수 있다</p>
<p>이는 AVD Manager에서 실행할 AVD의 [Action] - 🔻 - [Show on Disk]에서 확인할 수 있다. 
<img src="https://images.velog.io/images/continue_deve/post/c12483b4-2d81-4bb6-8f7b-e4ebaa7aab1d/image.png" alt=""></p>
<p>폴더가 열리면 주소창을 눌러 주소를 확인할 수 있는데 \Users옆이 계정명이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Chap15. 실습]]></title>
            <link>https://velog.io/@continue_deve/Chap15.-%EC%8B%A4%EC%8A%B5</link>
            <guid>https://velog.io/@continue_deve/Chap15.-%EC%8B%A4%EC%8A%B5</guid>
            <pubDate>Sun, 25 Oct 2020 04:16:57 GMT</pubDate>
            <description><![CDATA[<h2 id="연락처-관리-app">연락처 관리 APP</h2>
<ol>
<li><p>연락처는 친구, 가족, 기타로 분류할 수 있어야 한다.</p>
</li>
<li><p>이름으로 연락처를 검색할 수 있어야 한다.
2-1. 이름을 정확히 입력하였을 경우
2-2. 이름의 일부만 입력하였을 경우</p>
</li>
<li><p>전체 주소 보기 중 롱클릭 수행 시 삭제 확인 대화상자를 표시한 후 응답 결과에 따라 삭제를 수행.
: AlertDialog.Builder 이용</p>
</li>
<li><p>전체 주소 보기 중 클릭할 경우 내용을 수정할 수 있는 액티비티로 전환 후 수정 기능 수행
: 클릭한 항목의 데이터(DTO)를 intent에 저장 후 수정 Activity 호출 시에 전달</p>
</li>
<li><p>새로운 연락처 추가 기능</p>
</li>
<li><p>추가/변경/삭제 후 리스트 갱신 수행</p>
</li>
</ol>
]]></description>
        </item>
    </channel>
</rss>