4

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

基本上我只想要一个声音,如果用户在播放过程中单击另一个按钮,它会停止当前声音并播放被按下的声音。我只想要一个 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() 函数带来了问题。我是不是传错了,应该是私有的。

4

3 回答 3

6

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

  • 创建新方法 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;
} 

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

于 2011-10-20T06:34:19.227 回答
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 子句。

希望这可以帮助!!

于 2011-10-20T05:21:29.047 回答
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);
}
于 2012-06-22T21:28:59.753 回答