1

我是 Android 开发的新手,我被要求在 Android 中为 Google TV 创建一个应用程序,该应用程序将向用户显示一些直播频道,并在用户选择一个时播放直播。我已经设法做到了,而且工作正常。我使用MediaPlayer播放我的流媒体,而 Channels 大部分时间都可以正常播放。

我已经覆盖了 setOnErrorListener以了解是否有问题。如果有任何错误,这将捕获大部分错误,并且我在显示正确消息后完成()玩家活动。

最初,当流准备就绪时,我在进度条中向用户显示加载消息。在调用setOnPreparedListener侦听器后,我关闭()进度条并启动() MediaPlayer 。

我无法运行 rtsp:// 流。玩了一会儿就挂了。

  1. 进度条仍然存在,应用程序有点卡住了。
  2. 按方向键上的返回按钮也不起作用
  3. 我在setOnErrorListener监听器中没有收到任何错误
  4. 我无法关闭应用程序,因为每当我单击我的应用程序图标时,它都会打开相同的黑色“正在加载”播放器页面..

使用 Android 3.1 (API 12) 并且所有流 URL 都以 rtsp:// 开头

以下是 xml/java 文件的代码:

注意:我复制并更改了 VideoPlayer.java 和 video_player.xml 文件MediaPlayer_Demo 示例

video_player.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#000000">

    <SurfaceView android:id="@+id/surface"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
    </SurfaceView>
</LinearLayout>

错误的 VideoPlayer.Java 如下:

public class VideoPlayer extends Activity implements OnBufferingUpdateListener,
    OnCompletionListener, OnPreparedListener, OnVideoSizeChangedListener,
    SurfaceHolder.Callback, OnErrorListener {

private static final String TAG = "MediaPlayerDemo";
private int mVideoWidth;
private int mVideoHeight;
private MediaPlayer mMediaPlayer;
private SurfaceView mPreview;
private SurfaceHolder holder;
private Bundle extras;
private boolean mIsVideoSizeKnown = false;
private boolean mIsVideoReadyToBePlayed = false;
ProgressDialog progressDialog;

/**
 * 
 * Called when the activity is first created.
 */
@Override
public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.video_player);

    this.extras = getIntent().getExtras();

    mPreview = (SurfaceView) findViewById(R.id.surface);
    holder = mPreview.getHolder();
    holder.addCallback(this);
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

}

private void playVideo() {
    doCleanUp();
    try {

        this.progressDialog = ProgressDialog.show(this, "", "Loading...",
                true);

        // Check Internet Status
        if (!AppStatus.isInternetAvailable(this)) {
            showErrorToUser(getResources().getText(R.string.about_net)
                    .toString(),
                    "Internet connection is not available or Wi-Fi is not enabled.");
        } else {
            // Create a new media player and set the listeners
            String videoStreamUrl = extras.getString("streamUrl");

            if (videoStreamUrl != null) {
                mMediaPlayer = new MediaPlayer();
                mMediaPlayer.setDataSource(videoStreamUrl);
                mMediaPlayer.setDisplay(holder);
                mMediaPlayer.setOnBufferingUpdateListener(this);
                mMediaPlayer.setOnCompletionListener(this);
                mMediaPlayer.setOnPreparedListener(this);
                mMediaPlayer.setOnVideoSizeChangedListener(this);
                mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                mMediaPlayer.setOnErrorListener(this);
                mMediaPlayer.prepareAsync();
            }
            else
            {
                showErrorToUser("Invalid Stream URI",
                        "The Video's URI is not valid. Please provide correct URI.");
            }
        }
    } catch (Exception e) {
        Log.e(TAG, "error: " + e.getMessage(), e);
        errorOccured();
    }
}

public void onBufferingUpdate(MediaPlayer arg0, int percent) {
    Log.d(TAG, "onBufferingUpdate percent:" + percent);

}

public void onCompletion(MediaPlayer arg0) {
    Log.d(TAG, "onCompletion called");
}

public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
    Log.v(TAG, "onVideoSizeChanged called");
    if (width == 0 || height == 0) {
        Log.e(TAG, "invalid video width(" + width + ") or height(" + height
                + ")");
        return;
    }
    mIsVideoSizeKnown = true;
    mVideoWidth = width;
    mVideoHeight = height;
    if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
        startVideoPlayback();
    }
}

public void onPrepared(MediaPlayer mediaplayer) {
    Log.d(TAG, "onPrepared called");
    mIsVideoReadyToBePlayed = true;
    if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
        startVideoPlayback();
    }
}

public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k) {
    Log.d(TAG, "surfaceChanged called");

}

public void surfaceDestroyed(SurfaceHolder surfaceholder) {
    Log.d(TAG, "surfaceDestroyed called");
}

public void surfaceCreated(SurfaceHolder holder) {
    Log.d(TAG, "surfaceCreated called");
    playVideo();
}

@Override
protected void onPause() {
    super.onPause();
    releaseMediaPlayer();
    doCleanUp();
}

@Override
protected void onStop() {
    super.onStop();
    releaseMediaPlayer();
    doCleanUp();
}

@Override
protected void onDestroy() {
    super.onDestroy();
    releaseMediaPlayer();
    doCleanUp();
}

private void releaseMediaPlayer() {
    if (mMediaPlayer != null) {
        mMediaPlayer.release();
        mMediaPlayer = null;
    }
}

private void doCleanUp() {
    mVideoWidth = 0;
    mVideoHeight = 0;
    mIsVideoReadyToBePlayed = false;
    mIsVideoSizeKnown = false;
}

private void startVideoPlayback() {
    Log.v(TAG, "startVideoPlayback");
    holder.setFixedSize(mVideoWidth, mVideoHeight);

    this.progressDialog.dismiss();

    mMediaPlayer.start();
}

public boolean onError(MediaPlayer arg0, int arg1, int arg2) {
    errorOccured();
    return true;
}

private void errorOccured() {
    UserMessage
            .showPopup(
                    this,
                    "Channel not available",
                    "We are sorry for the inconvenience but this channel is not available right now. Please try later.");
}

private void showErrorToUser(String title, String message) {
    // Hide Progress Bar
    this.progressDialog.dismiss();
    releaseMediaPlayer();
    doCleanUp();

    UserMessage.showPopup(this, title, message);
    }
}

我创建了UserMessageAppStatus类来加快开发速度,我从 SO 中学到了它们。这些课程很好,根据我的知识和理解,不会导致任何错误。我提供它们只是为了分享和更好地理解VideoPlayer.java

这些类如下,仅供分享,以便其他人可以使用它们:

用户消息.Java

public class UserMessage {
public static void showPopup(final Activity activity, String title, String message) {

    View view = View.inflate(activity, R.layout.about, null);
    TextView textView = (TextView) view.findViewById(R.id.message);
    textView.setMovementMethod(LinkMovementMethod.getInstance());
    textView.setText(message);
    new AlertDialog.Builder(activity)
            .setTitle(title)
            .setView(view)
            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    activity.finish();
                }
            }).show();
    }
}

应用状态.Java

public class AppStatus {

public static boolean isInternetAvailable(Context context)  {               

    ConnectivityManager mgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = mgr.getActiveNetworkInfo();

    return (netInfo != null && netInfo.isConnected() && netInfo.isAvailable());
    }
}

非常感谢任何帮助,因为我快要完成我的应用程序了。

即使您无法回答我,也感谢您的阅读和思考。

4

1 回答 1

0

The answer to your problem is that while we do support RTSP, it's done in software, not hardware. When you need to rescale it, that too, is done in in software. When you present a fairly large size, like yours, and it needs to be scaled, it under runs. Giving the behavior your seeing. MP4's are a better solution.

于 2012-01-26T22:10:16.103 回答