Flutter PIP 插件 ---- 新增PipActivity,Android 11以下支持自动进入PIP Mode

接上文 Flutter PIP 插件 ---- Android
项目地址 PIP, pub.dev也已经同步发布 pip 0.0.3,你的加星和点赞,将是我继续改进最大的动力

开发文档 Add videos using picture-in-picture (PiP)介绍PIP 功能从 Android 8.0 (API level 26) 引入,但是autoEnter 功能从 Android 12 才开始支持,那么不支持的版本呢就需要通过监听 onUserLeaveHint 主动调用 enterPictureInPictureMode 才能进入 PIP Mode ,在之前的版本中因为 FlutterActivity 没有转发 onUserLeaveHint ,导致我们只能在 dart 中通过 flutterdidChangeAppLifecycleState 事件,在应用进入后台是主动调用的方式进入PIP Mode ,但实际测下来,似乎无法区分通知栏下滑的通知,这导致即使应用在前台,当用户下滑通知栏的时候依然会自动进入PIP Mode, 这显然不是我们想要的,优化后的效果如下:

修改PIP插件

  • 新增PipActivity

    java 复制代码
    package org.opentraa.pip;
    
    import android.app.PictureInPictureUiState;
    import android.content.res.Configuration;
    import android.os.Build;
    import androidx.annotation.NonNull;
    import androidx.annotation.RequiresApi;
    import io.flutter.embedding.android.FlutterActivity;
    
    @RequiresApi(Build.VERSION_CODES.O)
    public class PipActivity extends FlutterActivity {
     public interface PipActivityListener {
       void onPictureInPictureModeChanged(boolean isInPictureInPictureMode,
                                         Configuration newConfig);
    
       void onPictureInPictureUiStateChanged(PictureInPictureUiState state);
    
       boolean onPictureInPictureRequested();
    
       void onUserLeaveHint();
     }
    
     private PipActivityListener mListener;
    
     public void setPipActivityListener(PipActivityListener listener) {
       mListener = listener;
     }
    
     // only available in API level 26 and above
     @RequiresApi(26)
     @Override
     public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode,
                                               Configuration newConfig) {
       super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
       if (mListener != null) {
         mListener.onPictureInPictureModeChanged(isInPictureInPictureMode,
                                                 newConfig);
       }
     }
    
     // only available in API level 30 and above
     @RequiresApi(30)
     @Override
     public boolean onPictureInPictureRequested() {
       if (mListener != null) {
         return mListener.onPictureInPictureRequested();
       }
       return super.onPictureInPictureRequested();
     }
    
     // only available in API level 31 and above
     @RequiresApi(31)
     @Override
     public void
     onPictureInPictureUiStateChanged(@NonNull PictureInPictureUiState state) {
       super.onPictureInPictureUiStateChanged(state);
       if (mListener != null) {
         mListener.onPictureInPictureUiStateChanged(state);
       }
     }
    
     @Override
     public void onUserLeaveHint() {
       super.onUserLeaveHint();
       if (mListener != null) {
         mListener.onUserLeaveHint();
       }
     }
    }

    主要思路就是如果PIP 插件的用户想要在 Android 12 以下支持应用进入后台自动进入 PIP Mode 的话,可以将自己 MainActivity 的父类修改为 PipActivity ,这样在 PIP 插件被注册时,可以通过判断传入的 Activity 是否是 PipActivity 来决定是否启用相关的功能。

  • 绑定 ActivityPipController
    PipPluginonAttachedToActivityonReattachedToActivityForConfigChanges 的时候去初始化 PipController

    java 复制代码
    private void initPipController(@NonNull ActivityPluginBinding binding) {
      if (pipController == null) {
        pipController = new PipController(
            binding.getActivity(), new PipController.PipStateChangedListener() {
              @Override
              public void onPipStateChangedListener(
                  PipController.PipState state) {
                // put state into a json object
                channel.invokeMethod("stateChanged",
                                     new HashMap<String, Object>() {
                                       { put("state", state.getValue()); }
                                     });
              }
            });
      } else {
        pipController.attachToActivity(binding.getActivity());
      }
    }
    
    @Override
    public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
      initPipController(binding);
    }
    
    @Override
    public void onReattachedToActivityForConfigChanges(
        @NonNull ActivityPluginBinding binding) {
      initPipController(binding);
    }
  • PipController 构造函数和 attachToActivity 方法中去综合当前的系统版本和绑定的 Activity 进行检查是否支持 autoEnter

    java 复制代码
    public PipController(@NonNull Activity activity,
                         @Nullable PipStateChangedListener listener) {
      setActivity(activity);
      //  ... Other code ...
    }
    
    private boolean checkAutoEnterSupport() {
      // Android 12 and above support to set auto enter enabled directly
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        return true;
      }
    
      // For android 11 and below, we need to check if the activity is kind of
      // PipActivity since we can enter pip mode when the onUserLeaveHint is
      // called to enter pip mode as a workaround
      Activity activity = mActivity.get();
      return activity instanceof PipActivity;
    }
    
    private void setActivity(Activity activity) {
      mActivity = new WeakReference<>(activity);
      if (activity instanceof PipActivity) {
        ((PipActivity)activity).setPipActivityListener(this);
      }
    
      mIsSupported = checkPipSupport();
      mIsAutoEnterSupported = checkAutoEnterSupport();
    }
    
    public void attachToActivity(@NonNull Activity activity) {
      setActivity(activity);
    }

修改Example项目中的MainActivity

  • 孤伶伶的MainActivity

    java 复制代码
    package org.opentraa.pip_example;
    
    import io.flutter.embedding.android.FlutterActivity;
    import org.opentraa.pip.PipActivity;
    
    public class MainActivity extends PipActivity {
    }

如上,至此我们已经支持了全部版本的 PIP Mode autoEnter 功能。

相关推荐
晨陌y4 小时前
深入剖析:仓颉语言的性能优化核心技术
android·性能优化·仓颉
xhbh6664 小时前
【实战总结】MySQL日期加减大全:日期计算、边界处理与性能优化详解
android
00后程序员张4 小时前
如何提高 IPA 安全性 多工具组合打造可复用的 iOS 加固与反编译防护体系(IPA 安全 iOS 加固 无源码混淆 Ipa Guard 实战)
android·安全·ios·小程序·uni-app·iphone·webview
张拭心4 小时前
“不卷 AI、不碰币、下班不收消息”——Android 知名技术大牛 Jake Wharton 的求职价值观
android·前端·aigc
SoaringHeart4 小时前
Flutter疑难解决:单独让某个页面的电池栏标签颜色改变
前端·flutter
西西学代码5 小时前
Flutter---个人信息(3)---实现修改性别
flutter
西西学代码6 小时前
Flutter---ListTile列表项组件
flutter
某空m6 小时前
【Android】DrawerLayout实现侧边导航栏
android
西西学代码7 小时前
Flutter---个人信息(1)---实现简单的UI
开发语言·javascript·flutter
stevenzqzq7 小时前
Android开发工作经历整理
android·简历