Skip to content

Commit a7f50c1

Browse files
committed
feat: support pip on Android and iOS
1 parent 46f705b commit a7f50c1

File tree

20 files changed

+1763
-69
lines changed

20 files changed

+1763
-69
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,10 @@ migrate_working_dir/
2727
**/doc/api/
2828
.dart_tool/
2929
build/
30+
31+
# FVM Version Cache
32+
.fvm/
33+
.fvmrc
34+
35+
# VS Code settings
36+
.vscode/

.pubignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test

AUTHORS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Below is a list of people and organizations that have contributed
2+
# to the Flutter project. Names should be added to the list like so:
3+
#
4+
# Name/Organization <email address>
5+
6+
opentraa
7+
Sylar <peilinok@gmail.com>

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
## 0.0.1
22

3-
* TODO: Describe initial release.
3+
* Initial release.
4+
* Add picture in picture support for Android.
5+
* Add picture in picture support for iOS.

LICENSE

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,28 @@
1-
TODO: Add your license here.
1+
BSD 3-Clause License
2+
3+
Copyright (c) 2025, OpenTraa
4+
5+
Redistribution and use in source and binary forms, with or without
6+
modification, are permitted provided that the following conditions are met:
7+
8+
1. Redistributions of source code must retain the above copyright notice, this
9+
list of conditions and the following disclaimer.
10+
11+
2. Redistributions in binary form must reproduce the above copyright notice,
12+
this list of conditions and the following disclaimer in the documentation
13+
and/or other materials provided with the distribution.
14+
15+
3. Neither the name of the copyright holder nor the names of its
16+
contributors may be used to endorse or promote products derived from
17+
this software without specific prior written permission.
18+
19+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.md

Lines changed: 234 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,239 @@
1-
# pip
1+
# Flutter PiP Plugin Usage Guide
22

3-
A new Flutter plugin project.
3+
## Introduction
4+
pip is a Flutter plugin that supports Picture in Picture (PiP) functionality for both Android and iOS. It allows applications to continue displaying content in a small window while in the background.
45

5-
## Getting Started
6+
## Installation
7+
Add the dependency in your `pubspec.yaml`:
8+
```yaml
9+
dependencies:
10+
pip: ^latest_version
11+
```
612
7-
This project is a starting point for a Flutter
8-
[plug-in package](https://flutter.dev/to/develop-plugins),
9-
a specialized package that includes platform-specific implementation code for
10-
Android and/or iOS.
13+
## Platform Specific Setup
1114
12-
For help getting started with Flutter development, view the
13-
[online documentation](https://docs.flutter.dev), which offers tutorials,
14-
samples, guidance on mobile development, and a full API reference.
15+
### Android
1516
17+
Add the following permission to your `AndroidManifest.xml`:
18+
19+
```xml
20+
<activity android:name="VideoActivity"
21+
android:supportsPictureInPicture="true"
22+
android:configChanges=
23+
"screenSize|smallestScreenSize|screenLayout|orientation"
24+
...
25+
```
26+
27+
## Basic Usage
28+
29+
```dart
30+
import 'package:pip/pip.dart';
31+
32+
final _pip = Pip();
33+
```
34+
35+
### 1. Initialization and Feature Check
36+
```dart
37+
// Check if device supports PiP
38+
bool isPipSupported = await _pip.isSupported();
39+
40+
// Check if auto-enter PiP mode is supported
41+
bool isPipAutoEnterSupported = await _pip.isAutoEnterSupported();
42+
43+
// Check if currently in PiP mode
44+
bool isPipActived = await _pip.isActived();
45+
```
46+
47+
### 2. PiP Configuration
48+
```dart
49+
final options = PipOptions(
50+
autoEnterEnabled: true, // Enable/disable auto-enter PiP mode
51+
// Android specific options
52+
aspectRatioX: 16, // Aspect ratio X value
53+
aspectRatioY: 9, // Aspect ratio Y value
54+
sourceRectHintLeft: 0, // Source rectangle left position
55+
sourceRectHintTop: 0, // Source rectangle top position
56+
sourceRectHintRight: 1080, // Source rectangle right position
57+
sourceRectHintBottom: 720, // Source rectangle bottom position
58+
// iOS specific options
59+
sourceContentView: 0, // Source content view
60+
preferredContentWidth: 480, // Preferred content width
61+
preferredContentHeight: 270 // Preferred content height
62+
);
63+
64+
await _pip.setup(options);
65+
```
66+
67+
### 3. PiP State Monitoring
68+
```dart
69+
await _pip.registerStateChangedObserver(
70+
PipStateChangedObserver(
71+
onPipStateChanged: (state, error) {
72+
switch (state) {
73+
case PipState.pipStateStarted:
74+
print('PiP started successfully');
75+
break;
76+
case PipState.pipStateStopped:
77+
print('PiP stopped');
78+
break;
79+
case PipState.pipStateFailed:
80+
print('PiP failed: $error');
81+
break;
82+
}
83+
},
84+
)
85+
);
86+
```
87+
88+
### 4. PiP Lifecycle Management
89+
```dart
90+
// Start PiP mode
91+
await _pip.start();
92+
93+
// Stop PiP mode
94+
await _pip.stop();
95+
96+
// Release PiP resources
97+
await _pip.dispose();
98+
```
99+
100+
## API Reference
101+
102+
### PipOptions
103+
```dart
104+
PipOptions({
105+
bool? autoEnterEnabled, // Enable/disable auto-enter PiP mode
106+
// Android specific options
107+
int? aspectRatioX, // Aspect ratio X value
108+
int? aspectRatioY, // Aspect ratio Y value
109+
int? sourceRectHintLeft, // Source rectangle left position
110+
int? sourceRectHintTop, // Source rectangle top position
111+
int? sourceRectHintRight, // Source rectangle right position
112+
int? sourceRectHintBottom, // Source rectangle bottom position
113+
// iOS specific options
114+
int? sourceContentView, // Source content view
115+
int? preferredContentWidth, // Preferred content width
116+
int? preferredContentHeight // Preferred content height
117+
})
118+
```
119+
120+
### PiP States
121+
```dart
122+
enum PipState {
123+
pipStateStarted, // PiP mode is active
124+
pipStateStopped, // PiP mode is stopped
125+
pipStateFailed // PiP operation failed
126+
}
127+
```
128+
129+
### Core Methods
130+
131+
#### Check PiP Support
132+
```dart
133+
// Check basic PiP support
134+
Future<bool> isSupported()
135+
136+
// Check auto-enter PiP support
137+
Future<bool> isAutoEnterSupported()
138+
139+
// Check if PiP is currently active
140+
Future<bool> isActived()
141+
```
142+
143+
#### PiP Lifecycle Management
144+
```dart
145+
// Setup or update PiP configuration
146+
Future<bool> setup(PipOptions options)
147+
148+
// Start PiP mode
149+
Future<bool> start()
150+
151+
// Stop PiP mode
152+
Future<void> stop()
153+
154+
// Clean up PiP resources
155+
Future<void> dispose()
156+
```
157+
158+
#### State Management
159+
```dart
160+
// Register state change observer
161+
Future<void> registerStateChangedObserver(
162+
PipStateChangedObserver observer
163+
)
164+
165+
// Unregister state change observer
166+
Future<void> unregisterStateChangedObserver()
167+
```
168+
169+
## Platform-Specific Considerations
170+
171+
### Android
172+
- All aspect ratio and source rectangle configurations are Android-specific
173+
- Source rectangle hints help smooth transitions into PiP mode
174+
- `pipStop()` operation only switches the app to background
175+
- Ensure necessary permissions are declared in the app
176+
177+
### iOS
178+
- Content view and dimension settings are iOS-specific
179+
- Call `pipStart()` when the app enters background (`AppLifecycleState.inactive`)
180+
- Call `pipStop()` when the app returns to foreground (`AppLifecycleState.resumed`)
181+
- Recommended to use `autoEnterEnabled` for automatic PiP mode entry
182+
183+
## Best Practices
184+
185+
1. **Platform-Specific Configuration**
186+
```dart
187+
if (Platform.isAndroid) {
188+
options = PipOptions(
189+
aspectRatioX: 16,
190+
aspectRatioY: 9,
191+
);
192+
} else if (Platform.isIOS) {
193+
options = PipOptions(
194+
preferredContentWidth: 480,
195+
preferredContentHeight: 270,
196+
);
197+
}
198+
```
199+
200+
2. **Proper Resource Management**
201+
```dart
202+
@override
203+
void dispose() {
204+
_pip.unregisterStateChangedObserver();
205+
_pip.dispose();
206+
super.dispose();
207+
}
208+
```
209+
210+
3. **Error Handling**
211+
```dart
212+
try {
213+
await _pip.start();
214+
} catch (e) {
215+
print('Error starting PiP: $e');
216+
}
217+
```
218+
219+
## Common Issues
220+
221+
1. **PiP Won't Start**
222+
- Verify device supports PiP
223+
- Confirm PiP parameters are set correctly
224+
- Check error callback messages
225+
226+
2. **Auto-Enter Mode Not Working**
227+
- Confirm device supports auto-enter functionality
228+
- Verify `autoEnterEnabled` setting
229+
230+
3. **PiP Window Ratio Issues**
231+
- Ensure correct aspect ratio settings
232+
- Be aware of platform-specific limitations
233+
234+
## Tips for Implementation
235+
1. Always check device compatibility before enabling PiP features
236+
2. Implement proper error handling for better user experience
237+
3. Consider platform differences when implementing PiP functionality
238+
4. Test thoroughly on both Android and iOS devices
239+
5. Handle app lifecycle changes appropriately

0 commit comments

Comments
 (0)