Truyền âm thanh từ URL trong Android bằng MediaPlayer?


86

Tôi đã cố gắng phát trực tuyến mp3 qua http bằng cách sử dụng lớp MediaPlayer tích hợp sẵn của Android. Tài liệu sẽ gợi ý cho tôi rằng điều này sẽ dễ dàng như sau:

MediaPlayer mp = new MediaPlayer();
mp.setDataSource(URL_OF_FILE);
mp.prepare();
mp.start();

Tuy nhiên tôi nhận được những điều sau đây nhiều lần. Tôi cũng đã thử các URL khác nhau. Xin đừng nói với tôi rằng tính năng phát trực tuyến không hoạt động trên mp3.

E/PlayerDriver(   31): Command PLAYER_SET_DATA_SOURCE completed with an error or info PVMFErrNotSupported
W/PlayerDriver(   31): PVMFInfoErrorHandlingComplete
E/MediaPlayer(  198): error (1, -4)
E/MediaPlayer(  198): start called in state 0
E/MediaPlayer(  198): error (-38, 0)
E/MediaPlayer(  198): Error (1,-4)
E/MediaPlayer(  198): Error (-38,0)

Bất kỳ sự giúp đỡ nào được đánh giá cao, cảm ơn S


Một vài câu hỏi: (1) bạn đang sử dụng phiên bản SDK nào? (2) Bạn đang thử nghiệm trên (những) thiết bị nào? Điều này hoạt động tốt trên SDK 2.0.1, đang thử nghiệm trên Droid.
Roman Nurik

Xin chào Roman, cảm ơn vì đã dành thời gian. Tôi đang thử điều này so với 1.6 và tôi đang sử dụng HTC Hero. Tôi sẽ thử nó trên 2.01 theo ý kiến ​​của bạn nhưng sẽ là một kết quả nực cười nếu điều này chỉ hoạt động trên các thiết bị 2.x trở lên.
Pandalover

Chỉ cần thử nó trên trình giả lập 2.01. Thật không may. Tôi rất muốn thử điều này với thiết bị 1.6 thực và thiết bị 2.01 thực. Tôi đang thử nghiệm Google vào ngày 4. Có lẽ tôi sẽ phải đợi đến lúc đó. Tôi không muốn phải làm vậy.
Pandalover

Tôi không nghi ngờ 2.0 so với 2.0.1 sẽ tạo ra bất kỳ sự khác biệt nào, nhưng trình giả lập so với thiết bị trực tiếp có thể tạo ra sự khác biệt. Tôi ngạc nhiên là điều này không hiệu quả với Anh hùng. Tôi sẽ xem xét nó và xem liệu tôi có thể có câu trả lời tốt hơn hay không. Ngoài ra, chỉ là một kiểm tra sự tỉnh táo, bạn nên đảm bảo rằng bạn đã yêu cầu quyền INTERNET trong tệp kê khai.
Roman Nurik

Này, chỉ cần outta thảo luận, tôi có một câu hỏi. Nếu tôi sử dụng mp.setDataSource (URL_OF_FILE); Chúng tôi không cần lưu bất kỳ tệp nào để phát trực tuyến âm thanh. Phải không? Vì vậy, đó là cách tốt nhất để truyền âm thanh từ bất kỳ vị trí nào. Có ý kiến ​​gì không?
Bohemian

Câu trả lời:


78

Đơn giản Media Player với ví dụ phát trực tuyến. Đối với phần xml, bạn cần một nút với id button1 và hai hình ảnh trong thư mục có thể vẽ của bạn với tên button_pause và button_play và đừng quên thêm quyền truy cập internet vào tệp kê khai của bạn.

public class MainActivity extends Activity {
private Button btn;
/**
 * help to toggle between play and pause.
 */
private boolean playPause;
private MediaPlayer mediaPlayer;
/**
 * remain false till media is not completed, inside OnCompletionListener make it true.
 */
private boolean intialStage = true;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    btn = (Button) findViewById(R.id.button1);
    mediaPlayer = new MediaPlayer();
    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    btn.setOnClickListener(pausePlay);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

private OnClickListener pausePlay = new OnClickListener() {

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        // TODO Auto-generated method stub

        if (!playPause) {
            btn.setBackgroundResource(R.drawable.button_pause);
            if (intialStage)
                new Player()
                        .execute("http://www.virginmegastore.me/Library/Music/CD_001214/Tracks/Track1.mp3");
            else {
                if (!mediaPlayer.isPlaying())
                    mediaPlayer.start();
            }
            playPause = true;
        } else {
            btn.setBackgroundResource(R.drawable.button_play);
            if (mediaPlayer.isPlaying())
                mediaPlayer.pause();
            playPause = false;
        }
    }
};
/**
 * preparing mediaplayer will take sometime to buffer the content so prepare it inside the background thread and starting it on UI thread.
 * @author piyush
 *
 */

class Player extends AsyncTask<String, Void, Boolean> {
    private ProgressDialog progress;

    @Override
    protected Boolean doInBackground(String... params) {
        // TODO Auto-generated method stub
        Boolean prepared;
        try {

            mediaPlayer.setDataSource(params[0]);

            mediaPlayer.setOnCompletionListener(new OnCompletionListener() {

                @Override
                public void onCompletion(MediaPlayer mp) {
                    // TODO Auto-generated method stub
                    intialStage = true;
                    playPause=false;
                    btn.setBackgroundResource(R.drawable.button_play);
                    mediaPlayer.stop();
                    mediaPlayer.reset();
                }
            });
            mediaPlayer.prepare();
            prepared = true;
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            Log.d("IllegarArgument", e.getMessage());
            prepared = false;
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            prepared = false;
            e.printStackTrace();
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            prepared = false;
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            prepared = false;
            e.printStackTrace();
        }
        return prepared;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        if (progress.isShowing()) {
            progress.cancel();
        }
        Log.d("Prepared", "//" + result);
        mediaPlayer.start();

        intialStage = false;
    }

    public Player() {
        progress = new ProgressDialog(MainActivity.this);
    }

    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        super.onPreExecute();
        this.progress.setMessage("Buffering...");
        this.progress.show();

    }
}

@Override
protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    if (mediaPlayer != null) {
        mediaPlayer.reset();
        mediaPlayer.release();
        mediaPlayer = null;
    }
}

Có một vấn đề nhỏ với điều này, nếu tôi khóa điện thoại của mình trong khi MediaPlayer đang phát, ứng dụng của tôi sẽ bị treo khi tôi mở khóa.
CiaranC94

3
Tôi vừa thử nhận xét dòng "mediaPlayer.release ()" trong onPause () và bây giờ ứng dụng của tôi không gặp sự cố khi mở khóa.
CiaranC94

@PiyushMishra tính năng này có được bảng điều khiển dành cho nhà phát triển chấp nhận không? Như ứng dụng của tôi bị từ chối b'coz Tôi đã sử dụng Vitamio 4.x phiên bản
Pallavi

35

Android MediaPlayer không hỗ trợ phát trực tuyến MP3 nguyên bản cho đến phiên bản 2.2. Trong các phiên bản hệ điều hành cũ hơn, nó dường như chỉ phát trực tuyến 3GP nguyên bản. Bạn có thể thử mã pocketjourney, mặc dù nó đã cũ (có phiên bản mới ở đây ) và tôi đã gặp khó khăn khi làm cho nó dính - nó sẽ nói lắp mỗi khi nạp đầy bộ đệm.

Ứng dụng NPR News dành cho Android là nguồn mở và sử dụng máy chủ proxy cục bộ để xử lý phát trực tuyến MP3 trong các phiên bản của HĐH trước 2.2. Bạn có thể xem mã liên quan trong các dòng 199-216 (r94) tại đây: http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/ PlaybackService.java?r=7cf2352b5c3c0fbcdc18a5a8c67d836577e7e8e3

Và đây là lớp StreamProxy: http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/StreamProxy.java?r=e4984187f45c39a54ea6c88f71197762dbe10e72

Ứng dụng NPR đôi khi vẫn gặp "lỗi (-38, 0)" khi phát trực tuyến. Đây có thể là sự cố phân luồng hoặc sự cố thay đổi mạng. Kiểm tra trình theo dõi vấn đề để biết các bản cập nhật .


Bạn có hoàn toàn chắc chắn về điều này? Sự hiểu biết của tôi là nó liên quan đến thể loại kịch câm. Bạn có thể kiểm tra xem t có hoạt động với đúng loại MIME trước 2.1 không? Tôi đang làm việc khác ngay bây giờ và không thể kiểm tra trong một thời gian.
Pandalover

1
Theo ghi chú phát hành 2.2 ( developer.android.com/sdk/android-2.2-highlights.html ), nó bao gồm "Khung phương tiện mới (Stagefright) hỗ trợ phát lại tệp cục bộ và phát trực tuyến liên tục HTTP". Trong tất cả các thử nghiệm của tôi, tôi không thể nhận được thiết bị 2.1 phát trực tiếp từ máy chủ hét lên. Tôi tin rằng vấn đề là các máy chủ hét lên trả về một giao thức ICY / 1.1 thay vì HTTP / 1.1 và trình phát đa phương tiện truy cập vào điều này vì nó không biết cách phản hồi nội dung đó.
jwadsack

@jwadsack điều gì sẽ xảy ra nếu các tệp âm thanh phải được tải xuống một lần và người dùng cũng có thể phát tệp ngoại tuyến?
Devendra Singh

@DevendraSingh Tôi không biết liệu bạn có thể lưu tệp trong khi nó đang phát trực tuyến với việc triển khai trình phát đa phương tiện hiện tại hay không (câu trả lời này đã gần 5 năm tuổi và rất nhiều thay đổi kể từ phiên bản 2.2). Nếu không có gì khác, bạn có thể xây dựng một proxy theo ví dụ này và ghi tệp vào bộ nhớ trong khi bạn chuyển nó qua proxy.
jwadsack

11

Tôi đoán rằng bạn đang cố gắng chơi trực tiếp .pls hoặc thứ gì đó tương tự.

thử thứ này đi:

1: mã

mediaPlayer = MediaPlayer.create(this, Uri.parse("http://vprbbc.streamguys.net:80/vprbbc24.mp3"));
mediaPlayer.start();

2: tệp .pls

URL này là của BBC chỉ là một ví dụ. Đó là một tệp .pls mà tôi đã tải xuống trên linux bằng

wget http://foo.bar/file.pls

và sau đó tôi đã mở bằng vim (sử dụng trình soạn thảo yêu thích của bạn;) và tôi đã thấy các URL thực bên trong tệp này. Thật không may, không phải tất cả .pls đều là văn bản thuần túy như vậy.

Tôi đã đọc rằng 1.6 sẽ không hỗ trợ phát trực tuyến mp3 qua http, nhưng tôi vừa thử nghiệm mã obove với android 1.6 và 2.2 và không gặp vấn đề gì.

chúc may mắn!


7
Hãy nhớ rằng nếu bạn muốn phát trực tuyến nhạc, bạn phải sử dụng mediaplayer.prepareAsync chứ không phải mediaplayer.prepare. Do đó, bạn không thể sử dụng mediaplayer.create () vì bất kỳ hàm nào trong số các hàm .create () đưa đối tượng Media Player của bạn trực tiếp vào trạng thái Đã chuẩn bị, từ đó bạn không thể gọi chuẩn bị sẵn sàng để truyền trực tuyến. developer.android.com/reference/android/media/MediaPlayer.html
marienke

4

Sử dụng

 mediaplayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
 mediaplayer.prepareAsync();
 mediaplayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
      @Override
      public void onPrepared(MediaPlayer mp) {
          mediaplayer.start();
      }
 });

2

Tôi đã gặp lỗi tương tự như bạn gặp phải và hóa ra không có gì sai với mã. Vấn đề là máy chủ web đã gửi sai tiêu đề Loại-Nội dung.

Thử wirehark hoặc thứ gì đó tương tự để xem máy chủ web đang gửi loại nội dung nào.


cho mp3-files cần Content-Type: / mpeg audio Đó giải quyết vấn đề của tôi :)
doep

1
Bạn đã phát trực tuyến tệp đó như thế nào?
Nauman Khalid

2

Xem xét các dự án của tôi:

  1. https://github.com/master255/ImmortalPlayer Hỗ trợ http / FTP, Một luồng để đọc, gửi và lưu vào dữ liệu bộ nhớ cache. Cách đơn giản nhất và làm việc nhanh nhất. Logic phức tạp - cách tốt nhất!
  2. https://github.com/master255/VideoViewCache Videoview đơn giản với bộ nhớ cache. Hai chủ đề để chơi và lưu dữ liệu. Logic tồi, nhưng nếu bạn cần thì hãy sử dụng cái này.

1

Không gọi mp.start với OnPreparedListener để tránh trạng thái 0 trên nhật ký ..


Tôi vẫn nhận được dòng nhật ký 05-22 20: 26: 13.625: E / MediaPlayer (23818): dừng được gọi ở trạng thái 0 ngay cả khi tôi khởi động Media Player của mình trong hàm chuẩn bị (). Tôi cũng có chức năng onError nơi tôi đặt lại đối tượng Media Player. Vẫn cần tới 2 phút để luồng của tôi bắt đầu phát. Xem câu hỏi của tôi tại đây: stackoverflow.com/questions/16672568/…
marienke
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.