Android MediaPlayer 单例

发布于 2024-12-11 02:34:22 字数 3688 浏览 1 评论 0原文

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

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

I have read several of the articles on here that suggest using the singleton code, Which I have read and placed into the soundboard as I want to use the singleton code to only allow one mediaplayer instance no matter how many clicks the user defines.

Basically I only want one sound and if the user clicks another button during playback it stops the current sound and plays the one that is pressed. I want only the one MediaPlayer instance but do not understand how to implement it.

Here is the basic idea of my code:

    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();
}

This is what I had to update and change my code too but it is giving me a problem with passing the playresource() function. Am I passing it wrong, should it be private that is passing.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

著墨染雨君画夕 2024-12-18 02:34:23

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

  • 在每种情况下创建新方法 playResource(int j, int resources)
  • 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;
} 

我没有对此进行测试,因此可能会出现错误。希望有帮助。

You don't need a Singleton for that. What are you doing is calling create method every time you want to play a file. That's wrong because you already have MediaPlayer instance.
Check MediaPlayer.create implementation.
I would do like that:

  • create new method playResource(int j, int resource)
  • in every case R.id.btnX i would call method playResource(X, R.raw.Y) - X and Y depends on btn

playResource method example:

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();
}

When you don't need MediaPlayer again, you should release it. For example in onPause() call:

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

I didn't test that so there could be errors. Hope it helps.

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 子句。

希望这有帮助!

The getSingletonObject() method should return an instance of MediaPlayer, created using the default constructor for MediaPlayer (without specifying the resource).

You could call getSingletonObject() from onCreate() in the main class and initialize the player with it.

Later in the onClick(), you should call, player.prepare() and then player.setDataSource(), passing in the resource.

So, your code should look something like the below:

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

In the main class, in the onCreate() method,

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

Hope you can figure out the code in onClick() by yourself. And don't forget to add the appropriate try..catch clauses in the onClick() method.

Hope this helps!!

旧夏天 2024-12-18 02:34:23

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

添加 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);
}

I have been trying to solve this issue for a project of myself. I ran in the same issue that while playing a second playback will let the app crash.

Adding player = new MediaPlayer(); solved the issue (seems no mediaplayer was initiated in the try-catch block).

See the code below:

    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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文