Android MediaPlayer Singleton

时间:2011-10-20 04:56:03

标签: android singleton onclick android-mediaplayer

我已经阅读了这里的几篇文章,建议使用单例代码,我已阅读并放入音板,因为我想使用单例代码只允许一个媒体播放器实例,无论用户定义多少次点击。

基本上我只想要一个声音,如果用户在播放期间点击另一个按钮,它会停止当前声音并播放按下的声音。我只想要一个MediaPlayer实例,但不了解如何实现它。

以下是我的代码的基本概念:

    package com.example.context;

    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;




    import android.app.Activity;
    import android.content.ContentValues;
    import android.content.Intent;
    import android.media.MediaPlayer;
    import android.net.Uri;
    import android.os.Bundle;
    import android.provider.MediaStore;
    import android.view.ContextMenu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.ContextMenu.ContextMenuInfo;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.Toast;

    public class main extends Activity implements OnClickListener {

    MediaPlayer player;

    int[] ressound ={R.raw.boomstick, R.raw.chainsaw, R.raw.shebitch, R.raw.byebye,
    R.raw.comegetsome, R.raw.groovy, R.raw.shoelace, R.raw.smart,   R.raw.yeahbaby};//added as needed
    int j=0;
    private static final String TAG = "MyTag";

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);


     //Coding for all buttons, registers, and Listeners
        Button btn1 = (Button) findViewById(R.id.btn1);
        registerForContextMenu(btn1); 
        btn1.setOnClickListener(this);
        Button btn2 = (Button) findViewById(R.id.btn2);
        registerForContextMenu(btn2);
        btn2.setOnClickListener(this);
        Button btn3 = (Button) findViewById(R.id.btn3);
        registerForContextMenu(btn3);
        btn3.setOnClickListener(this);

    }

     //On click Handlers for multiple buttons 
        public void onClick(View v) {
        switch(v.getId()){
        case R.id.btn1:
        // action to perform on button 1
        j = 0;
        playResource();
        break;
    case R.id.btn2:
        // action to perform on button 1
        j = 1;
        playResource();
        break;
    case R.id.btn3:
        // action to perform on button 1    
        j = 2;
        playResource();
        break;

    }
         public void playResource(int j, int resource) {
    this.j = j;
    if (player != null) {
        if (player.isPlaying())
            player.stop();
        player.reset();
        //from MediaPlayer implementation (link above)
        try {
            AssetFileDescriptor afd = getResources().openRawResourceFd(resource);
            if (afd == null) return;
            player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
            afd.close();
            player.prepare();
        } catch (IOException ex) {
            Log.d(TAG, "create failed:", ex);
            // failed: return
        } catch (IllegalArgumentException ex) {
            Log.d(TAG, "create failed:", ex);
            // failed: return
        } catch (SecurityException ex) {
            Log.d(TAG, "create failed:", ex);
            // failed: return
        }
    }
    else {
        //player is null
        //it will create new MediaPlayer instance, setDataSource and call prepare
        player = MediaPlayer.create(this, resource);
    }
    //if everything ok play file
    //in case of any error return from method before (catch)
    player.start();
}

这是我必须更新和更改我的代码,但它给我一个传递playresource()函数的问题。我是不是错了,如果它是私密的,那就过去了。

3 个答案:

答案 0 :(得分:4)

你不需要单身人士。你在做什么是每次想要播放文件时调用create方法。这是错误的,因为你已经有了MediaPlayer实例。 检查MediaPlayer.create implementation。 我会这样做:

  • 创建新方法playResource(int j,int resource)
  • 在每种情况下R.id.btnX我会调用方法playResource(X,R.raw.Y) - X和Y依赖于btn

playResource方法示例:

private static final String TAG = "MyTag";
playResource(int j, int resource) {
    this.j = j;
    if (player != null) {
        if (player.isPlaying())
            player.stop();
        player.reset();
        //from MediaPlayer implementation (link above)
        try {
            AssetFileDescriptor afd = getResources().openRawResourceFd(resource);
            if (afd == null) return null;
            player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
            afd.close();
            player.prepare();
        } catch (IOException ex) {
            Log.d(TAG, "create failed:", ex);
            // failed: return
        } catch (IllegalArgumentException ex) {
            Log.d(TAG, "create failed:", ex);
            // failed: return
        } catch (SecurityException ex) {
            Log.d(TAG, "create failed:", ex);
            // failed: return
        }
    }
    else {
        //player is null
        //it will create new MediaPlayer instance, setDataSource and call prepare
        player = MediaPlayer.create(this, resource);
    }
    //if everything ok play file
    //in case of any error return from method before (catch)
    player.start();
}

如果您不再需要MediaPlayer,则应该将其发布。例如在onPause()调用中:

if (player != null) {
    player.release();
    player = null;
} 

我没有测试过,所以可能会有错误。希望它有所帮助。

答案 1 :(得分:1)

getSingletonObject()方法应返回MediaPlayer的实例,使用MediaPlayer的默认构造函数创建(不指定资源)。

您可以从主类中的onCreate()调用getSingletonObject()并使用它初始化播放器。

稍后在onClick()中,你应该调用,player.prepare()然后调用player.setDataSource(),传入资源。

因此,您的代码应如下所示:

   public static MediaPlayer getSingletonObject()
  {
    if (ref == null)
        // it's ok, we can call this constructor
        ref = new MediaPlayer();        
    return ref;
  }

在主类中,在onCreate()方法中,

public void onCreate(Bundle savedInstanceState) {
//....
//....
player=SingletonObject.getSingletonObject();
}

希望你能自己弄清楚onClick()中的代码。并且不要忘记在onClick()方法中添加适当的try..catch子句。

希望这会有所帮助!!

答案 2 :(得分:0)

我一直在尝试为自己的项目解决这个问题。我遇到了同样的问题,即播放第二次播放时会让应用程序崩溃。

添加player = new MediaPlayer();解决了这个问题(似乎没有在try-catch块中启动媒体播放器)。

请参阅以下代码:

    playResource(int j, int resource) {
this.j = j;
if (player != null) {
    if (player.isPlaying())
        player.stop();
    player.reset();

    try {
        player = new MediaPlayer(); //added to the code
        AssetFileDescriptor afd = getResources().openRawResourceFd(resource);
        if (afd == null) return null;
        player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
        afd.close();
        player.prepare();
    } catch (IOException ex) {
        Log.d(TAG, "create failed:", ex);
        // failed: return
    } catch (IllegalArgumentException ex) {
        Log.d(TAG, "create failed:", ex);
        // failed: return
    } catch (SecurityException ex) {
        Log.d(TAG, "create failed:", ex);
        // failed: return
    }
}
else {
    //player is null
    //it will create new MediaPlayer instance, setDataSource and call prepare
    player = MediaPlayer.create(this, resource);
}