올해는 머신러닝이다.
미디어플레이어 백그라운드 작업 참고문 본문
background에서 작업하기
<Service >
예) 미디어 플레이어 : 꼭 Service로 만들어야 하는건 아니다. Activity로도 만들수있음.
장시간으로 하면서 user Interface가 거의 없는 것을 Service로 만드는 게 좋다.
* intent filter 존재 : intent로 시작됨.
Intent i = new Intent(명시적 or 암시적)
startService(i); // 한 life cycle 돌게됨.
- 객체는 singleton이라서 다른곳에서 startService()를 다시 호출해도 onCreate()는 되지않고 onStart()만 다시불린다.
stopService(i);
bindService(i); // 내 액티비티에서 저 서비스 연결해서 뭔가 뽑아내고자 할때
unbindService(i);
* Life Cycle
onCreate()
| |
onStart() onBind()
...
thread
(장시간 이용할시)
...
onStop() unBind()
| |
onDestroy()
onCreate() -> onStart() -> onStop() -> onDestroy();
Binding할때 : onCreate() ->onBind() -> unBind() -> onDestroy();
onBind()
{
return new My();
}
class My extends Binder {
service getService();
return 0;
}
ServiceConnection타입의 객체 (interface) 를 inner class로 만듬.
- onServiceConnected(Binder b);, onServiceDisConnected() 두개 overriding해야됨.
Connection완료된 다음에 Binding정보 넘겨주는 게 맞음.
b.getService() 이런식으로..
BindService할때 매개변수로 ServiceConnection을 매개변수로 넘겨줌.
쓰레드를 얼마나 깔끔하게 짜느냐도 관건..
* Background Thread (<-> Main Thread(UI Thread))
오래걸리는 작업이 있을 시 Background thread로 돌린다.
왜냐하면 5초이상 반응해주지 못하면 에러이기때문.
Binder-post()
[실습]
프로젝트 새로 생성 후,
res폴더밑에 폴더 raw하나 만들어서 kara.mp3, start.png, stop.png파일을 넣는다.
[AndroidManifest.xml]
Service 하나 추가한다.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="chap8.Service"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".Main"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="PlayService"></service>
</application>
<uses-sdk android:minSdkVersion="7" />
</manifest>
[main.xml]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageButton android:id="@+id/ImageButton01"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:src="@raw/start"></ImageButton>
<ImageButton android:id="@+id/ImageButton02"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:src="@raw/stop"></ImageButton>
</LinearLayout>
<ProgressBar
android:id="@+id/ProgressBar01"
android:layout_width="fill_parent" android:layout_height="wrap_content"
style="?android:attr/progressBarStyleHorizontal"></ProgressBar>
</LinearLayout>
[PlayService.java]
package chap8.Service;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;
public class PlayService extends Service implements Runnable {
MediaPlayer player;
boolean flag = true;
private int duration;
private int currentPosition;
// getter, setter함수
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public int getDuration() {
return duration;
}
public void setDuration(int duration) {
this.duration = duration;
}
public int getCurrentPosition() {
return currentPosition;
}
public void setCurrentPosition(int currentPosition) {
this.currentPosition = currentPosition;
}
// thread 에 의해 실행되는 코드...
// Bind되는 순간부터 run이 실행되면서 매 초마다 현재 Position를 설정한다.
public void run() {
// run을 빠져나가면 thread는 끝난다.
// 장시간 해야되는건 주로 loop를 만들어 놓는다.
while(flag) // 음원이 끝나면 나가라.
{
setCurrentPosition(player.getCurrentPosition());
try {
// sleep은 항상 try~cath와 같이 쓰여야 한다.
Thread.sleep(1000); // milisecond unit
} catch (Exception e) {
// TODO: handle exception
}
}
}
@Override
public IBinder onBind(Intent arg) {
// TODO Auto-generated method stub
player = MediaPlayer.create(this, R.raw.kara);
setDuration(player.getDuration());
player.start();
// MediaPlayer의 음원 플레이 시간을 얻어내서 service의 데이터를
// 업데이트 시키는 작업을 하는 thread
//(null: 특별히 group값이 필요없음.
// this: thread 돌릴 source, player는 이름
Thread t = new Thread(null, this, "player");
t.start(); // bind되는 순간 PlayService의 run()이 시작됨.
return new MyBinder(); // bind될 객체 리턴해야됨.
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
player.stop(); // service 멈추기
flag = false; // thread가 멈출 수 있게 flag값 설정
}
@Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
// player = MediaPlayer.create(this, R.raw.kara);
// player.start();
// SD카드의 여러 음악프로그램중 어떤걸 play할 것인지?
// 음악이 끝났다는 신호를 받을 수 있다. 그러면 다음곡 실행시키기.
}
// Activity bind시 Activity에 전달시킬 객체
public class MyBinder extends Binder {
PlayService getService() {
return PlayService.this;
}
}
}
[Main.java]
package chap8.Service;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.ProgressBar;
public class Main extends Activity implements OnClickListener, Runnable{
/** Called when the activity is first created. */
private ImageButton bt1;
private ImageButton bt2;
private ProgressBar bar;
// service랑 bind해서 service 객체를 얻어 service 의 데이터에 접근하기 위해
private PlayService pService;
// UI Thread에 UI 변경작업을 지시하기 위해 선언
private Handler handler = new Handler();
// user event와 상관없이 장시간 동안 service에 접근해서 데이터 획득하는 역할
private Thread background;
@Override
// 1. Main이 실행되면서 onCreate()함수가 가장 먼저 실행된다.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
bt1 = (ImageButton)findViewById(R.id.ImageButton01);
bt2 = (ImageButton)findViewById(R.id.ImageButton02);
bt1.setOnClickListener(this);
bt2.setOnClickListener(this);
bar = (ProgressBar)findViewById(R.id.ProgressBar01);
//bar.setOnClickListener(this);
}
public void onClick(View v) {
// TODO Auto-generated method stub
if(v == bt1)
{
Intent intent = new Intent(this, PlayService.class); // 명시적
//startService(intent);
// 2. 재생버튼을 누르면 OnClick이 실행되고,
// 여기서 service를 bind시킨다.
// Service에서는 onCreate(), onBind()까지 실행되게된다.
bindService(intent, connection, Context.BIND_AUTO_CREATE);
background = new Thread(null, this, "test");
} else if(v == bt2) {
Intent intent = new Intent(this, PlayService.class);
//stopService(intent);
// stop버튼을 누르면 binding이 끊긴다.
unbindService(connection);
} else if(v == bar) {
//handler.post(updateBar);
// UserEvent받아들일 수 있는 거는 SeekBar로만 할 수 있다.
// ProgressBar는 시스템에 의해서만 동작된다.
}
}
// bind 상태에 따라 자동 호출되는 메서드를 가지는 객체 선언
private ServiceConnection connection =
new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
pService = null;
}
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
// IBinder타입을 PlayService.MyBinder타입으로 type-casting하고
// getService로 서비스 가져온다.
//3. Binding이 완료되면 Service 정보를 가져오고
pService = ((PlayService.MyBinder)service).getService();
//4. background로 thread를 실행시킨다.
background.start(); // 이때부터 run()이 실행된다.
}
};
// UI Thread 에게 넘겨줄 작업
// Inner class - Runnable이 inteface이므로..
private Runnable updateBar = new Runnable() {
public void run() {
// UI thread는 간단하게 짠다. loop문같은거 넣지않는다.
// 6. bar가 새롭게 그려진다.
bar.setProgress(pService.getCurrentPosition());
}
};
// background thread가 작업할 내용을 가지는 메서드
// 5. background thread는 돌면서 1초마다
// UI updateBar thread한테 progress를 표시하라고 post한다.
public void run() {
// 전체 음원의 시간값으로 bar의 Max를 설정한다.
bar.setMax(pService.getDuration());
while(pService.isFlag())
{
try {
Thread.sleep(1000);
// 오늘의 key point!!
// 1초마다 main thread한테 update progress bar하라고 날린다.
handler.post(updateBar);
} catch (Exception e) {
// TODO: handle exception
}
}
}
}
'Android > Tip&Tech' 카테고리의 다른 글
[펌]안드로이드 aidl 시작하기 (0) | 2010.12.07 |
---|---|
[펌][Android] 안드로이드 인디케이터 설정 - NotificationManager (0) | 2010.12.06 |
MediaPlayer 순환표 (0) | 2010.12.03 |
[안드로이드]롤오버 이미지 만들기 (0) | 2010.12.03 |
[펌]Mediaplayer Service - 백그라운드 음악 실행 (0) | 2010.12.03 |