• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.example.android.apis.app;
18 
19 import android.app.Activity;
20 import android.app.PictureInPictureParams;
21 import android.content.res.Configuration;
22 import android.graphics.Rect;
23 import android.net.Uri;
24 import android.os.Bundle;
25 import android.util.Rational;
26 import android.view.Gravity;
27 import android.view.View;
28 import android.widget.Button;
29 import android.widget.FrameLayout;
30 import android.widget.VideoView;
31 
32 import com.example.android.apis.R;
33 
34 public class PictureInPictureSourceRectHint extends Activity {
35 
36     private FrameLayout mFrameLayout;
37     private VideoView mVideoView;
38     private Button mEntryButton;
39     private Button mExitButton;
40 
41     private int mPositionOnEntry;
42     private int mPositionOnExit;
43 
44     @Override
onCreate(Bundle savedInstanceState)45     protected void onCreate(Bundle savedInstanceState) {
46         super.onCreate(savedInstanceState);
47         getActionBar().hide();
48         setContentView(R.layout.picture_in_picture_source_rect_hint);
49 
50         mFrameLayout = findViewById(R.id.frame_layout);
51         mVideoView = findViewById(R.id.video_view);
52         mEntryButton = findViewById(R.id.entry_source_btn);
53         mExitButton = findViewById(R.id.exit_source_btn);
54 
55         initPlayer(Uri.parse("android.resource://" + getPackageName() +
56                 "/" + R.raw.videoviewdemo));
57 
58 
59         setEntryState(Gravity.TOP);
60         setExitState(Gravity.TOP);
61 
62         mEntryButton.setOnClickListener(v -> {
63             // Toggle the position and update the views.
64             setEntryState(mPositionOnEntry == Gravity.TOP ? Gravity.BOTTOM : Gravity.TOP);
65         });
66         mExitButton.setOnClickListener(v -> {
67             // Toggle the position and update the views.
68             setExitState(mPositionOnExit == Gravity.TOP ? Gravity.BOTTOM : Gravity.TOP);
69         });
70 
71         mVideoView.addOnLayoutChangeListener(
72                 (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
73                     if (left == oldLeft && right == oldRight && top == oldTop
74                             && bottom == oldBottom) return;
75 
76                     setPictureInPictureParams(new PictureInPictureParams.Builder()
77                             .setSourceRectHint(getVideoRectHint())
78                             .build());
79                 });
80     }
81 
82     @Override
onDestroy()83     protected void onDestroy() {
84         super.onDestroy();
85         mVideoView.stopPlayback();
86     }
87 
88     @Override
onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig)89     public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode,
90             Configuration newConfig) {
91         mEntryButton.setVisibility(isInPictureInPictureMode ? View.GONE : View.VISIBLE);
92         mExitButton.setVisibility(isInPictureInPictureMode ? View.GONE : View.VISIBLE);
93 
94         final FrameLayout.LayoutParams params;
95         if (isInPictureInPictureMode) {
96             // In PIP mode the video should take up the full width and height.
97             params = new FrameLayout.LayoutParams(
98                     FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
99         } else {
100             // Exiting PIP, return the video to its original size and place it to the preferred
101             // gravity selected before entering PIP mode.
102             params = new FrameLayout.LayoutParams(
103                     FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
104             params.gravity = mPositionOnExit;
105             // The "exit" gravity becomes the current "entry" gravity, update it and its views.
106             setEntryState(mPositionOnExit);
107         }
108         mVideoView.setLayoutParams(params);
109     }
110 
111     @Override
onPictureInPictureRequested()112     public boolean onPictureInPictureRequested() {
113         final Rect hint = getVideoRectHint();
114         enterPictureInPictureMode(new PictureInPictureParams.Builder()
115                 .setSourceRectHint(hint)
116                 .setAspectRatio(new Rational(hint.width(), hint.height()))
117                 .build());
118         return true;
119     }
120 
initPlayer(Uri uri)121     private void initPlayer(Uri uri) {
122         mVideoView.setVideoURI(uri);
123         mVideoView.requestFocus();
124         mVideoView.setOnPreparedListener(mp -> {
125             mp.setLooping(true);
126             mVideoView.start();
127         });
128     }
129 
getVideoRectHint()130     private Rect getVideoRectHint() {
131         final Rect hint = new Rect();
132         mVideoView.getGlobalVisibleRect(hint);
133         return hint;
134     }
135 
setEntryState(int gravity)136     private void setEntryState(int gravity) {
137         mPositionOnEntry = gravity;
138         mEntryButton.setText(getString(
139                 R.string.activity_picture_in_picture_source_rect_hint_current_position,
140                 getGravityName(mPositionOnEntry)));
141         final FrameLayout.LayoutParams p = (FrameLayout.LayoutParams) mVideoView.getLayoutParams();
142         p.gravity = mPositionOnEntry;
143         mVideoView.setLayoutParams(p);
144     }
145 
setExitState(int gravity)146     private void setExitState(int gravity) {
147         mPositionOnExit = gravity;
148         mExitButton.setText(getString(
149                 R.string.activity_picture_in_picture_source_rect_hint_position_on_exit,
150                 getGravityName(mPositionOnExit)));
151     }
152 
getGravityName(int gravity)153     private String getGravityName(int gravity) {
154         return gravity == Gravity.TOP ? "TOP" : "BOTTOM";
155     }
156 }
157