问题
I'm trying to watch RTSP streaming on Android device. But if the server set password for the streaming my Android cannot play it. If without password it's ok. Here is my codes.
public class VideoFragment extends Fragment implements View.OnClickListener, SurfaceHolder.Callback, MediaPlayer.OnPreparedListener {
VideoView m_videoView;
SurfaceView m_surfaceView;
SurfaceHolder m_surfaceHolder;
MediaPlayer m_mediaPlayer;
SharedPreferences m_sharedPref;
Boolean m_videoStarted;
public VideoFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_video, container, false);
m_sharedPref = this.getActivity().getSharedPreferences(MainActivity.class.getSimpleName(), Context.MODE_PRIVATE);
m_surfaceView = (SurfaceView) view.findViewById(R.id.surfaceView);
m_surfaceHolder = m_surfaceView.getHolder();
m_surfaceHolder.addCallback(this);
m_surfaceHolder.setFixedSize(320, 240);
m_videoStarted = false;
ToggleButton togglePlay = (ToggleButton) view.findViewById(R.id.toggleVideo);
togglePlay.setOnClickListener(this);
return view;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.toggleVideo:
if(m_videoStarted == false) {
play();
m_videoStarted = true;
}
else {
m_mediaPlayer.reset();
}
break;
default:
Log.i(AppConfig.TAG, "DEFAULT");
break;
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.e(AppConfig.TAG, "surfaceCreated");
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
m_mediaPlayer.release();
}
@Override
public void onPrepared(MediaPlayer mp) {
Log.e(AppConfig.TAG, "Media Player Prepared");
m_mediaPlayer.start();
}
private void play() {
if(m_mediaPlayer == null) {
m_mediaPlayer = new MediaPlayer();
}
setErrorListener();
m_mediaPlayer.setDisplay(m_surfaceHolder);
m_mediaPlayer.setOnPreparedListener(this);
try {
Map<String, String> headers = createHeaders();
String videoUri = "rtsp://192.168.1.100:554/video/3gpp";
Log.i(AppConfig.TAG, "Video URI: " + videoUri);
m_mediaPlayer.setDataSource(getActivity(), Uri.parse(videoUri), headers);
m_mediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
private void setErrorListener() {
m_mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
if(extra == MediaPlayer.MEDIA_ERROR_IO) {
Log.e(AppConfig.TAG, "MEDIA ERROR");
}
else if(extra == MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
Log.e(AppConfig.TAG, "SERVER DIED ERROR");
}
else if(extra == MediaPlayer.MEDIA_ERROR_UNSUPPORTED) {
Log.e(AppConfig.TAG, "MEDIA UNSUPPORTED");
}
else if(extra == MediaPlayer.MEDIA_ERROR_UNKNOWN) {
Log.e(AppConfig.TAG, "MEDIA ERROR UNKOWN");
}
else if(extra == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) {
Log.e(AppConfig.TAG, "NOT VALID PROGRESSIVE PLAYBACK");
}
else {
Log.e(AppConfig.TAG, String.valueOf(what));
Log.e(AppConfig.TAG, String.valueOf(extra));
Log.e(AppConfig.TAG, "ERROR UNKNOWN!");
}
return false;
}
});
}
private Map<String, String> createHeaders() {
String videoUri = "rtsp://192.168.1.100:554/video/3gpp";
Map<String, String> headers = new HashMap<String, String>();
String camUser = "guest";//m_sharedPref.getString(AppConfig.CAM_USER,"");
String camPassword = "tseug";//m_sharedPref.getString(AppConfig.CAM_PASSWORD,"");
String describe = "DESCRIBE " + videoUri + " RTSP/1.0";
String accept = "application/sdp";
String basicAuthValue = "";
if (camUser != "") {
String credentials = camUser + ":" + camPassword;
byte[] bytes = credentials.getBytes();
int flags = Base64.URL_SAFE|Base64.NO_WRAP;
basicAuthValue = "Basic " + Base64.encodeToString(bytes, flags);
headers.put("Authorization", basicAuthValue);
}
headers.put("Request", describe);
headers.put("Accept", accept);
Log.i(AppConfig.TAG, "Describe: " + describe);
Log.i(AppConfig.TAG, "Authorization: " + basicAuthValue);
Log.i(AppConfig.TAG, "Accept: " + accept);
return headers;
}
}
The IP Camera I use is D-link DCS 942L. I always get 401 response from the camera but my username and password is correct. Here is the log I got
05-25 21:45:31.640 1917-19687/? W/ARTSPConnection﹕ RTSP Response: 401
05-25 21:45:31.640 1917-19687/? I/MyHandler﹕ DESCRIBE completed with result 0 (Success)
05-25 21:45:31.640 1917-19687/? E/MyHandler﹕ Server responses [401] ERROR for the DESCRIBE request
05-25 21:45:31.645 1917-19687/? W/ARTSPConnection﹕ onReceiveResponse >>> State is not CONNECTED !!!
05-25 21:45:31.665 1917-19685/? V/NuPlayer﹕ scanning sources haveAudio=0, haveVideo=0
05-25 21:45:31.665 1917-19685/? V/MediaPlayerService﹕ [152] notify (0x41c61ca0, 100, 1, -2147483648)
05-25 21:45:31.665 19534-19547/com.cameraalert.app V/MediaPlayer﹕ message received msg=100, ext1=1, ext2=-2147483648
05-25 21:45:31.665 19534-19547/com.cameraalert.app E/MediaPlayer﹕ error (1, -2147483648)
05-25 21:45:31.665 19534-19547/com.cameraalert.app V/MediaPlayer﹕ callback application
05-25 21:45:31.665 19534-19547/com.cameraalert.app V/MediaPlayer﹕ back from callback
05-25 21:45:31.665 19534-19534/com.cameraalert.app E/MediaPlayer﹕ Error (1,-2147483648)
05-25 21:45:31.665 19534-19534/com.cameraalert.app E/CameraAlert﹕ 1
05-25 21:45:31.665 19534-19534/com.cameraalert.app E/CameraAlert﹕ -2147483648
05-25 21:45:31.665 19534-19534/com.cameraalert.app E/CameraAlert﹕ ERROR UNKNOWN!
I wonder if my request header is wrong. And there's an article here http://www.tuicool.com/articles/R7ZF7bF about how to play RTSP with authentication using the same camera I use. I will be very thankful for any help or explanation.
回答1:
I'm developing the RTSP related code just like you, and I found the following conclusions:
- When using MediaPlayer, your RTSP_URL can be like: rtsp://account:pass@192.168.0.x
But with the authentication you mentioned, if your camera use HTTP basic auth, you need to add header in http request:, ex(I use OKHTTP 2.0):
String basicAuth = Credentials.basic("account", "pass"); Request request = new Request.Builder().url(url).header("Authorization", basicAuth).build(); Response response = client.newCall(request).execute();
That works for me! Hope it's helpful for you.
来源:https://stackoverflow.com/questions/23855965/android-media-player-rtsp