본문 바로가기

Android Studio를 활용한 안드로이드 프로그래밍

13장. 멀티미디어와 구글 지도

오디오

멀티미디어를 동작시키기 위해 제공되는 MediaPlayer 클래스는 음악과 동영상을 재생해준다.

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activiry_main);
    
    // MediaPlayer 객체 선언 및 song1.mp3 파일 대응
    final MediaPlayer mPlayer;
    mPlayer = MediaPlayer.create(this, R.raw.song1);
    
    // 스위치를 클릭할 때마다 동작하는 리스너 생성
    final Switch switch1 = (Switch)findViewById(R.id.switch1);
    switch1.setOnClickListener(new View.OnClickListener(){
    	public void onClick(View v) {
        	if (switch1.isChecked() == true)
            	mPlayer.start();
            else
            	mPlayer.stop();        
    	}
    });
}

 

스레드

프로그레스바와 시크바

프로그레스바 : 작업의 진행 상태 확인에 많이 활용된다.

시크바 : 음악이나 동영상의 재생 위치를 지정할 때 많이 활용된다.

 

일반적인 프로그레스바의 용도는 음악과 같은 멀티미디어의 재생과 함께 프로그레스바가 자연스럽게 진행되도록 하는 것이다.

 

이렇게 2개의 작업 (음악 재생, 프로그레스바)이 동시에 진행되기 위해서는 스레드가 필요하다.

 

스레드의 기본

기본 스레드를 사용하는 형식

new Thread() {
    public void run() {
        // 이 곳에 작업 코딩
    }
}.start();

 

예제

public class MainActivity extends AppCompatActivity {
    ProgressBar pb1, pb2;
    Button btn;

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

        pb1 = (ProgressBar)findViewById(R.id.pb1);
        pb2 = (ProgressBar)findViewById(R.id.pb2);
        btn = (Button)findViewById(R.id.button1);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
//                for(int i = 0; i < 100; ++i)
//                {
//                    pb1.setProgress(pb1.getProgress()+2);
//                    pb2.setProgress(pb2.getProgress()+1);
//                    SystemClock.sleep(100);
//                }

                new Thread(){
                    public void run() {
                        for(int i = pb1.getProgress(); i < 100; i=i+2){
                            pb1.setProgress(pb1.getProgress()+2);
                            SystemClock.sleep(100);
                        }
                    }
                }.start();

                new Thread(){
                    public void run() {
                        for(int i = pb2.getProgress(); i < 100; i=i++){
                            pb2.setProgress(pb2.getProgress()+1);
                            SystemClock.sleep(100);
                        }
                    }
                }.start();
            }
        });
    }
}

각 프로그레스 바를 조작하는 스레드를 생성하게 되면, 각 프로그레스바가 동시에 동작한다.

 

UI 스레드

UI(User Interface) 스레드는 화면의 위젯을 변경할 때 사용한다.

 

일반적인 스레드는 스레드 안에서 화면의 다른 위젯을 변경할 수 없다.

 

위의 그림과 같이 텍스트 뷰 2개를 추가한 뒤, 스레드 별로 텍스트뷰를 수정하여 진행률을 보이게 하고자 한다.

 

간단히 생각하면 아래와 같은 코드를 생각할 수 있다.

public class MainActivity extends AppCompatActivity {
    ...
    TextView tv1, tv2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        tv1 = (TextView)findViewById(R.id.tv1);
        tv2 = (TextView)findViewById(R.id.tv2);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new Thread(){
                    public void run() {
                        for(int i = pb1.getProgress(); i < 100; i=i+2){
                            pb1.setProgress(pb1.getProgress()+2);
                            tv1.setText("1번 진행률: " + pb1.getProgress() + "%");
                            SystemClock.sleep(100);
                        }
                    }
                }.start();

        ...
    }
}

책에서는 위와같이 코드를 작성하는 경우 실행 오류가 발생하거나 응용 프로그램이 즉시 종료된다고 했지만, 실행은 잘 되었고 프로그레스바가 100% 채워지지 않는 버그가 발생했다.

 

 

위젯을 안정적으로 변경하기 위해서는 runOnUiThread({}) 안에 코드를 넣어야한다.

runOnUiThread(new Runnable()) {
    public void run() {
        // 위젯을 변경하는 코드를 이 곳에 삽입
    }
});
...
                new Thread(){
                    public void run() {
                        for(int i = pb1.getProgress(); i < 100; i=i+2){
                            runOnUiThread(new Runnable(){
                                public void run() {
                                    pb1.setProgress(pb1.getProgress()+2);
                                    tv1.setText("1번 진행률: " + pb1.getProgress() + "%");
                                }
                            });
                            SystemClock.sleep(100);
                        }
                    }
                }.start();
...

UI 스레드를 사용하도록 변경한 경우, 프로그레스바가 100% 모두 채워지게 동작하는 것을 확인했다.

 

※ 프로그레스바와 그 자식 클래스(위젯)은 예외적으로 스레드 안에서 변경이 가능하지만, 안정적인 변경을 위해서는 마찬가지로 UI 스레드를 사용한다.

 

 

구글 지도

구글 지도 사용을 위한 준비

구글 지도를 안드로이드 앱에 포함하려면 개발에 사용할 PC별로 구글에서 제공하는 API 키를 얻어야 한다.

키를 얻는 방법은 책의 497page ~ 507page를 따라 진행한다.

 

따라하다보면 아래와 같이 어플리케이션 내에서 지도를 사용할 수 있다.

 

구글 지도의 응용

책의 실습 13-3을 따라해보면, GoogleMap 클래스 객체의 setMapType을 통해 위성 지도, 일반 지도 등의 옵션을 선택할 수 있다.