### Typical Pip Workflow Example Source: https://github.com/opentraa/pip/blob/main/_autodocs/QUICK-REFERENCE.md Demonstrates the complete lifecycle for using the Pip library, including checking support, setup with options, registering a state observer, starting PiP, and cleanup. ```dart // 1. Check support if (!(await pip.isSupported())) { print('Not supported'); return; } // 2. Setup final options = PipOptions( autoEnterEnabled: await pip.isAutoEnterSupported(), ); if (!(await pip.setup(options))) { print('Setup failed'); return; } // 3. Register observer await pip.registerStateChangedObserver( PipStateChangedObserver( onPipStateChanged: (state, error) { print('State: $state, Error: $error'); }, ), ); // 4. Start await pip.start(); // 5. Cleanup await pip.unregisterStateChangedObserver(); await pip.dispose(); ``` -------------------------------- ### start() Source: https://github.com/opentraa/pip/blob/main/_autodocs/android-native.md Requests entry into PiP mode. It checks for support, current state, and setup completion before attempting to enter PiP. ```APIDOC ## start() ### Description Requests entry into Picture-in-Picture (PiP) mode. This method performs several checks to ensure PiP is supported and the activity is in a state to enter PiP. ### Method ```java public boolean start() ``` ### Returns `boolean` - `true` if the request to enter PiP mode was accepted, `false` otherwise (e.g., not supported, already in PiP, or setup not called). ### Behavior 1. Checks if PiP is supported using `isSupported()`. 2. Checks if PiP mode is already active using `isActived()`. 3. Verifies if PiP has been set up by calling `isPipEnabled()`. 4. Invokes the platform-specific method to enter PiP mode (`activity.enterPictureInPictureMode()`). 5. Returns the result of the entry attempt. ### Platform-Specific Entry - **Android 8+:** `enterPictureInPictureMode(mParamsBuilder.build())` - **Android 7:** `enterPictureInPictureMode()` ``` -------------------------------- ### Verify PiP Setup and Start on Android Source: https://github.com/opentraa/pip/blob/main/_autodocs/integration-guide.md Check if PiP is supported, ensure setup is successful, and start PiP only when the activity is in the foreground. This snippet helps diagnose startup failures. ```dart if (!(await pip.isSupported())) { print('PiP not supported'); return; } final success = await pip.setup(options); if (!success) { print('Setup failed'); return; } if (await pip.isActive()) { print('Already in PiP'); return; } final startSuccess = await pip.start(); print('Start result: $startSuccess'); ``` -------------------------------- ### Check Pip Support and Start Status Source: https://github.com/opentraa/pip/blob/main/_autodocs/integration-guide.md Verify if Pip is supported before proceeding and check the return value of start() to ensure setup was called. Use state callbacks for detailed failure reasons. ```dart // Check before proceeding if (!(await pip.isSupported())) { print('PiP not supported'); return; } // start() returns false if setup not called final success = await pip.start(); if (!success) { print('Start failed; check state callback for reason'); } ``` -------------------------------- ### Setup Parameter Parsing Logic Source: https://github.com/opentraa/pip/blob/main/_autodocs/ios-native.md Demonstrates the parsing logic within `handleMethodCall:result:` for the 'setup' method, specifically extracting `sourceContentView` and `preferredContentSize` from the arguments dictionary. ```objc // sourceContentView and contentView if ([arguments objectForKey:@"sourceContentView"] && [[arguments objectForKey:@"sourceContentView"] isKindOfClass:[NSNumber class]]) { options.sourceContentView = (__bridge UIView *)[[arguments objectForKey:@"sourceContentView"] pointerValue]; } // preferredContentSize if ([arguments objectForKey:@"preferredContentWidth"] && [arguments objectForKey:@"preferredContentHeight"]) { options.preferredContentSize = CGSizeMake( [[arguments objectForKey:@"preferredContentWidth"] floatValue], [[arguments objectForKey:@"preferredContentHeight"] floatValue]); } ``` -------------------------------- ### Build Example Apps Source: https://github.com/opentraa/pip/blob/main/CONTRIBUTING.md Navigate to the example directory and run these commands to build debug APK and iOS release builds when native code changes. ```bash cd example flutter build apk --debug flutter build ios --no-codesign ``` -------------------------------- ### Setup Parameter Parsing Source: https://github.com/opentraa/pip/blob/main/_autodocs/ios-native.md Details how the `setup` method call arguments are parsed from a dictionary into `PipOptions` for configuring the PiP controller. ```APIDOC ## Setup Parameter Parsing When `setup` is called, the method parses the `NSDictionary` arguments and constructs a `PipOptions` object: **Parameters parsed from arguments dictionary:** | Key | Type | Target Property | Notes | |-----|------|-----------------|-------| | `sourceContentView` | `NSNumber` | `PipOptions.sourceContentView` | Pointer value; cast to `UIView*` via bridge. | | `contentView` | `NSNumber` | `PipOptions.contentView` | Pointer value; cast to `UIView*` via bridge. | | `autoEnterEnabled` | `NSNumber` (bool) | `PipOptions.autoEnterEnabled` | Converted to `BOOL`. | | `preferredContentWidth` | `NSNumber` (float) | `PipOptions.preferredContentSize.width` | Converted to `CGFloat`. | | `preferredContentHeight` | `NSNumber` (float) | `PipOptions.preferredContentSize.height` | Converted to `CGFloat`. | | `controlStyle` | `NSNumber` (int) | `PipOptions.controlStyle` | Range 0-3. Default: 0. | **Parsing Logic:** ```objc // sourceContentView and contentView if ([arguments objectForKey:@"sourceContentView"] && [[arguments objectForKey:@"sourceContentView"] isKindOfClass:[NSNumber class]]) { options.sourceContentView = (__bridge UIView *)[[arguments objectForKey:@"sourceContentView"] pointerValue]; } // preferredContentSize if ([arguments objectForKey:@"preferredContentWidth"] && [arguments objectForKey:@"preferredContentHeight"]) { options.preferredContentSize = CGSizeMake( [[arguments objectForKey:@"preferredContentWidth"] floatValue], [[arguments objectForKey:@"preferredContentHeight"] floatValue]); } ``` ``` -------------------------------- ### Start Picture in Picture Mode Source: https://github.com/opentraa/pip/blob/main/_autodocs/api-reference.md Requests the platform to enter Picture in Picture mode. The request may succeed, but the actual state transition is reported asynchronously via state callbacks. On Android, the app must first call `setup()`. On iOS, `start()` only works when the app is in the foreground. ```dart Future start() ``` ```dart final success = await pip.start(); if (success) { print('Start request accepted'); // Wait for state callback to confirm actual entry } ``` -------------------------------- ### start Source: https://github.com/opentraa/pip/blob/main/_autodocs/ios-native.md Starts the Picture-in-Picture mode. ```APIDOC ## start ### Description Starts the Picture-in-Picture mode. ### Method Dart to iOS Method Channel ### Parameters #### Arguments (none) ### Return - **NSNumber** (bool) - Indicates whether starting PiP was successful. ``` -------------------------------- ### Picture in Picture State Lifecycle Diagram Source: https://github.com/opentraa/pip/blob/main/_autodocs/README.md Illustrates the state transitions for Picture in Picture mode, from initial setup to starting, stopping, and handling failures. ```text PipStateStarted ↑ | Initial → isSupported() ← setup() → start() ↓ [Not Supported] ↓ ← stop() ← [in PiP] ↓ PipStateStopped ↑ [User exits PiP] Failures at any step trigger `PipStateFailed` with error message. ``` -------------------------------- ### setup: Source: https://github.com/opentraa/pip/blob/main/_autodocs/ios-native.md Initializes or updates the PiP configuration with the provided options. This method must be called on the main thread. It handles support checks, view resolution, and the initial setup or update of the PiP controller and its associated views. ```APIDOC ## setup: (BOOL) ### Description Initializes or updates PiP configuration with the provided options. Must be called on the main thread. ### Method Objective-C ### Endpoint `- (BOOL)setup:(PipOptions *)options` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **options** (`PipOptions*`) - Required - Configuration object with source view, content view, size, and style. ### Request Example ```objc // Example usage (assuming PipOptions is configured) [pipController setup:options]; ``` ### Response #### Success Response (BOOL) - `true` if setup completed successfully. - `false` if not supported or source view unavailable. #### Response Example ```json { "success": true } ``` ### Error Handling - If `!isSupported`, delegate is invoked with `PipStateFailed` and error "Pip is not supported". - If no source view is available, delegate is invoked with `PipStateFailed` and error "Pip source view is not available". ``` -------------------------------- ### Start PiP Mode Source: https://github.com/opentraa/pip/blob/main/_autodocs/android-native.md Requests entry into PiP mode. Returns true if accepted, false if not supported, already in PiP, or setup not called. Behavior depends on Android version. ```java public boolean start() ``` ```java activity.enterPictureInPictureMode(mParamsBuilder.build()) ``` ```java activity.enterPictureInPictureMode() ``` -------------------------------- ### PipController Setup Failure: Source View Unavailable Source: https://github.com/opentraa/pip/blob/main/_autodocs/errors.md When setup() is called but the source content view cannot be determined (e.g., no sourceContentView provided and no active key window or root view controller), setup() invokes the delegate with PipStateFailed and an error message. The method returns NO. ```objective-c if (!sourceContentView) { [self.delegate pipStateChanged:PipStateFailed error:@"Pip source view is not available"]; return NO; } ``` -------------------------------- ### PipController Setup: Background Thread Dispatch Source: https://github.com/opentraa/pip/blob/main/_autodocs/errors.md If setup() is called from a background thread, the call is re-dispatched to the main thread using dispatch_sync(). Execution blocks until main-thread setup completes. ```objective-c dispatch_sync(dispatch_get_main_queue(), ^{ // Setup code on main thread }); ``` -------------------------------- ### Get Project Dependencies Source: https://github.com/opentraa/pip/blob/main/CONTRIBUTING.md Run this command to fetch all project dependencies after cloning the repository. ```bash flutter pub get ``` -------------------------------- ### PipController Start: App in Background Source: https://github.com/opentraa/pip/blob/main/_autodocs/errors.md Calling start() when the app is in the background returns NO, as PiP cannot be started in this state. Consider using autoEnterEnabled to start PiP upon transitioning to the background. ```objective-c if (UIApplication.sharedApplication.applicationState == UIApplicationStateBackground) { return NO; } ``` -------------------------------- ### PipController Setup Failure: iOS Version < 15 Source: https://github.com/opentraa/pip/blob/main/_autodocs/errors.md If isSupported() returns NO (indicating iOS version is less than 15), setup() invokes the delegate with PipStateFailed and an error message. The method returns NO. ```objective-c if (![PipController isSupported]) { [self.delegate pipStateChanged:PipStateFailed error:@"Pip is not supported"]; return NO; } ``` -------------------------------- ### Get Dependencies and Run Flutter App Source: https://github.com/opentraa/pip/blob/main/example/README.md Use these commands to fetch project dependencies and launch the Flutter application. ```bash flutter pub get flutter run ``` -------------------------------- ### Flutter PiP Video Widget Example Source: https://github.com/opentraa/pip/blob/main/_autodocs/integration-guide.md This widget demonstrates the full integration of the OpenTRAA Pip SDK. It includes checking for PiP support, configuring options like aspect ratio and seamless resizing, registering for state change notifications, and providing UI elements to start and stop PiP mode. Ensure the device and OS support PiP before attempting to use this functionality. ```dart import 'package:flutter/material.dart'; import 'package:pip/pip.dart'; class PipVideoScreen extends StatefulWidget { @override _PipVideoScreenState createState() => _PipVideoScreenState(); } class _PipVideoScreenState extends State { late Pip _pip; PipState? _currentState; String? _error; bool _isSupported = false; @override void initState() { super.initState(); _pip = Pip(); _initializePip(); } Future _initializePip() async { try { // Check support final isSupported = await _pip.isSupported(); final isAutoEnterSupported = await _pip.isAutoEnterSupported(); if (!isSupported) { setState(() { _error = 'PiP not supported on this device'; }); return; } // Configure final options = PipOptions( autoEnterEnabled: isAutoEnterSupported, aspectRatioX: 16, aspectRatioY: 9, seamlessResizeEnabled: true, ); final setupSuccess = await _pip.setup(options); if (!setupSuccess) { setState(() { _error = 'PiP setup failed'; }); return; } // Register observer await _pip.registerStateChangedObserver( PipStateChangedObserver( onPipStateChanged: (state, error) { setState(() { _currentState = state; _error = error; }); }, ), ); setState(() { _isSupported = true; _error = null; }); } catch (e) { setState(() { _error = 'Initialization error: $e'; }); } } Future _startPip() async { try { final success = await _pip.start(); if (!success) { setState(() { _error = 'Failed to start PiP'; }); } } catch (e) { setState(() { _error = 'Error starting PiP: $e'; }); } } Future _stopPip() async { try { await _pip.stop(); } catch (e) { setState(() { _error = 'Error stopping PiP: $e'; }); } } @override void dispose() { _pip.unregisterStateChangedObserver(); _pip.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('PiP Video')), body: Column( children: [ Expanded( child: Container( color: Colors.black, child: Center( child: Text( 'Video Player Here', style: TextStyle(color: Colors.white), ), ), ), ), Padding( padding: EdgeInsets.all(16), child: Column( children: [ if (_error != null) Text( 'Error: $_error', style: TextStyle(color: Colors.red), ), if (_currentState != null) Text('State: $_currentState'), SizedBox(height: 16), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ ElevatedButton( onPressed: _isSupported ? _startPip : null, child: Text('Start PiP'), ), ElevatedButton( onPressed: _isSupported ? _stopPip : null, child: Text('Stop PiP'), ), ], ), ], ), ), ], ), ); } } ``` -------------------------------- ### start Source: https://github.com/opentraa/pip/blob/main/_autodocs/ios-native.md Requests entry into Picture-in-Picture mode. This method initiates the PiP process but is limited to foreground use. For background transitions, consider using `autoEnterEnabled`. ```APIDOC ## start ### Description Requests entry into PiP mode. ### Method Objective-C ### Signature - (BOOL)start ### Returns `BOOL` — `true` if PiP started successfully; `false` otherwise. ### Behavior 1. If called on a background thread, re-dispatches to main thread and returns result. 2. Calls `[_pipController startPictureInPictureAnimated:YES]` on the AVKit controller. 3. Returns the result. ### Limitation Only works when the app is in the foreground. If app is in background, returns `NO` (or does nothing). Use `autoEnterEnabled` to start PiP when transitioning to background. ``` -------------------------------- ### start Source: https://github.com/opentraa/pip/blob/main/_autodocs/api-reference.md Requests the platform to enter Picture in Picture mode. The request may succeed (method returns `true`) but the actual state transition is reported asynchronously via state callbacks. ```APIDOC ## start ### Description Requests the platform to enter Picture in Picture mode. The request may succeed (method returns `true`) but the actual state transition is reported asynchronously via state callbacks. ### Method `Future start()` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```dart final success = await pip.start(); if (success) { print('Start request accepted'); // Wait for state callback to confirm actual entry } ``` ### Response #### Success Response (bool) `true` if the platform accepted the start request; `false` if not supported, already active, or unable to start. A `true` return does not guarantee the window is visible; listen to state callbacks for confirmation. #### Response Example `true` or `false` ### Note On Android, the actual PiP entry depends on system policy. The app must first call `setup()`. On iOS, `start()` only works when the app is in the foreground. Use `autoEnterEnabled` to start PiP when moving to the background. ``` -------------------------------- ### Dart PiP Implementation Source: https://github.com/opentraa/pip/blob/main/_autodocs/integration-guide.md Implement Picture-in-Picture functionality in Dart, including setup, state observation, and starting PiP mode. Ensure PiP is supported before proceeding. ```dart import 'package:pip/pip.dart'; final pip = Pip(); // Check support if (await pip.isSupported()) { // Setup PiP final options = PipOptions( autoEnterEnabled: await pip.isAutoEnterSupported(), aspectRatioX: 16, aspectRatioY: 9, ); await pip.setup(options); // Register observer await pip.registerStateChangedObserver( PipStateChangedObserver( onPipStateChanged: (state, error) { switch (state) { case PipState.pipStateStarted: print('PiP started'); break; case PipState.pipStateStopped: print('PiP stopped'); break; case PipState.pipStateFailed: print('PiP failed: $error'); break; } }, ), ); // Start PiP await pip.start(); } ``` -------------------------------- ### handleMethodCall:result: Source: https://github.com/opentraa/pip/blob/main/_autodocs/ios-native.md Routes Dart method calls to the PiP controller or returns `FlutterMethodNotImplemented` for unknown methods. It handles various PiP operations like checking support, setup, starting, and stopping. ```APIDOC ## handleMethodCall:result: Routes Dart method calls to the PiP controller or returns `FlutterMethodNotImplemented` for unknown methods. ```objc - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result ``` | Parameter | Type | Description | |-----------|------|-------------| | `call` | `FlutterMethodCall*` | Method name and arguments from Dart. | | `result` | `FlutterResult` | Callback to send result back to Dart. | **Method Dispatch:** | Method | Arguments | Controller Method | Return Type | |--------|-----------|------------------|-------------| | `isSupported` | (none) | `isSupported` | `NSNumber` (bool) | | `isAutoEnterSupported` | (none) | `isAutoEnterSupported` | `NSNumber` (bool) | | `isActived` | (none) | `isActived` | `NSNumber` (bool) | | `setup` | `NSDictionary` with options | `setup:` | `NSNumber` (bool) | | `getPipView` | (none) | `getPipView` | `NSNumber` (uint64_t pointer) | | `start` | (none) | `start` | `NSNumber` (bool) | | `stop` | (none) | `stop` | `nil` | | `dispose` | (none) | `dispose` | `nil` | **Unknown Methods:** Returns `FlutterMethodNotImplemented`. ``` -------------------------------- ### setup Source: https://github.com/opentraa/pip/blob/main/_autodocs/api-reference.md Configures Picture in Picture with specified options. This method can be called multiple times to update options. Platform-specific validation is performed at call time. ```APIDOC ## setup ### Description Configures Picture in Picture with specified options. This method can be called multiple times to update options. Platform-specific validation is performed at call time. ### Method `Future setup(PipOptions options)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body * **options** (`PipOptions`) - Required - Configuration object containing platform-specific and generic settings ### Request Example ```dart final options = PipOptions( autoEnterEnabled: true, aspectRatioX: 16, aspectRatioY: 9, ); final success = await pip.setup(options); if (!success) { print('Setup failed'); } ``` ### Response #### Success Response (bool) `true` if setup completed successfully; `false` if not supported or validation failed. #### Response Example `true` or `false` ### Throws * `ArgumentError` - If any validation rules in `PipOptions` are violated (e.g., aspect ratio values <= 0, mismatched property pairs). ``` -------------------------------- ### PipOptions Configuration Source: https://github.com/opentraa/pip/blob/main/_autodocs/types.md Configuration object for Picture in Picture setup, containing both platform-specific and generic options. ```APIDOC ## PipOptions Configuration object for Picture in Picture setup, containing both platform-specific and generic options. **Import:** `package:pip/pip_platform_interface.dart` ### Fields | Field | Type | Required | Platform | Description | |---|---|---|---|---| | `autoEnterEnabled` | `bool?` | No | Both | Enable automatic entry into PiP when app moves to background. Default: `false`. Supported on Android 12+ natively; Android 11 and below require activity extending `PipActivity`. | | `aspectRatioX` | `int?` | Paired | Android | Width component of desired PiP aspect ratio. Must be > 0. Must be provided with `aspectRatioY`. Used to set `PictureInPictureParams.setAspectRatio()` on Android 8+. | | `aspectRatioY` | `int?` | Paired | Android | Height component of desired PiP aspect ratio. Must be > 0. Must be provided with `aspectRatioX`. | | `sourceRectHintLeft` | `int?` | Paired | Android | Left edge coordinate of source rectangle hint. Must be provided with all other `sourceRectHint*` fields or none. Used to set `PictureInPictureParams.setSourceRectHint()` on Android 8+. All four values must be >= 0 and `right` > `left`, `bottom` > `top` (unless all are 0). | | `sourceRectHintTop` | `int?` | Paired | Android | Top edge coordinate of source rectangle hint. | | `sourceRectHintRight` | `int?` | Paired | Android | Right edge coordinate of source rectangle hint. | | `sourceRectHintBottom` | `int?` | Paired | Android | Bottom edge coordinate of source rectangle hint. | | `seamlessResizeEnabled` | `bool?` | No | Android | Enable seamless (crossfade-free) resizing of the PiP window. Default: `false`. Supported on Android 12+. Useful for video content that can scale arbitrarily. | | `useExternalStateMonitor` | `bool?` | No | Android | Enable external polling thread to detect PiP state changes. Default: `false`. Required on Android 11 and below if the activity does not extend `PipActivity` and you need state change callbacks. Polls every `externalStateMonitorInterval` ms. | | `externalStateMonitorInterval` | `int?` | No | Android | Polling interval in milliseconds for external state monitor. Must be > 0. Default: `100`. Only used if `useExternalStateMonitor` is `true`. Smaller values increase accuracy but increase CPU usage. | | `sourceContentView` | `int?` | No | iOS | Pointer (as `int`) to the native source `UIView` for PiP content. If not provided, defaults to the app's root view. | | `contentView` | `int?` | No | iOS | Pointer (as `int`) to the native `UIView` that should be rendered inside the PiP window. Optional; if not set, the PiP window is created but no content is rendered. The content view is inserted into the PiP view after `setup()`. | | `preferredContentWidth` | `int?` | Paired | iOS | Desired width of the PiP window content in pixels. Must be > 0. Must be provided with `preferredContentHeight`. Used to configure the sample buffer display layer in the PiP view. | | `preferredContentHeight` | `int?` | Paired | iOS | Desired height of the PiP window content in pixels. Must be > 0. Must be provided with `preferredContentWidth`. | | `controlStyle` | `int?` | No | iOS | Controls the appearance and behavior of AVKit's system controls in the PiP window. Valid range: 0-3. Default: `0` (show all controls). See iOS Control Styles below. | ### iOS Control Styles The `controlStyle` field accepts the following values: | Value | Description | Behavior | |---|---|---| | 0 | Default | Shows all AVKit system controls: play/pause button, progress bar, timeline. Standard video player interface. | | 1 | Linear playback | Requests documented linear-playback behavior. Sets `requiresLinearPlayback = true`. Disables seeking on the progress bar. | | 2 | Minimal controls | Hides play/pause button and progress bar using private iOS API. Timeline still visible. Increases App Store review risk. May break on future iOS releases. | | 3 | No controls | Hides all system controls using private iOS API. Only the close button remains. Highest App Store review risk. May break on future iOS releases. | Values 2 and 3 rely on private iOS APIs and are preserved for backward compatibility only. They increase the risk of App Store rejection and may stop working on future iOS versions. ``` -------------------------------- ### Configure and Setup PiP Source: https://github.com/opentraa/pip/blob/main/_autodocs/android-native.md Configures the Picture-in-Picture mode with various parameters and initiates state monitoring. Supports aspect ratio, auto-enter, source rect hint, and seamless resize, with platform-specific limitations for certain features. ```java public boolean setup(@Nullable Rational aspectRatio, @Nullable Boolean autoEnterEnabled, @Nullable Rect sourceRectHint, @Nullable Boolean seamlessResizeEnabled, @Nullable Boolean useExternalStateMonitor, @Nullable Integer externalStateMonitorInterval) ``` -------------------------------- ### PipPlatform Instance Management Source: https://github.com/opentraa/pip/blob/main/_autodocs/api-reference.md Details on how to get and set the static instance of PipPlatform, including the use of a security token for custom implementations. ```APIDOC ## PipPlatform Instance Management ### Description Manages the singleton instance of the PipPlatform. You can retrieve the current instance or set a custom implementation. ### Get Instance ```dart final platform = PipPlatform.instance; ``` ### Set Instance Custom implementations must be set using the `instance` setter. A security token is required for custom implementations. ```dart // Assuming CustomPipImplementation extends PipPlatform and has a constructor that accepts the token PipPlatform.instance = CustomPipImplementation(); // A security token is implicitly used or required by the constructor ``` **Note:** Setting an instance without the correct internal token will result in an exception. ``` -------------------------------- ### Handle Validation Errors in Dart Source: https://github.com/opentraa/pip/blob/main/_autodocs/integration-guide.md Catch ArgumentErrors when calling setup() with invalid PipOptions. Ensure all required options are provided. ```dart try { final options = PipOptions( aspectRatioX: 16, // Missing aspectRatioY — will raise ArgumentError ); await pip.setup(options); } on ArgumentError catch (e) { print('Invalid options: ${e.message}'); } ``` -------------------------------- ### Start Picture-in-Picture Source: https://github.com/opentraa/pip/blob/main/_autodocs/ios-native.md Requests entry into PiP mode. Only works when the app is in the foreground. If called on a background thread, it re-dispatches to the main thread. ```objc - (BOOL)start ``` -------------------------------- ### PipState Parsing Examples Source: https://github.com/opentraa/pip/blob/main/_autodocs/types.md Demonstrates how to use the fromNative static method to parse string and integer values into PipState enum instances. Shows handling of valid and invalid inputs. ```dart final state = PipState.fromNative('started'); // pipStateStarted final state2 = PipState.fromNative(0); // pipStateStarted (legacy) final state3 = PipState.fromNative('unknown'); // null ``` -------------------------------- ### Checking Device Capabilities Before Setup Source: https://github.com/opentraa/pip/blob/main/_autodocs/errors.md Before attempting to set up PiP, check if the device supports PiP functionality and specific features like auto-enter. This prevents unnecessary errors and informs the user if a feature is unavailable. ```dart // Check support before calling setup if (!(await pip.isSupported())) { print('PiP not supported on this device'); return; } // Check auto-enter support before using autoEnterEnabled if (!(await pip.isAutoEnterSupported())) { print('Auto-enter not supported; set autoEnterEnabled to false'); } // Proceed with setup final options = PipOptions( autoEnterEnabled: await pip.isAutoEnterSupported(), // ... other options ); await pip.setup(options); ``` -------------------------------- ### PipOptions Class Definition Source: https://github.com/opentraa/pip/blob/main/_autodocs/types.md Defines the configuration object for Picture in Picture setup. It includes platform-specific and generic options for controlling PiP behavior. ```dart class PipOptions { const PipOptions({ this.autoEnterEnabled, // Android only this.aspectRatioX, this.aspectRatioY, this.sourceRectHintLeft, this.sourceRectHintTop, this.sourceRectHintRight, this.sourceRectHintBottom, this.seamlessResizeEnabled, this.useExternalStateMonitor, this.externalStateMonitorInterval, // iOS only this.sourceContentView, this.contentView, this.preferredContentWidth, this.preferredContentHeight, this.controlStyle, }); Map toDictionary(); void _validate(TargetPlatform targetPlatform); } ``` -------------------------------- ### Handle User Leaving Hint Source: https://github.com/opentraa/pip/blob/main/_autodocs/android-native.md Callback invoked when the app moves to the background. On Android 11 and below, it calls start() if autoEnterEnabled is true. On Android 12+, it does nothing. ```java @Override public void onUserLeaveHint() ``` -------------------------------- ### Error Handling Reference Source: https://github.com/opentraa/pip/blob/main/_autodocs/MANIFEST.txt Comprehensive guide to error handling within the Pip Flutter Plugin, covering Dart and native errors. ```APIDOC ## Error Handling Reference ### Dart Validation Errors Details `ArgumentError` cases specific to the Dart side of the plugin, including trigger conditions and expected messages. ### Native Android Error Handling Explains how errors originating from the Android native layer are handled and propagated. ### Native iOS Error Handling Describes the mechanisms for handling and reporting errors that occur within the iOS native implementation. ### Error Recovery Patterns Provides examples and strategies for recovering from various error conditions encountered during plugin usage. ### Error Type Summary A table summarizing all recognized error types, their causes, and recommended actions. ``` -------------------------------- ### Get PiP View Source: https://github.com/opentraa/pip/blob/main/_autodocs/ios-native.md Returns a weak reference to the internal PiP view. Can be used to interact with the PiP view from the app for rendering. ```objc - (UIView *)getPipView ``` -------------------------------- ### iOS-Specific PiP Options and Setup Source: https://github.com/opentraa/pip/blob/main/_autodocs/integration-guide.md Configure iOS-specific Picture-in-Picture behavior, including source and content views, preferred dimensions, and control styles. Use native code for view creation and interaction. ```dart // First, create native views (outside Dart; use native_plugin or similar) // This pseudo-code shows the pattern: // final sourceView = createNativeSourceView(); // UIView* // final contentView = createNativeContentView(); // UIView* // Convert pointers to integers // In Swift: let sourceViewPtr = Int(bitPattern: Unmanaged.passUnretained(sourceView).toOpaque()) // In Objective-C: NSNumber *sourceViewPtr = [NSNumber numberWithUnsignedLongLong:(uint64_t)sourceView]; final options = PipOptions( // Generic autoEnterEnabled: true, // iOS-specific sourceContentView: sourceViewPointer, contentView: contentViewPointer, preferredContentWidth: 400, preferredContentHeight: 300, controlStyle: 0, // 0=default, 1=linear, 2=minimal (private), 3=none (private) ); await pip.setup(options); // Retrieve the PiP view to interact with it final pipViewHandle = await pip.getPipView(); // Use native code to interact with the view at this handle ``` -------------------------------- ### Check PiP Capabilities Source: https://github.com/opentraa/pip/blob/main/README.md Checks if PiP is supported, if auto-enter is supported, and if PiP is currently active. Use these checks before configuring or attempting to start PiP. ```dart final isSupported = await pip.isSupported(); final isAutoEnterSupported = await pip.isAutoEnterSupported(); final isActive = await pip.isActive(); ``` -------------------------------- ### Initialize or Update PiP Configuration Source: https://github.com/opentraa/pip/blob/main/_autodocs/ios-native.md Initializes or updates the PiP configuration. This method must be called on the main thread. It handles support checks, view resolution, and the initial setup or update of the AVPictureInPictureController. ```objc - (BOOL)setup:(PipOptions *)options ``` -------------------------------- ### Handle PiP Crashes on iOS Source: https://github.com/opentraa/pip/blob/main/_autodocs/integration-guide.md Ensure native view pointers are valid and alive before passing them to Dart. Avoid calling `setup()` from background threads by dispatching to the main thread. ```dart // Ensure views are valid and alive // Verify pointers in native code before passing to Dart // Don't call from background thread Future _setupPipFromBackground() async { // Re-dispatch to main thread if needed await runOnUiThread(() async { await pip.setup(options); }); } // Keep views alive class MyApp extends StatefulWidget { late UIView sourceView; late UIView contentView; @override void initState() { super.initState(); // Create views early _createNativeViews(); } void _createNativeViews() { // Native code creates views // Views are stored and passed to pip.setup() } } ``` -------------------------------- ### Setup Picture in Picture Source: https://github.com/opentraa/pip/blob/main/_autodocs/api-reference.md Configures Picture in Picture with specified options. Platform-specific validation is performed at call time. Use this to set initial configuration like aspect ratio and auto-enter behavior. ```dart Future setup(PipOptions options) ``` ```dart final options = PipOptions( autoEnterEnabled: true, aspectRatioX: 16, aspectRatioY: 9, ); final success = await pip.setup(options); if (!success) { print('Setup failed'); } ``` -------------------------------- ### Initialize PiP Plugin Source: https://github.com/opentraa/pip/blob/main/README.md Initializes the PiP plugin. This should be done before any other PiP operations. ```dart import 'package:pip/pip.dart'; final pip = Pip(); ``` -------------------------------- ### PipState Enum Definition Source: https://github.com/opentraa/pip/blob/main/_autodocs/QUICK-REFERENCE.md Defines the possible states for the Picture-in-Picture mode: started, stopped, or failed. ```dart enum PipState { pipStateStarted, // In PiP pipStateStopped, // Not in PiP pipStateFailed, // Error occurred } ``` -------------------------------- ### Managing PipPlatform Instance Source: https://github.com/opentraa/pip/blob/main/_autodocs/api-reference.md Demonstrates how to access the current PipPlatform instance and how to replace it with a custom implementation. Ensure custom implementations are securely set. ```dart // Get the current implementation final platform = PipPlatform.instance; // Replace with custom implementation PipPlatform.instance = CustomPipImplementation(); ``` -------------------------------- ### getPipView Source: https://github.com/opentraa/pip/blob/main/_autodocs/ios-native.md Returns a weak reference to the internal Picture-in-Picture view. This can be used to interact with the PiP view from the app, for example, for rendering purposes. ```APIDOC ## getPipView ### Description Returns a weak reference to the internal PiP view. ### Method Objective-C ### Signature - (UIView *)getPipView ### Returns `UIView* __weak` — Weak reference to the `PipView` instance, or `nil` if not initialized. ### Usage Can be used to interact with the PiP view from the app (e.g., for rendering). ``` -------------------------------- ### Instantiate Pip with Default Options Source: https://github.com/opentraa/pip/blob/main/_autodocs/configuration.md Instantiate the Pip class without any options to use the default configuration. This is equivalent to explicitly setting all PipOptions fields to null. ```dart final pip = Pip(); // Equivalent to: final options = PipOptions( autoEnterEnabled: null, // Disabled by default aspectRatioX: null, // Not set aspectRatioY: null, // Not set // ... all other fields null ); await pip.setup(options); ``` -------------------------------- ### PipState Enum Definition Source: https://github.com/opentraa/pip/blob/main/_autodocs/android-native.md Defines the possible operational states for Picture-in-Picture mode: Started, Stopped, and Failed. Each state has an associated integer value. ```java public enum PipState { Started(0), Stopped(1), Failed(2); private final int value; public int getValue(); } ``` -------------------------------- ### iOS Native Implementation Source: https://github.com/opentraa/pip/blob/main/_autodocs/MANIFEST.txt Reference for the iOS-specific implementation details of the Pip plugin. ```APIDOC ## iOS Native Implementation ### PipPlugin Class Details the `PipPlugin` class, responsible for plugin registration and method dispatch on iOS. ### PipController Class Documents the `PipController` class, focusing on its integration with AVKit and management of Picture-in-Picture functionality on iOS. ### PipView Class Describes the `PipView` class, which handles rendering sample buffers for video display within the Picture-in-Picture context on iOS. ### Delegate Protocols Outlines the delegate protocols used for communication and event handling between different components of the iOS implementation. ### Thread Safety Addresses thread safety considerations, including main-thread enforcement for UI-related operations on iOS. ``` -------------------------------- ### Control PiP Lifecycle Source: https://github.com/opentraa/pip/blob/main/README.md Manages the PiP lifecycle by starting, stopping, and disposing of the PiP session. Call these methods to control the PiP view. ```dart await pip.start(); await pip.stop(); await pip.dispose(); ``` -------------------------------- ### PipOptions Constructor Source: https://github.com/opentraa/pip/blob/main/_autodocs/QUICK-REFERENCE.md Configuration options for the PiP SDK, categorized by platform. ```APIDOC ## PipOptions Constructor ### Description Configuration options for the PiP SDK, categorized by platform. ### Generic Options (Both Platforms) - **autoEnterEnabled** (`bool?`): Enables or disables automatic PiP entry. ### Android-only Options - **aspectRatioX** (`int?`): The X component of the aspect ratio. Must pair with `aspectRatioY`. - **aspectRatioY** (`int?`): The Y component of the aspect ratio. Must pair with `aspectRatioX`. - **sourceRectHintLeft** (`int?`): The left coordinate of the source rectangle hint. Must provide all 4 or none. - **sourceRectHintTop** (`int?`): The top coordinate of the source rectangle hint. Must provide all 4 or none. - **sourceRectHintRight** (`int?`): The right coordinate of the source rectangle hint. Must be greater than `sourceRectHintLeft`. - **sourceRectHintBottom** (`int?`): The bottom coordinate of the source rectangle hint. Must be greater than `sourceRectHintTop`. - **seamlessResizeEnabled** (`bool?`): Enables or disables seamless resizing. - **useExternalStateMonitor** (`bool?`): Enables or disables the use of an external state monitor. - **externalStateMonitorInterval** (`int?`): The interval for the external state monitor. Must be greater than 0. ### iOS-only Options - **sourceContentView** (`int?`): Pointer to the source content view. - **contentView** (`int?`): Pointer to the content view. - **preferredContentWidth** (`int?`): The preferred width of the content. Must pair with `preferredContentHeight`. - **preferredContentHeight** (`int?`): The preferred height of the content. Must pair with `preferredContentWidth`. - **controlStyle** (`int?`): The style of the player controls. Values range from 0 to 3 (0=default, 1=linear, 2/3=private). ``` -------------------------------- ### Get PipState Wire Code Source: https://github.com/opentraa/pip/blob/main/_autodocs/types.md Retrieves the stable string wire protocol code for the current PipState. This is useful for inter-process communication or serialization. ```dart String get code ``` -------------------------------- ### Android Native Implementation Source: https://github.com/opentraa/pip/blob/main/_autodocs/MANIFEST.txt Reference for the Android-specific implementation details of the Pip plugin. ```APIDOC ## Android Native Implementation ### PipPlugin Class Details the `PipPlugin` class, which implements the `FlutterPlugin` interface and handles plugin registration and method dispatch on Android. ### PipController Class Documents the `PipController` class, responsible for managing the plugin's lifecycle, state monitoring, and core logic on Android. ### PipActivity Class Describes the `PipActivity` base class, which supports automatic entry into Picture-in-Picture mode on Android. ### Method Channel Protocol Explains the mapping between Dart method calls and Android native methods, including argument parsing and response handling specific to the Android platform. ``` -------------------------------- ### MethodChannelPip Methods Source: https://github.com/opentraa/pip/blob/main/_autodocs/api-reference.md Provides a list of methods that can be called on the MethodChannelPip class to interact with native PiP functionalities. This includes checking support, managing PiP state, and setting up PiP options. ```APIDOC ## Class: MethodChannelPip Implements the method channel protocol for communicating with native code. ### Methods - **registerStateChangedObserver(PipStateChangedObserver observer)** - Description: Registers an observer to receive PiP state changes. - Arguments: `observer` (PipStateChangedObserver) - **unregisterStateChangedObserver()** - Description: Unregisters the current PiP state change observer. - Returns: `Future` - **isSupported()** - Description: Checks if the PiP feature is supported on the current platform. - Returns: `Future` - **isAutoEnterSupported()** - Description: Checks if the auto-enter PiP feature is supported. - Returns: `Future` - **isActive()** - Description: Checks if the PiP feature is currently active. - Returns: `Future` - **isActived()** - Description: Checks if the PiP feature is currently active (backward compatibility). - Returns: `Future` - **setup(PipOptions options)** - Description: Sets up the PiP feature with the provided options. - Arguments: `options` (PipOptions dictionary) - Returns: `Future` - **getPipView()** - Description: Retrieves the PiP view identifier. Returns 0 for Android. - Returns: `Future` - **start()** - Description: Starts the PiP feature. - Returns: `Future` - **stop()** - Description: Stops the PiP feature. - Returns: `Future` - **dispose()** - Description: Disposes of the PiP feature resources. - Returns: `Future` ### Incoming Methods (from native) - **stateChanged(Map args)** - Description: Receives PiP state changes from the native side. - Arguments: `state` (string code or legacy int), `error` (string, optional) ``` -------------------------------- ### Check Auto-Enter PiP Support Source: https://github.com/opentraa/pip/blob/main/_autodocs/ios-native.md Determines if the automatic Picture-in-Picture start feature is supported. This is available on iOS 15+ devices with PiP support via canStartPictureInPictureAutomaticallyFromInline. ```objc - (BOOL)isAutoEnterSupported ``` -------------------------------- ### PipController Constructor Source: https://github.com/opentraa/pip/blob/main/_autodocs/android-native.md Initializes the PipController with a host activity and an optional listener for PiP state changes. It sets up internal references and performs initial capability checks. ```APIDOC ## PipController Constructor ### Description Initializes the PipController with a host activity and an optional listener for PiP state changes. It sets up internal references and performs initial capability checks. ### Parameters #### Path Parameters - **activity** (Activity) - Required - Host activity. Weak reference stored internally. - **listener** (PipStateChangedListener) - Optional - Listener for state changes. Can be `null`. ### Behavior 1. Calls `setActivity()` to initialize activity and capability checks. 2. Stores the listener. 3. Creates a main-thread Handler for state monitoring. ``` -------------------------------- ### registerStateChangedObserver Source: https://github.com/opentraa/pip/blob/main/_autodocs/api-reference.md Registers a callback observer to receive notifications when the Picture in Picture state changes. This allows your application to react to events such as PiP starting, stopping, or failing. ```APIDOC ## registerStateChangedObserver ### Description Registers a callback observer that receives Picture in Picture state change notifications. ### Method Future ### Parameters #### Path Parameters - observer (`PipStateChangedObserver`) - Required - Observer instance containing the callback handler ### Response #### Success Response (void) Completes when registration is successful. #### Error Handling Propagates errors from the platform implementation if observer registration fails. ### Request Example ```dart final pip = Pip(); await pip.registerStateChangedObserver( PipStateChangedObserver( onPipStateChanged: (state, error) { if (state == PipState.pipStateStarted) { print('PiP started'); } else if (state == PipState.pipStateStopped) { print('PiP stopped'); } else if (state == PipState.pipStateFailed) { print('PiP failed: $error'); } }, ), ); ``` ``` -------------------------------- ### PipController Initialization Source: https://github.com/opentraa/pip/blob/main/_autodocs/ios-native.md Initializes the PiP controller with a state change delegate. This is the primary way to set up the controller for receiving state change notifications. ```APIDOC ## initWith: ### Description Initializes the PiP controller with a state change delegate. ### Method - (instancetype)initWith:(id)delegate ### Parameters #### Parameters - **delegate** (id) - Delegate for state notifications. ### Behavior 1. Calls super `init`. 2. Stores weak reference to delegate. 3. Initializes mutable arrays for constraint tracking. 4. Returns self. ``` -------------------------------- ### Initialize PipController Source: https://github.com/opentraa/pip/blob/main/_autodocs/ios-native.md Initializes the PiP controller with a delegate for receiving state change notifications. Stores a weak reference to the delegate and initializes necessary arrays for constraint tracking. ```objc - (instancetype)initWith:(id)delegate ``` -------------------------------- ### PipState Enum Source: https://github.com/opentraa/pip/blob/main/_autodocs/types.md Enumeration representing the different states of Picture in Picture on the iOS native layer. These states indicate whether PiP has started, stopped, or failed. ```APIDOC ## PipState Enum ### Description Enumeration of Picture in Picture states on the iOS native layer. ### Enum Values - **PipStateStarted** (0) - **PipStateStopped** (1) - **PipStateFailed** (2) ``` -------------------------------- ### Observe PiP State Changes Source: https://github.com/opentraa/pip/blob/main/README.md Registers an observer to receive notifications about PiP state changes. Handle different states like started, stopped, and failed. ```dart await pip.registerStateChangedObserver( PipStateChangedObserver( onPipStateChanged: (state, error) { switch (state) { case PipState.pipStateStarted: break; case PipState.pipStateStopped: break; case PipState.pipStateFailed: debugPrint('PiP failed: $error'); break; } }, ), ); ```