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

    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

    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

    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
    package org.opentraa.pip_example;
    
    import io.flutter.embedding.android.FlutterActivity;
    import org.opentraa.pip.PipActivity;
    
    public class MainActivity extends PipActivity {
    }
    

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值