2012-12-14 2 views
1

MediaPlayer를 사용하여 사운드를 재생하는 IntentService를 시작하는 BroadcastReceiver를 트리거하는 반복 알람이 있습니다. 그러나, IntentService에서 스레드가 사운드 끝나기 전에 사망하기 때문에 (자원을 realeasing에 사용) 내 OnCompletionListener가 호출되지 않고 나는 로그에 경고 메시지를 얻을 : 나는 oncompletionlistener 때까지 살아 스레드를 유지할 수있는 방법MediaPlayer onCompletionListener가 호출되고 스레드가 죽지 않았는지 확인하십시오.

Handler{4072a788} sending message to a Handler on a dead thread 

을 호출됩니다. 아니면 내가 원하는 것을 얻기위한 더 나은 접근법이 있습니까?

답변

0

로컬 서비스를 통해 재생되는 Controll 미디어 플레이어의 경우 CarefulMediaPlayer (mp, this)와 같은 다른 클래스에 대한 미디어 플레이어 참조를 보내는 것이 좋습니다. 이 클래스의 모든 미디어 플레이어 속성을 처리합니다. 나는 그것이 당신을 도울 것이라고 생각합니다.

감사

0

나는이 문제를 얼마 동안 고투 그리고 마지막으로 나는 아래의 클래스를 사용하여 제대로 작동하려면 그것을 얻었다. Looper가있는 스레드를 사용하여 모든 MediaPlayer 논리를 처리하는 것이 아이디어입니다.

난 단지 루퍼를 종료하고 서비스가 명시적인 중지 메시지를받은 경우 스레드를 청소

public class PlayService extends IntentService { 
private static PowerManager.WakeLock wakeLock; 
private static final String TAG = "PlayService"; 
private static String LOCK_NAME = TAG; 
public static final String EXTRA_FILE = "file"; 
public static final String ACTION_PLAY = "play"; 
private static final String ACTION_STOP = "stop"; 
public static final int MSG_START = 1; 
public static final int MSG_STOP = 2; 

public PlayService(String name) { 
    super(name); 
} 

public PlayService() { 
    super("PlayService"); 
} 

@Override 
public void onCreate() { 
    super.onCreate(); 
} 

@Override 
protected void onHandleIntent(Intent intent) { 
    Message msg = new Message(); 
    if (ACTION_PLAY.equalsIgnoreCase(intent.getAction())) { 
     String fileName = intent.getExtras().getString(EXTRA_FILE); 
     msg.what = MSG_START; 
     msg.obj = fileName; 
    } else if (ACTION_STOP.equalsIgnoreCase(intent.getAction())) { 
     msg.what = MSG_STOP; 
    } 
    try { 
     PlayMediaThread.getInstance(this).sendMessage(msg); 
    } catch (InterruptedException e) { 
     Log.e(TAG, e.getMessage()); 
    } 
} 

public static PowerManager.WakeLock acquireLock(Context context) { 
    if (wakeLock == null || !wakeLock.isHeld()) { 
     PowerManager powerManager = (PowerManager) context 
       .getSystemService(Context.POWER_SERVICE); 
     wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 
       LOCK_NAME); 
     wakeLock.setReferenceCounted(true); 
     wakeLock.acquire(); 
    } 
    return wakeLock; 
} 

public static void releaseLock(Context context) { 
    if (wakeLock != null && wakeLock.isHeld()) { 
     wakeLock.release(); 
    } 
} 

} 

class PlayMediaThread extends Thread implements OnCompletionListener, 
    OnErrorListener, OnPreparedListener { 
private static Semaphore semaphore = new Semaphore(0); 
private static Handler handler; 
private static Looper myLooper; 
private static Context context; 
private static String currentFileName; 
private static MediaPlayer player; 
private static PlayMediaThread instance; 
private static final String TAG = "PlayMediaThread"; 

private PlayMediaThread(Context context) throws InterruptedException { 
    super(TAG); 
    PlayMediaThread.context = context; 
    start(); 
    // To insure that the looper was initialized correctly before return an 
    // instance 
    semaphore.acquire(); 
} 

public static PlayMediaThread getInstance(Context context) 
     throws InterruptedException { 
    if (instance == null) { 
     instance = new PlayMediaThread(context); 
    } 
    PlayMediaThread.context = context; 
    return instance; 
} 

public void sendMessage(Message msg) { 
    handler.sendMessage(msg); 
} 

public void quitLooper() { 
    try { 
     if (myLooper != null) { 
      myLooper.quit(); 
      Log.i(TAG, "After quit"); 

     } 
    } catch (Exception ex) { 
     Log.e(TAG, ex.getMessage()); 
    } 
} 

@Override 
public void run() { 
    Looper.prepare(); 
    myLooper = Looper.myLooper(); 
    handler = new Handler() { 
     @Override 
     public void handleMessage(Message msg) { 
      if (msg.what == PlayService.MSG_START) { 
       startPlayer((String) msg.obj); 
      } else if (msg.what == PlayService.MSG_STOP) { 
       // when stop command is coming from the activity i.e. user 
       // explicitly clicked stop, I quit the looper and 
       // clean the thread 
       stopPlayer(true); 
      } 
     } 
    }; 
    semaphore.release(); 
    Log.i(TAG, "Before Loop"); 
    Looper.loop();  
} 

private void stopPlayer(boolean clean) {     
    if (player != null) { 
     if (player.isPlaying()) { 
      player.stop(); 
     } 
     player.release(); 
     player = null; 
    } 
    if (clean) { 
        PlayService.releaseLock(context); 
     quitLooper(); 
     instance = null; 

    } 
} 

private void startPlayer(String fileName) { 
    if (player != null && player.isPlaying() && currentFileName != null 
      && currentFileName.equalsIgnoreCase(fileName)) { 
     return; 
    } 
    currentFileName = fileName; 
    stopPlayer(false); 

    player = new MediaPlayer(); 
    player.setOnCompletionListener(this); 
    player.setOnErrorListener(this); 
    player.setOnPreparedListener(this); 

    try { 
     player.setDataSource(context, Uri.parse(currentFileName)); 
     player.prepare(); 
     player.start(); 
     PlayService.acquireLock(context); 
    } catch (Exception e) { 
     Log.e(TAG, e.getMessage()); 
    } 
} 

@Override 
public boolean onError(MediaPlayer mp, int arg1, int arg2) { 
    Log.e(TAG, "onError");  

    stopPlayer(true); 

    return false; 
} 

@Override 
public void onCompletion(MediaPlayer mp) { 
    Log.d(TAG, "onCompletion"); 
      // Just to quit the looper and clean the thread 
      stopPlayer(true); 
} 

@Override 
public void onPrepared(MediaPlayer mp) { 
    Log.d(TAG, "onPrepared");  
} 

} 
관련 문제