Flutter PIP 插件 ---- Android
在 Flutter Android 应用中实现画中画功能
画中画(Picture-in-Picture, PiP)模式允许您的应用在一个固定在屏幕角落的小窗口中运行,同时用户可以与其他应用进行交互。本指南将介绍如何在 Flutter Android 应用中实现画中画功能,包括其局限性和解决方案。
项目地址
flutter_pip
前提条件
-
需要 Android 8.0 (API level 26) 或更高版本才能完全支持画中画功能
-
基本的 Flutter 插件开发知识
-
基本的 Android 开发知识
实现概述
实现包含两个主要组件:
-
FlutterPipController
: 处理画中画功能和状态管理 -
FlutterPipPlugin
: 桥接 Flutter 和原生 Android 代码
主要特性
-
画中画模式支持检测
-
自定义宽高比配置
-
平滑过渡的源矩形提示
-
画中画状态监控和回调
-
非视频内容的交叉淡入淡出动画
核心实现
1. 检查画中画支持
在使用画中画之前,我们需要检查设备是否支持:
public boolean isSupported() {Activity activity = mActivity.get();if (activity == null) {return false;}// Requires Android 8.0 (API 26) or higherif (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {return false;}final PackageManager pm = activity.getApplicationContext().getPackageManager();return pm != null && pm.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE);
}
2. 配置画中画参数
画中画模式可以自定义几个参数:
public boolean setup(@Nullable Rational aspectRatio,@Nullable Boolean autoEnterEnabled,@Nullable Rect sourceRectHint) {// ... version checks and null checks ...PictureInPictureParams.Builder builder = new PictureInPictureParams.Builder();if (aspectRatio != null) {builder.setAspectRatio(aspectRatio);}if (sourceRectHint != null) {builder.setSourceRectHint(sourceRectHint);}// Disable seamless resize for non-video contentbuilder.setSeamlessResizeEnabled(false);activity.setPictureInPictureParams(builder.build());
}
Flutter 集成限制和解决方案
1. 自动进入画中画模式限制
Flutter 不正确地委托 Android 生命周期事件,如 onPause
和 onPiPModeChanged
。这给实现自动进入画中画模式带来了挑战。
限制:
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.S)
public boolean isAutoEnterSupported() {// We could support this on Android 12+, but Flutter limitations prevent itreturn false;
}
解决方案:
我们不依赖自动进入画中画模式,而是提供显式的方法来进入和退出画中画模式,这些方法可以从 Flutter 代码中调用:
public boolean start() {if (!isSupported() || isActived() || !isPipEnabled()) {return false;}Activity activity = mActivity.get();if (activity == null) {return false;}activity.enterPictureInPictureMode(mParamsBuilder.build());return true;
}
2. 画中画状态变化检测
由于 Flutter 不提供画中画状态变化事件,我们实现了一个轮询机制来检测状态变化。
解决方案:
private void startStateMonitoring() {// Poll every 100ms to check PiP statemCheckStateTask = new Runnable() {@Overridepublic void run() {checkPipState();mHandler.postDelayed(this, CHECK_INTERVAL_MS);}};mHandler.post(mCheckStateTask);
}
3. 画中画退出处理
Android 不提供直接退出画中画模式的方法。
解决方案:
public void stop() {if (!isSupported() || !isActived()) {return;}Activity activity = mActivity.get();if (activity == null) {return;}// Move the activity to background instead of truly stopping PiPactivity.moveTaskToBack(false);
}
最佳实践
- 资源管理: 始终正确释放资源:
public void dispose() {stopStateMonitoring();mPipParams = null;mParamsBuilder = null;mHandler = null;mLastPipState = false;mCheckStateTask = null;
}
- 状态监控: 跟踪画中画状态变化并通知 Flutter:
private void checkPipState() {boolean currentState = isActived();if (currentState != mLastPipState) {mLastPipState = currentState;notifyPipStateChanged(currentState ? PipState.Started : PipState.Stopped);}
}
- 交叉淡入淡出动画: 对于非视频内容,禁用无缝调整大小:
mParamsBuilder.setSeamlessResizeEnabled(false);
结论
虽然在 Flutter Android 应用中实现画中画功能受到 Flutter 处理 Android 生命周期事件的一些限制,但我们可以通过轮询状态检测和显式控制方法来解决这些问题。这里提供的解决方案提供了一个可靠且稳定的实现,同时保持良好的用户体验。
请记住要在不同的 Android 版本和设备配置上进行全面测试,因为画中画行为在不同的 Android 实现中可能会有所不同。
参考
- Android 官方文档 - 画中画
PS
这个项目会持续维护下去,而且已经在准备发布pub.dev, 目前上面的文档是AI帮助生成的,有些不太准确和完善,但基本路线是对的,后续会持续补充完善。
相关文章:
Flutter PIP 插件 ---- Android
在 Flutter Android 应用中实现画中画功能 画中画(Picture-in-Picture, PiP)模式允许您的应用在一个固定在屏幕角落的小窗口中运行,同时用户可以与其他应用进行交互。本指南将介绍如何在 Flutter Android 应用中实现画中画功能,包括其局限性和解决方案。 项目地址 flutter_p…...
【20250211】字符串:459.重复的子字符串
#方法一:暴力求解法 # class Solution: # def repeatedSubstringPattern(self, s): # n len(s) # substr "" # #只重复一次不算“重复多次” # if n < 1: # return False # else: # …...

【DeepSeek学Cuda】矩阵转置:行读取优先还是列读取优先。
目录 **1. 实现A(按行读取,按列存储)2. 实现B(按列读取,按行存储)**3. 哪种更好 Professional cuda programming5. "当L1缓存被禁用时,所有内存访问都直接指向全局内存(Global …...

如何将3DMAX中的3D文件转换为AutoCAD中的2D图形?
大家好,今天我们来探讨一下如何将3DMAX中的3D文件转换为AutoCAD中的2D图形。无论是出于设计交流、施工准备还是其他实际需求,这种转换在工程设计领域都是一项非常实用的技能。接下来,我将为大家详细介绍几种实现这一转换的方法,帮助大家轻松跨越3D与2D设计之间的鸿沟。让我…...
Softhsm储存安全数据性能整理
目标:存储百万条数据对象 测试方案一:总大小2GB,每个数据对象大小约512KB,总条数4096条; 测试方案一:总大小2GB,每个数据对象大小约256B,总条数8388608条; 测试环境&am…...

【C++】——精细化哈希表架构:理论与实践的综合分析
先找出你的能力在哪里,然后再决定你是谁。 —— 塔拉韦斯特弗 《你当像鸟飞往你的山》 目录 1. C 与哈希表:核心概念与引入 2. 哈希表的底层机制:原理与挑战 2.1 核心功能解析:效率与灵活性的平衡 2.2 哈希冲突的本质&#x…...

【cocos creator】拖拽排序列表
DEMO下载 GameCtrl.ts import ItemCtrl from "./ItemCtrl";const { ccclass, property } cc._decorator;ccclass export default class GameCtrl extends cc.Component {property(cc.Node)content: cc.Node null;property(cc.Node)prefab: cc.Node null;arr []…...

b站——《【强化学习】一小时完全入门》学习笔记及代码(1-3 多臂老虎机)
问题陈述 我们有两个多臂老虎机(Multi-Armed Bandit),分别称为左边的老虎机和右边的老虎机。每个老虎机的奖励服从不同的正态分布: 左边的老虎机:奖励服从均值为 500,标准差为 50 的正态分布,即…...

【Mac排错】ls: command not found 终端命令失效的解决办法
【TroubleShooting on Mac】ls: command not found 终端命令失效的解决办法 A Solution to Solve “Command not found” of Terminal on Mac 一直在使用心爱的MacBook Pro的Terminal,并且为她定制了不同的Profile。 这样,看起来她可以在不同季节&…...
探秘Hugging Face与DeepSeek:AI开源世界的闪耀双子星
目录 一、引言:AI 开源浪潮的澎湃二、Hugging Face:AI 开源社区的基石(一)起源与发展历程(二)核心技术与特色(三)在 AI 领域的广泛应用 三、DeepSeek:东方崛起的 AI 新势…...

SkyWalking 10.1.0 实战:从零构建全链路监控,解锁微服务性能优化新境界
文章目录 前言一、集成SkyWalking二、SkyWalking使用三、SkyWalking性能剖析四、SkyWalking 告警推送4.1 配置告警规则4.2 配置告警通知地址4.3 下发告警信息4.4 测试告警4.5 慢SQL查询 总结 前言 在传统监控系统中,我们通过进程监控和日志分析来发现系统问题&…...

本地部署DeepSeek-R1(Mac版)
本地部署DeepSeek-R1(Mac版) 前言:过年这段时间,DeepSeek火遍全球,但遭受黑客攻击,10次对话基本9次都是服务器繁忙,请稍后重试。那么,本地部署整起来 总体来说,本地部署…...

网易易盾接入DeepSeek,数字内容安全“智”理能力全面升级
今年农历新年期间,全球AI领域再度掀起了一波革命性浪潮,国产通用大模型DeepSeek凭借其强大的多场景理解与内容生成能力迅速“出圈”,彻底改写全球人工智能产业的格局。 作为国内领先的数字内容风控服务商,网易易盾一直致力于探索…...

apachePoi中XSSFClientAnchor图片坐标简述;填充多张图片
概述 业务中经常会遇到在单元格内填充图片的需求,而且要求指定图片在单元格内的位置。 一般都是用的apache的poi,设置图片坐标。 HSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2)dx1 dy1 起始单元…...
Java、Go、Rust、Node.js 的内存占比及优缺点分析
在选择编程语言进行项目开发时,内存占用是一个重要的考量因素。不同语言在内存管理、垃圾回收、并发模型等方面各有特点,影响着它们的内存使用情况。本文将对 Java、Go、Rust 和 Node.js 的内存占比进行对比,并分析它们的优缺点。 1. Java 的…...
C++智能指针的使用
文章目录 智能指针的使用和原理智能指针的使用场景RAII和智能指针C标准库智能指针的使用 智能指针的使用和原理 智能指针的使用场景 1. 下面的程序中,new了以后,我们也delete了,但是因为抛异常导致后面的delete没有得到执行,所以…...
计算机毕业设计——Springboot的社区维修平台旅游管理
📘 博主小档案: 花花,一名来自世界500强的资深程序猿,毕业于国内知名985高校。 🔧 技术专长: 花花在深度学习任务中展现出卓越的能力,包括但不限于java、python等技术。近年来,花花更…...
MySQL ALTER 命令详解
MySQL ALTER 命令详解 引言 MySQL 是一款广泛使用的开源关系数据库管理系统,ALTER 命令在 MySQL 数据库管理中扮演着至关重要的角色。ALTER 命令用于修改现有的数据库、表或列的定义。本文将详细介绍 MySQL ALTER 命令的用法、功能及其在实际应用中的重要性。 ALTER 命令概…...

02、QLExpress从入门到放弃,相关API和文档
QLExpress从入门到放弃,相关API和文档 一、属性开关 public class ExpressRunner {private boolean isTrace;private boolean isShortCircuit;private boolean isPrecise; }/*** 是否需要高精度计算*/ private boolean isPrecise false;高精度计算在会计财务中非常重要&…...

Mp4视频播放机无法播放视频-批量修改视频分辨率(帧宽、帧高)
背景 家人有一台夏新多功能 视频播放器(夏新多功能 视频播放器),用来播放广场舞。下载了一些广场舞视频, 只有部分视频可以播放,其他视频均无法播放,判断应该不是帧速率和数据速率的限制, 分析可能是播放器不支持帧高度大于720的视频。由于视频文件较多,需要借助视频编…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...

【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...
在golang中如何将已安装的依赖降级处理,比如:将 go-ansible/v2@v2.2.0 更换为 go-ansible/@v1.1.7
在 Go 项目中降级 go-ansible 从 v2.2.0 到 v1.1.7 具体步骤: 第一步: 修改 go.mod 文件 // 原 v2 版本声明 require github.com/apenella/go-ansible/v2 v2.2.0 替换为: // 改为 v…...
【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解
一、前言 在HarmonyOS 5的应用开发模型中,featureAbility是旧版FA模型(Feature Ability)的用法,Stage模型已采用全新的应用架构,推荐使用组件化的上下文获取方式,而非依赖featureAbility。 FA大概是API7之…...
手动给中文分词和 直接用神经网络RNN做有什么区别
手动分词和基于神经网络(如 RNN)的自动分词在原理、实现方式和效果上有显著差异,以下是核心对比: 1. 实现原理对比 对比维度手动分词(规则 / 词典驱动)神经网络 RNN 分词(数据驱动)…...
统计学(第8版)——统计抽样学习笔记(考试用)
一、统计抽样的核心内容与问题 研究内容 从总体中科学抽取样本的方法利用样本数据推断总体特征(均值、比率、总量)控制抽样误差与非抽样误差 解决的核心问题 在成本约束下,用少量样本准确推断总体特征量化估计结果的可靠性(置…...
C#最佳实践:为何优先使用as或is而非强制转换
C#最佳实践:为何优先使用as或is而非强制转换 在 C# 的编程世界里,类型转换是我们经常会遇到的操作。就像在现实生活中,我们可能需要把不同形状的物品重新整理归类一样,在代码里,我们也常常需要将一个数据类型转换为另…...