4

シングルトンコードを使用することを提案するいくつかの記事をここで読みました。ユーザーが定義したクリック数に関係なく、シングルトンコードを使用して1つのメディアプレーヤーインスタンスのみを許可したいので、これを読んでサウンドボードに配置しました。

基本的には1つのサウンドだけが必要で、再生中にユーザーが別のボタンをクリックすると、現在のサウンドが停止し、押されたサウンドが再生されます。MediaPlayerインスタンスが1つだけ必要ですが、その実装方法がわかりません。

これが私のコードの基本的な考え方です:

    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

私は自分のプロジェクトのためにこの問題を解決しようとしています。2回目の再生中にアプリがクラッシュするのと同じ問題が発生しました。

追加する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 に答える