본문 바로가기

안드로이드

안드로이드 - 5 주사위 App0201

1. MainActivity

package com.example.app0201;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.Random;

public class MainActivity extends AppCompatActivity {
    // 주사위 App
    //1. 버튼을 누르면 주사위 눈이 랜덤으로 출력된다.(Random)
    //2. 두 주사위 눈을 비교한다.
    //2-1. img > img2 : tv_ueser1에 카운트 +1
    //2-2. img <img2 : tv_ueser2 에 카운트 +1
    // 2-3 img1 == img2 : Toast 를 이용해서 "무승부!" 알림메시지 출력

    ImageView img1, img2;
    Button btn_shake;
    TextView tv_user1, tv_user2;

    Random random;
    int[] imgArray = {R.drawable.dice1, R.drawable.dice2, R.drawable.dice3, R.drawable.dice4,
            R.drawable.dice5, R.drawable.dice6};

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

        img1 = findViewById(R.id.img1);
        img2 = findViewById(R.id.img2);
        btn_shake = findViewById(R.id.btn_shake);
        tv_user1 = findViewById(R.id.tv_user1);
        tv_user2 = findViewById(R.id.tv_user2);

        // 버튼에 클릭이벤트 적용하기!(익명클래스)
        btn_shake.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                random = new Random();
                // img1,img2에 사용할 랜덤수를 생성하기!
                int num1 = random.nextInt(imgArray.length);
                int num2 = random.nextInt(6);

                img1.setImageResource(imgArray[num1]);
                img2.setImageResource(imgArray[num2]);

                // 두 주사위 눈 비교하기!
                if (num1 > num2) {
                    int user1 = Integer.parseInt(tv_user1.getText().toString());
                    user1 += 1;
                    tv_user1.setText(String.valueOf(user1));
                } else if (num1 < num2) {
                    int user2 = Integer.parseInt(tv_user2.getText().toString());
                    user2 += 1;
                    tv_user2.setText(String.valueOf(user2));
                } else {
                    Toast.makeText(MainActivity.this, "무승부!", Toast.LENGTH_SHORT).show();
                }
            }
        });

    }
}

2. activity_main

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <!-- DICE 타이틀 -->
    <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="146dp"
        android:layout_marginTop="104dp"
        android:layout_marginEnd="135dp"
        android:text="DICE"
        android:textSize="60sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <!-- 유저 1 주사위 눈 수 -->
    <TextView
        android:id="@+id/tv_user1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="76dp"
        android:text="0"
        android:textSize="30sp"
        app:layout_constraintEnd_toStartOf="@+id/textView2"
        app:layout_constraintHorizontal_bias="0.384"
        app:layout_constraintStart_toStartOf="@+id/textView4"
        app:layout_constraintTop_toBottomOf="@+id/textView4" />

    <!-- 콜론 텍스트 -->
    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=":"
        android:textSize="30sp"
        app:layout_constraintBottom_toBottomOf="@+id/tv_user1"
        app:layout_constraintEnd_toEndOf="@+id/textView4"
        app:layout_constraintHorizontal_bias="0.455"
        app:layout_constraintStart_toStartOf="@+id/textView4"
        app:layout_constraintTop_toTopOf="@+id/tv_user1"
        app:layout_constraintVertical_bias="0.0" />

    <!-- 유저 2 주사위 눈 수 -->
    <TextView
        android:id="@+id/tv_user2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="0"
        android:textSize="30sp"
        app:layout_constraintBottom_toBottomOf="@+id/textView2"
        app:layout_constraintEnd_toEndOf="@+id/textView4"
        app:layout_constraintHorizontal_bias="0.66"
        app:layout_constraintStart_toEndOf="@+id/textView2"
        app:layout_constraintTop_toTopOf="@+id/textView2" />

    <!-- 유저 1 주사위 이미지 -->
    <ImageView
        android:id="@+id/img1"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginStart="60dp"
        android:layout_marginTop="380dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/dice1" />

    <!-- 유저 2 주사위 이미지-->
 <Button
        android:id="@+id/btn_shake"
        android:layout_width="132dp"
        android:layout_height="67dp"
        android:layout_marginTop="244dp"
        android:backgroundTint="#C5C5C5"
        android:insetTop="2dp"
        android:insetBottom="2dp"
        android:text="SHAKE"
        android:textColor="#010001"
        android:textSize="25sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="@+id/img2"
        app:layout_constraintHorizontal_bias="0.54"
        app:layout_constraintStart_toStartOf="@+id/img1"
        app:layout_constraintTop_toBottomOf="@+id/textView2" />

</androidx.constraintlayout.widget.ConstraintLayout>

3. MainActivity2.java

package com.example.app0201;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;

//생명주기(Life cycle)
// : App이 시작부터 종료까지 실행되는 일련의 과정
// : onCreate-onStart-onResume-onPause-onStop-onDestory
// : onReStart
public class MainActivity2 extends AppCompatActivity {
    //Log에 사용할 Tag 변수 생성
    private final static String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        Log.v(TAG,"onCreate()실행");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.v(TAG,"onStart()실행");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.v(TAG,"onResume()실행");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.v(TAG,"onPause()실행");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.v(TAG,"onStop()실행");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.v(TAG,"onRestart()실행");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.v(TAG,"onDestroy()실행");
    }
}
  • MainActivity2 클래스는 AppCompatActivity 클래스를 상속받아서 구현된 Activity 클래스이다.
  • 액티비티 생명주기에 따른 각각의 콜백 메서드들을 재정의하여 로그 출력을 한다.
  • TAG 상수는 Log 클래스의 메서드들 중 하나인 v() 메서드에서 출력할 메시지의 태그로 사용된다.
  • 각 콜백 메서드에 로그를 출력하여, 해당 메서드가 실행될 때마다 로그가 출력된다.

4. activity_main2.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity2">

</androidx.constraintlayout.widget.ConstraintLayout>

이 코드는 activity_main2.xml 파일의 뼈대 코드입니다. 현재는 뷰가 존재하지 않고 빈 레이아웃으로만 구성되어 있습니다. 앱 개발자는 이 파일을 열어서 UI 요소들을 추가하고 배치할 수 있습니다. ConstraintLayout은 안드로이드에서 가장 많이 사용되는 레이아웃 중 하나입니다. 이 레이아웃을 사용하여 UI 요소들을 배치하면 다양한 화면 크기와 해상도에 대응하는 뷰를 쉽게 만들 수 있습니다.

5. MainActivity2

package com.example.app0201;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;

public class MainActivity3 extends AppCompatActivity {
    Button btnWeb, btnCamera, btnDial, btnCall;

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

        // 버튼 객체 초기화
        btnWeb = findViewById(R.id.btnWeb);
        btnCamera = findViewById(R.id.btnCamera);
        btnDial = findViewById(R.id.btnDial);
        btnCall = findViewById(R.id.btnCall);

        // 웹 사이트 접속 버튼 리스너 설정
        btnWeb.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //Intent 객체 생성
                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.naver.com"));
                // Intent에 담긴 정보 실행
                startActivity(intent);
            }
        });

        // 카메라 앱 실행 버튼 리스너 설정
        btnCamera.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                startActivity(intent);
            }
        });

        // 전화 걸기 앱 실행 버튼 리스너 설정
        btnDial.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(Intent.ACTION_DIAL,
                        Uri.parse("tel:010-8278-5908"));
                startActivity(intent);
            }
        });

        // 전화 걸기 권한 요청 후 전화 걸기 앱 실행 버튼 리스너 설정
        btnCall.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(Intent.ACTION_CALL,
                        Uri.parse("tel:010-8278-5908"));
                // 유저에게 권한사용에 대한 허가를 받아야 한다!
                // 앱에 권한 설정이 되어있는지 확인 후 유저 화면에 요청알림 띄우기!
                // *앱이 실행되었을 때 권한을 요청해야 할 경우, onStart or onResume에 구현하기!
                if (ContextCompat.checkSelfPermission(MainActivity3.this,
                        android.Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(MainActivity3.this,
                            new String[]{android.Manifest.permission.CALL_PHONE}, 0);
                    return;
                }

                startActivity(intent);
            }
        });
    }
}
  • MainActivity3는 네이버 웹사이트, 카메라 앱, 전화 걸기 앱을 실행시키는 버튼 4개로 이루어진 앱이다.
  • btnWeb 버튼 클릭 시 Intent를 사용하여 네이버 웹사이트를 실행시킨다.
  • btnCamera 버튼 클릭 시 Intent를 사용하여 카메라 앱을 실행시킨다.
  • btnDial 버튼 클릭 시 Intent를 사용하여 전화 걸기 앱을 실행시킨다

6. MainActivity3

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context=".MainActivity3">

    <Button
        android:id="@+id/btnDial"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:backgroundTint="#D6D5D6"
        android:text="전화걸기(DIAL)"
        android:textColor="#050505"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toTopOf="@+id/btnCall"
        app:layout_constraintEnd_toEndOf="@+id/btnCamera"
        app:layout_constraintStart_toStartOf="@+id/btnCamera"
        app:layout_constraintTop_toBottomOf="@+id/btnCamera"
        app:layout_constraintVertical_bias="0.5" />

    <Button
        android:id="@+id/btnWeb"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:backgroundTint="#D6D5D6"
        android:text="웹 페이지 보기"
        android:textColor="#050505"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toTopOf="@+id/btnCamera"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.5" />

    <Button
        android:id="@+id/btnCamera"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:backgroundTint="#D6D5D6"
        android:text="카메라호출"
        android:textColor="#050505"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toTopOf="@+id/btnDial"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="@+id/btnWeb"
        app:layout_constraintTop_toBottomOf="@+id/btnWeb"
        app:layout_constraintVertical_bias="0.5" />

    <Button
        android:id="@+id/btnCall"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:backgroundTint="#D6D5D6"
        android:text="전화걸기(CALL)"
        android:textColor="#050505"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="@+id/btnDial"
        app:layout_constraintStart_toStartOf="@+id/btnDial"
        app:layout_constraintTop_toBottomOf="@+id/btnDial"
        app:layout_constraintVertical_bias="0.5" />
</androidx.constraintlayout.widget.ConstraintLayout>

위의 코드는 4개의 Button 위젯을 ConstraintLayout을 사용하여 배치한 코드입니다.

각 버튼마다 onClickListener를 설정하여 클릭 이벤트를 처리하도록 구현되어 있습니다.

  • btnWeb : 인터넷 브라우저를 열어 지정된 URL로 이동합니다.
  • btnCamera : 카메라 앱을 실행합니다.
  • btnDial : 전화번호를 입력하여 다이얼을 띄웁니다.
  • btnCall : 전화번호를 입력하여 전화를 걸 수 있도록 권한요청 후 처리합니다.

각 버튼 위젯은 ConstraintLayout의 속성을 사용하여 배치되었으며, 각각의 속성은 아래와 같습니다.

  • layout_constraintStart_toStartOf : 왼쪽 여백을 지정합니다.
  • layout_constraintEnd_toEndOf : 오른쪽 여백을 지정합니다.
  • layout_constraintTop_toTopOf : 위쪽 여백을 지정합니다.
  • layout_constraintBottom_toBottomOf : 아래쪽 여백을 지정합니다.
  • layout_constraintVertical_bias : 수직 정렬 위치를 지정합니다. (0.0은 상단, 1.0은 하단)
  • layout_width : 버튼의 너비를 지정합니다.
  • layout_height : 버튼의 높이를 지정합니다.
  • backgroundTint : 버튼 배경색을 지정합니다.
  • text : 버튼에 표시될 텍스트를 지정합니다.
  • textColor : 버튼에 표시될 텍스트 색상을 지정합니다.
  • textSize : 버튼에 표시될 텍스트 크기를 지정합니다.
  • textStyle : 버튼에 표시될 텍스트 스타일을 지정합니다.

또한, 앱에서 전화를 걸기 위해 CALL_PHONE 권한이 필요한데, 버튼을 누르기 전에 권한이 허용되었는지 확인하고, 권한이 없는 경우 권한 요청 다이얼로그를 띄우도록 구현되어 있습니다.