오늘이라도

[Android] 23. Navigation Drawer / 오디오 재생, 정지, 일시정지, 재시작 본문

취업성공패키지 SW 개발자 교육/Android

[Android] 23. Navigation Drawer / 오디오 재생, 정지, 일시정지, 재시작

upcake_ 2020. 6. 9. 10:15
반응형

 

 

https://github.com/upcake/Class_Examples

교육 중에 작성한 예제들은 깃허브에 올려두고 있습니다. 

gif 파일은 클릭해서 보는 것이 정확합니다.


 - Navigation Drawer -

▲FloatingActionButton 작동 화면

 

▲메뉴 클릭 시 작동 화면

 

▲뒤로가기 버튼 눌렀을 시 작동 화면

 

apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    defaultConfig {
        applicationId "com.example.my31_navigationdrawer"
        minSdkVersion 16
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    implementation 'com.android.support:design:29.0.0'
}

▲build.gradle(:app)

 

<?xml version="1.0" encoding="utf-8"?>
<!--화면 전체 : drawerLayout-->
<androidx.drawerlayout.widget.DrawerLayout
    android:id="@+id/drawerLayout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/ThemeOverlay.AppCompat">

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:popupTheme="@style/Widget.AppCompat.Toolbar" />
        </com.google.android.material.appbar.AppBarLayout>

        <FrameLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

        <!--layout_gravity= bottom|end 두개 속성을 동시에 지정 가능-->
        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@android:drawable/ic_dialog_email"/>

    </androidx.coordinatorlayout.widget.CoordinatorLayout>

    <!--실질적으로 보여지는 네비게이션 뷰-->
    <!--헤더뷰와 아이템을 찾아서 사용한다-->
    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer"/>
</androidx.drawerlayout.widget.DrawerLayout>

▲activity_main.xml

 

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:showIn="navigation_view">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_home"
            android:icon="@android:drawable/ic_menu_camera"
            android:title="Home" />

        <item
            android:id="@+id/nav_gallery"
            android:icon="@android:drawable/ic_menu_gallery"
            android:title="Gallery" />

        <item
            android:id="@+id/nav_slideshow"
            android:icon="@android:drawable/ic_menu_slideshow"
            android:title="Slideshow" />

        <item
            android:id="@+id/nav_tools"
            android:icon="@android:drawable/ic_menu_manage"
            android:title="Tools" />
    </group>

    <item
        android:id="@+id/communicate"
        android:title="Communicate"
        android:visible="false">
        <!--처음엔 안보이게 설정-->
        <menu>
           <item
               android:id="@+id/nav_share"
               android:icon="@android:drawable/ic_menu_share"
               android:title="Share" />

            <item
                android:id="@+id/nav_send"
                android:icon="@android:drawable/ic_menu_send"
                android:title="Send" />
        </menu>
    </item>
</menu>

 

▲activity_main_drawer.xml

 

<resources>

    <!-- Base application theme. -->
    <!--NoActionBar로 바꾸면 상단에 액션바가 사라짐-->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>

▲styles.xml

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:id="@+id/headerLayout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="176dp"
    android:background="@drawable/side_nav_bar"
    android:gravity="bottom"
    android:orientation="vertical"
    android:padding="16dp"
    android:theme="@style/ThemeOverlay.AppCompat.Dark">

    <ImageView
        android:id="@+id/loginImage"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:contentDescription="Navigation Header"
        android:paddingTop="8dp"
        android:src="@mipmap/ic_launcher_round" />

    <TextView
        android:id="@+id/loginID"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="8dp"
        android:text="Android Studio"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1" />

    <TextView
        android:id="@+id/loginStr"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="android.studio@android.com" />

</LinearLayout>

▲nav_header_main.xml

 

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <gradient
        android:angle="135"
        android:centerColor="#009688"
        android:endColor="#00695C"
        android:startColor="#4DB6AC"
        android:type="linear" />


</shape>

▲side_nav_bar.xml

 

 

package com.example.my31_navigationdrawer;

import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;

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

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.navigation.NavigationView;
import com.google.android.material.snackbar.Snackbar;


public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
    Toolbar toolbar;
    Fragment1 fragment1;
    Fragment2 fragment2;
    Fragment3 fragment3;

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

        toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        DrawerLayout drawerLayout = findViewById(R.id.drawerLayout);
        //string.xml에 사용할 스트링을 미리 작성해두고 그 주소(int 타입)을 가져다 사용한다.
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar,
                R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawerLayout.addDrawerListener(toggle);
        toggle.syncState();



        //프래그먼트
        fragment1 = new Fragment1();
        fragment2 = new Fragment2();
        fragment3 = new Fragment3();

        getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment1).commit();

        NavigationView navigationView = findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
        /*
        //방법 1. setNavigationItemSelectedListener(new O) ▶ 자동 완성
        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
                return false;
            }
        });
         */

        /*----------------------헤드 드로어에 로그인 정보 표시하기-------------------------*/
        String loginID = "ASDF";
        //헤더의 0번지 뷰에 접근한다
        View headerView = navigationView.getHeaderView(0);
        //헤더뷰에 id로 접근하면 에러가 나온다.
        //View headerView = navigationView.findViewById(R.id.headerLayout);

        //헤더 뷰의 객체 초기화
        ImageView loginImage = headerView.findViewById(R.id.loginImage);
        TextView navLoginID = headerView.findViewById(R.id.loginID);

        //ID와 이미지를 로그인된 ID와 이미지로 바꾸기
        navLoginID.setText("반갑습니다 " + loginID + "님");
        loginImage.setImageResource(R.drawable.dream01);

        //로그인 ID가 있으면 커뮤니케이트 메뉴가 보이게 설정
        if(loginID != null) {
            navigationView.getMenu().findItem(R.id.communicate).setVisible(true);
        }

        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_SHORT).setAction("Action", null).show();
            }
        });
    }

    //방법 2. 메인액티비티 implements NavigationView.OnNavigationItemSelectedListener ▶ implements methods
    //navigationView 객체를 초기화하고 navigationView.setNavigationItemSelectedListener(this);
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
        int selectedItemId = menuItem.getItemId();

        if (selectedItemId == R.id.nav_home) {
            Toast.makeText(this, "첫 번째 메뉴 선택", Toast.LENGTH_SHORT).show();
            onFragmentSelected(0, null);
        } else if (selectedItemId == R.id.nav_gallery) {
            Toast.makeText(this, "두 번째 메뉴 선택", Toast.LENGTH_SHORT).show();
            onFragmentSelected(1, null);
        } else if (selectedItemId == R.id.nav_slideshow) {
            Toast.makeText(this, "세 번째 메뉴 선택", Toast.LENGTH_SHORT).show();
            onFragmentSelected(2, null);
        } else if (selectedItemId == R.id.nav_tools) {
            Toast.makeText(this, "네 번째 메뉴 선택", Toast.LENGTH_SHORT).show();
            onFragmentSelected(3, null);
        } else if (selectedItemId == R.id.nav_share) {
            Toast.makeText(this, "다섯 번째 메뉴 선택", Toast.LENGTH_SHORT).show();
            onFragmentSelected(4, null);
        } else if (selectedItemId == R.id.nav_send) {
            Toast.makeText(this, "여섯 번째 메뉴 선택", Toast.LENGTH_SHORT).show();
            onFragmentSelected(5, null);
        }

        //드로어 닫기
        DrawerLayout drawerLayout = findViewById(R.id.drawerLayout);
        drawerLayout.closeDrawer(GravityCompat.START);

        return true;
    } //onNavigationItemSelected()

    public void onFragmentSelected(int position, Bundle bundle) {
        Fragment curFragment = null;

        if (position == 0) {
            curFragment = fragment1;
            toolbar.setTitle("첫 번째 화면");
        } else if (position == 1) {
            curFragment = fragment2;
            toolbar.setTitle("두 번째 화면");
        } else if (position == 2) {
            curFragment = fragment3;
            toolbar.setTitle("세 번째 화면");
        } else if (position == 3) {
            curFragment = fragment1;
            toolbar.setTitle("네 번째 화면");
        } else if (position == 4) {
            curFragment = fragment2;
            toolbar.setTitle("다섯 번째 화면");
        } else if (position == 5) {
            curFragment = fragment3;
            toolbar.setTitle("여섯 번째 화면");
        }
        getSupportFragmentManager().beginTransaction().replace(R.id.container, curFragment).commit();
    } //onFragmentSelect()

    //뒤로가기 버튼이 눌렸을때 작동하는 메서드
    @Override
    public void onBackPressed() {
        DrawerLayout drawerLayout = findViewById(R.id.drawerLayout);
        if(drawerLayout.isDrawerOpen(GravityCompat.START)) { // 드로어가 열려있다면
            drawerLayout.closeDrawer(GravityCompat.START);   // 드로어를 닫는다.
        } else {
            super.onBackPressed();
        }
    } //onBackPressed()
}

▲MainActivity.java

 

<resources>
    <string name="app_name">My31_NavigationDrawer</string>
    <string name="navigation_drawer_open">Open Navigation Drawer</string>
    <string name="navigation_drawer_close">Close Navigation Drawer</string>

</resources>

▲strings.xml

 

 

 - 오디오 재생, 정지, 일시정지, 재시작 -

 

▲작동 화면, (소리가 매우 작습니다)

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="재생"
        android:textSize="24sp" />

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="정지"
        android:textSize="24sp" />

    <Button
        android:id="@+id/button3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="일시정지"
        android:textSize="24sp" />

    <Button
        android:id="@+id/button4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="재시작"
        android:textSize="24sp" />
</LinearLayout>

▲activity_main.xml

 

package com.example.my32_audioplayer;

import androidx.appcompat.app.AppCompatActivity;

import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.io.IOException;

public class MainActivity extends AppCompatActivity {
    //외부 URL에서 가져올 경우
    String AUDIO_URL = "http://sites.google.com/site/ubiaccessmobile/sample_audio.amr";
    MediaPlayer mediaPlayer;
    int position = 0;

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

        //버튼 객체 초기화
        Button btnStart = findViewById(R.id.button1);
        Button btnStop = findViewById(R.id.button2);
        Button btnPause = findViewById(R.id.button3);
        Button btnResume = findViewById(R.id.button4);

        //시작 버튼 기능 추가
        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                playAudio(AUDIO_URL);
//                playAudioInnerProject(R.raw.m01);
                Toast.makeText(MainActivity.this, "재생 시작!", Toast.LENGTH_SHORT).show();
            }
        });

        //정지 버튼 기능 추가
        btnStop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mediaPlayer != null) { // mediaPlayer가 재생중일 때
                    mediaPlayer.stop();
                    Toast.makeText(MainActivity.this, "음악 정지!", Toast.LENGTH_SHORT).show();
                }
            }
        });

        //일시정지 버튼 기능 추가
        btnPause.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mediaPlayer != null) {
                    position = mediaPlayer.getCurrentPosition();
                    mediaPlayer.pause();
                    Toast.makeText(MainActivity.this, "음악 일시정지! : " + position, Toast.LENGTH_SHORT).show();
                }
            }
        });

        //재시작 버튼 기능 추가
        btnResume.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mediaPlayer != null && !mediaPlayer.isPlaying()) { // 미디어 플레이어에 재생 흔적이 있으면서 재생중이 아닐때
                    mediaPlayer.start();
                    mediaPlayer.seekTo(position);
                    Toast.makeText(MainActivity.this, "음악 재시작! : " + position, Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
    private void playAudio(String audio_url) {
        killMediaPlayer();
        try {
            mediaPlayer = new MediaPlayer();
            mediaPlayer.setDataSource(audio_url);
            mediaPlayer.prepare();
            mediaPlayer.start();
        } catch (Exception e) {
            e.printStackTrace();
            e.getMessage(); //에러 발생시 메세지 출력
        }
    } //playAudio()

    private void playAudioInnerProject(int resId) {
        killMediaPlayer();
        try {
//            mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.m01);
            mediaPlayer.start();
        } catch (Exception e) {
            e.printStackTrace();
            e.getMessage(); //에러 발생시 메세지 출력
        }
    } //playAudio()

    //기존의 재생되고 있는 미디어플레이어를 제거하는 메서드
    private void killMediaPlayer() {
        if(mediaPlayer != null) {
            mediaPlayer.release();
        }
    } //killMediaPlayer()

    //어플리케이션이 정지될 경우 작동하는 메서드
    @Override
    protected void onStop() {
        super.onStop();
        killMediaPlayer();
    } //onStop()
}

▲MainActivity.java

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.my32_audioplayer">

    <!--권한 설정-->
    <uses-permission android:name="android.permission.INTERNET" />

    <!--Cleartext HTTP traffic to sites.google.com not permitted-->
    <!--IOException 발생시 android:usesCleartextTraffic="true" 추가할 것-->
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:usesCleartextTraffic="true">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

▲AndroidManifest.xml

반응형