在 MiniControllerFragment 中调用 super.onCreateView() 时出现 NullPointerException

NullPointerException when calling super.onCreateView() in MiniControllerFragment

在我的应用程序中,我尝试 to implement a MiniControlFragment 当用户决定关闭 ExpandedControlsActivity(迷你控制器的全屏版本)时显示。我需要以编程方式将其添加到 xml 布局,而不是声明性地添加它。

所以我创建了自己的 class 扩展了 MiniControllerFragment:

public class CastControllingFragment extends MiniControllerFragment
{
    @Override
    public View onCreateView(LayoutInflater layoutInflater, ViewGroup viewGroup, Bundle bundle)
    {
        View view = super.onCreateView(layoutInflater, viewGroup, bundle);
        if (view != null) {
            FrameLayout.LayoutParams frameLayoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            view.setLayoutParams(frameLayoutParams);
        }
        return view;
    }

    public static void show(FragmentActivity activity) {
        FragmentManager fragmentManager = activity.getSupportFragmentManager();
        if (fragmentManager.findFragmentById(R.id.castMiniController) == null)
        {
            View rootView = activity.findViewById(R.id.fragment_container);
            if (rootView instanceof ViewGroup)
            {                    
               fragmentManager.beginTransaction().add(R.id.fragment_container, new CastControllingFragment()).commit();
            }
        }
    }

}

我实例化它并将其添加到 ActivityonResume 回调中的片段事务:

    @Override
    protected void onResume() {
        CastControllingFragment.show(this);
        super.onResume();
    }

这是 Activity 的布局,FrameLayout 作为我的片段的容器:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:app="http://schemas.android.com/apk/res-auto"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </FrameLayout>

</RelativeLayout>

但是,当我的 CastControllingFragment 中的 super.onCreateView() 被调用时,我得到以下错误:

java.lang.RuntimeException: Unable to resume activity java.lang.NullPointerException: Attempt to read from null array at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3400) at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3440) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2713) at android.app.ActivityThread.-wrap12(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6077) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

Caused by: java.lang.NullPointerException: Attempt to read from null array at com.google.android.gms.cast.framework.media.widget.MiniControllerFragment.zza(Unknown Source) at com.google.android.gms.cast.framework.media.widget.MiniControllerFragment.onCreateView(Unknown Source) at com.google.sample.cast.refplayer.CastControllingFragment.onCreateView(CastControllingFragment.java:22) at android.support.v4.app.Fragment.performCreateView(Fragment.java:2087) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1113) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1295) at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:801) at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1682) at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:388) at android.support.v4.app.FragmentActivity.onPostResume(FragmentActivity.java:499) at android.support.v7.app.AppCompatActivity.onPostResume(AppCompatActivity.java:175) at android.app.Activity.performResume(Activity.java:6792) at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3377) at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3440)  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2713)  at android.app.ActivityThread.-wrap12(ActivityThread.java)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)  at android.os.Handler.dispatchMessage(Handler.java:102)  at android.os.Looper.loop(Looper.java:154)  at android.app.ActivityThread.main(ActivityThread.java:6077)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

希望对您有所帮助

 private void displayViewFromDrawer(int position, @Nullable String  textTitle) {
    Fragment fragment = null;
    switch (position){
        case 1: //Activity record
            ActivityFragment.newInstance(current_date_string);
            break;
    }
    if (fragment != null) {
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(R.id.content_frame, fragment,"fragment_container");
        ft.addToBackStack(null);
        ft.commit();
    }
}

这是 ActivityFragment 示例

 public class ActivityFragment extends Fragment{
   public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    View v = inflater.inflate(R.layout.fragment_activity_main, container, false);

   //In here you can cast TextViews,Buttons,etc...

   return v;
 }

  public static ActivityFragment newInstance(String date) {
    ActivityFragment fragment = new ActivityFragment();
    Bundle args = new Bundle();
    args.putString("title", date);
    fragment.setArguments(args);
    return fragment;
  }
}

最新的 Cast SDK 发生了变化,导致它与旧版本的 Google Play 服务不兼容(崩溃)。 不幸的是,当使用带有过时 GPS 的最新 Cast SDK(或在模拟器上)时,即使是 Cast 示例应用程序也会崩溃。 该问题已在此处讨论:https://github.com/googlecast/CastVideos-android/issues/12

解决方案是在初始化任何演员组件之前检查 Google 播放服务版本,包括迷你控制器(即你不能只将迷你控制器片段放入你的 xml 布局文件 - 你要么必须动态地给它充气,或者有两个布局文件——一个有你的迷你控制器,一个没有。

检查 GPS 版本的代码:

GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
int resultCode = apiAvailability.isGooglePlayServicesAvailable(context);
isGPSAvailable = (resultCode == ConnectionResult.SUCCESS);

如果结果不是 ConnectionResult.SUCCESS,请不要初始化您的 MiniControllerFragment

此外,请记住 不可能 使用 new MiniControllerFragment() 实例化 MiniControllerFragment。你必须从 xml 给它充气,否则你会得到 NullPointerException.

充气方式有两种MiniControllerFragment:

  1. 创建单独的 xml 布局文件并在您的 Activity.onCreate:

    中扩充适当的布局文件
    setContentView(isGPSAvailable ? R.layout.activity_main_with_controller : R.layout.activity_main_without_controller);
    
  2. 在您的布局中创建指向 MiniControllerFragmentViewStub 并仅在您有播放服务时对其进行膨胀。

activity布局:

<ViewStub
android:id="@+id/cast_minicontroller"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout="@layout/cast_mini_controller_fragment"
/>

cast_mini_controller_fragment:

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/castMiniController"
          class="com.google.android.gms.cast.framework.media.widget.MiniControllerFragment"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:visibility="gone"/>

代码在你的 activity onCreate():

ViewStub miniControllerStub = (ViewStub) findViewById(R.id.cast_minicontroller);
if (isGPSAvailable) {
    miniControllerStub.inflate();
}

我更喜欢 ViewStub 方法,因为它不会重复您的布局。