Intereting Posts
Как обеспечить пользовательскую анимацию во время сортировки (notifyDataSetChanged) в RecyclerView Android. Сохраняйте ранее добавленные намерения дополнительно при переходе к родительской активности. Как настроить несколько сигналов тревоги на Android? Как создать таблицу с границами в Android? Создание ярлыка для любого приложения на рабочем столе Каковы ограничения HTML5-аудио на Android и iOS? Обнаруживать касание EditText, но не прерывать его? Алмазный оператор не поддерживается Максимальный размер приложения для Android Как установить тип ввода как числовое, но также разрешить "-" Android: Получение URI файла из URI контента? Android SwipeRefreshLayout, как реализовать canChildScrollUp, если дочерний элемент не является ListView или ScrollView Программное создание GridLayout из библиотеки поддержки Лучше всего использовать плагины Android Studio или Intellij Idea wth? Android: Google SSO – OAuth или AccountManager? Или оба?

Вращение андроида

Мое приложение предлагает только портретный режим. В портретной деятельности у меня есть полноэкранный VideoView. То, что я хочу сделать, – это поворот VideoView (фактического видео, видеообуфера) на 90 градусов в ландшафтном режиме. Включение активности в режиме Lanscape не является вариантом. Расширение VideoView и поворота холста не будет работать, поскольку SurfaceView не является реальным видом. Есть ли способ достичь этого с помощью видеовидео?

Solutions Collecting From Web of "Вращение андроида"

VideoView не поддерживает поворот видео, даже если композиционная матрица установлена ​​правильно и используется атрибут вращения.

Вы можете использовать TextureView и установить его атрибут rotation = «90» (например). Затем он будет вращать кадры, но соотношение сторон – это то, что вам нужно, чтобы справиться с собой. Для этого вы можете использовать textureView.setScaleX ((screenHeight * 1.0f) / screenWidth)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <TextureView android:id="@+id/playback_video" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true" android:rotation="90" /> </RelativeLayout> 

Он также должен обрабатывать потоковое видео. Но, пожалуйста, подумайте об этом как о примере, а не о выпуске готового кода. Я переименовал некоторые вещи и удалил других, они не имеют отношения к вопросу, и это может сломать что-то, но в целом это практичный пример.

 public class PlaybackActivity extends Activity implements MediaPlayer.OnErrorListener, OnPreparedListener, OnCompletionListener, OnVideoSizeChangedListener, OnBufferingUpdateListener, OnInfoListener, SurfaceTextureListener { private MediaPlayer mediaPlayer; private TextureView videoView; private boolean startedPlayback = false; private boolean playerReady = false; public static final int MEDIA_INFO_NETWORK_BANDWIDTH = 703; private void createMediaPlayer() { mediaPlayer = new MediaPlayer(); } private void releaseMediaPlayer() { if (mediaPlayer != null) { mediaPlayer.setSurface(null); mediaPlayer.release(); mediaPlayer = null; } } public void onCompletion(MediaPlayer mp) { Log.w(TAG, "Video playback finished"); } @Override public boolean onError(MediaPlayer player, int what, int extra) { if (what == MediaPlayer.MEDIA_ERROR_UNKNOWN) { /* * Restart play back in case we did not start anything yet. This may * be the case when we tried to tune in in very first secs of the * broadcast when there is no data yet. */ if (liveBroadcast && mediaPlayer != null && !mediaPlayer.isPlaying() && !startedPlayback) { if (checkCount-- > 0) { mediaPlayer.reset(); checkBroadcast(); } else { Log.w(TAG, "Broadcast finished"); } } else { Log.w(TAG, "No media in stream"); } } else if (what == MediaPlayer.MEDIA_ERROR_SERVER_DIED) { Log.w(TAG, "Media service died unexpectedly"); } else { Log.w(TAG, "Unknown media error"); } return true; } @Override public boolean onInfo(MediaPlayer mp, int what, int extra) { switch (what) { case MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING: Log.w(TAG, "Media is too complex to decode it fast enough."); startedPlayback = true; break; case MEDIA_INFO_NETWORK_BANDWIDTH: Log.w(TAG, "Bandwith in recent past."); break; case MediaPlayer.MEDIA_INFO_BUFFERING_START: Log.w(TAG, "Start of media bufferring."); startedPlayback = true; break; case MediaPlayer.MEDIA_INFO_BUFFERING_END: Log.w(TAG, "End of media bufferring."); startedPlayback = true; break; case MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING: Log.w(TAG, "Media is not properly interleaved."); break; case MediaPlayer.MEDIA_INFO_NOT_SEEKABLE: Log.w(TAG, "Stream is not seekable."); break; case MediaPlayer.MEDIA_INFO_METADATA_UPDATE: Log.w(TAG, "New set of metadata is available."); break; case MediaPlayer.MEDIA_INFO_UNKNOWN: default: Log.w(TAG, "Unknown playback info (" + what + ":" + extra + ")."); break; } return true; } private void startPlayback() { if (mediaPlayer != null) { onLoaded(mediaPlayer); mediaPlayer.start(); } } private void pausePlayback() { if (mediaPlayer != null && mediaPlayer.isPlaying()) mediaPlayer.pause(); } private void resumePlayback() { if (mediaPlayer != null && mediaPlayer.isPlaying()) mediaPlayer.start(); } private void onLoaded(MediaPlayer mp) { } public void onPrepared(MediaPlayer mp) { playerReady = true; startPlayback(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); setContentView(R.layout.playback); videoView = (TextureView) findViewById(R.id.playback_video); videoView.setOnClickListener(videoViewClickHandler); videoView.setSurfaceTextureListener(this); createMediaPlayer(); } @Override protected void onDestroy() { releaseMediaPlayer(); if (surface != null) { surface.release(); surface = null; } super.onDestroy(); } @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { this.surface = new Surface(surface); loadMedia(someurl); } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { if (this.surface != null) { releaseMediaPlayer(); this.surface.release(); this.surface = null; } return true; } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { } @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) { } @Override public void onVideoSizeChanged(MediaPlayer mp, int w, int h) { if (w > 0 && h > 0 && !videoSizeSetupDone) { Log.w(TAG, "Video size changed: " + w + "x" + h); changeVideoSize(w, h); } } private boolean videoSizeSetupDone = false; private void changeVideoSize(int width, int height) { DisplayMetrics metrics = new DisplayMetrics(); RelativeLayout.LayoutParams params; Utils.getScreenMetrics(this, metrics); VideoOrientation orientation = someVideoSource.getVideoOrientation(); if (orientation == LANDSCAPE) { params = new RelativeLayout.LayoutParams(metrics.widthPixels, metrics.heightPixels); } else { float rotation = orientation == BroadcastVideoOrientation.BroadcastVideoFrontCamera ? -90.0f : 90.0f; params = new RelativeLayout.LayoutParams(metrics.heightPixels, metrics.widthPixels); float scale = (width * 1.0f) / (height * 1.0f); videoView.setRotation(rotation); videoView.setScaleX(scale); } params.addRule(RelativeLayout.CENTER_IN_PARENT, -1); videoView.setLayoutParams(params); videoSizeSetupDone = true; } private void loadMedia(String url) { if (surface == null) return; Log.d(App.TAG, "Loading url: " + url); startedPlayback = false; try { mediaPlayer.reset(); mediaPlayer.setSurface(surface); mediaPlayer.setDataSource(url); mediaPlayer.setOnPreparedListener(this); mediaPlayer.setOnCompletionListener(this); mediaPlayer.setOnErrorListener(this); mediaPlayer.setOnVideoSizeChangedListener(this); mediaPlayer.setScreenOnWhilePlaying(true); mediaPlayer.setOnBufferingUpdateListener(this); mediaPlayer.setOnInfoListener(this); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.prepareAsync(); } catch (Exception e) { Log.w(TAG, "Media load failed"); Utils.alert(this, "Playback Error", e.getMessage(), finishHandler); } } } 

Надеюсь это поможет. Я искал это решение довольно долгое время. Пробовал почти все, и это кажется единственным способом.

Вы можете настроить ориентацию по отдельности в манифесте, поэтому ваше видео может отображаться в альбомном (и портретном), пока остальная часть вашего приложения находится в портрете. См. Мой ответ здесь для решения по этому вопросу.