Search code examples
javaandroidyoutubescreen-orientationandroid-youtube-api

YouTube Android Player API - ExceptionInInitializerError


Note: I'm using the YouTube Android Player API

Expected behavior:

  • The activity remains in portrait mode when the video is not fullscreen (Enforced by AndroidManifest ok).
  • The activity is set to landscape orientation when the video enters fullscreen mode (ok).
  • The activity returns to portrait orientation when the user exits fullscreen mode (ExceptionInInitializerError occurs here).

See the problem in action here

YouTubeFailureRecoveryActivity.java (This is included in the library under sample/src/com/examples/youtubeapidemo)

Main Activity

package test.testapp;

import android.content.pm.ActivityInfo;
import android.os.Bundle;

import com.google.android.youtube.player.YouTubePlayer;
import com.google.android.youtube.player.YouTubePlayerView;

public class MainActivity extends YouTubeFailureRecoveryActivity implements YouTubePlayer.OnFullscreenListener {

    static final String API_KEY = "PLACE YOUTUBE DATA API KEY HERE";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        YouTubePlayerView youTubeView = (YouTubePlayerView) findViewById(R.id.youtube_view);
        youTubeView.initialize(API_KEY, this);
    }

    @Override
    public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer youTubePlayer, boolean wasRestored) {
        youTubePlayer.setOnFullscreenListener(this);
        youTubePlayer.setFullscreenControlFlags(YouTubePlayer.FULLSCREEN_FLAG_CONTROL_SYSTEM_UI);
        if(!wasRestored){
            youTubePlayer.cueVideo("wKJ9KzGQq0w");
        }
    }

    protected YouTubePlayer.Provider getYouTubePlayerProvider() {
        return (YouTubePlayerView) findViewById(R.id.youtube_view);
    }

    @Override
    public void onFullscreen(boolean isFullscreen) {
        if(isFullscreen){
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        }else if(!isFullscreen){
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="test.testapp.MainActivity">

    <com.google.android.youtube.player.YouTubePlayerView
        android:id="@+id/youtube_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    </com.google.android.youtube.player.YouTubePlayerView>

</LinearLayout>

Stack trace

06-10 09:47:09.205 2646-2646/test.testapp E/AndroidRuntime: FATAL EXCEPTION: main
    java.lang.ExceptionInInitializerError
        at android.support.v7.widget.RecyclerView.onSaveInstanceState(SourceFile:201)
        at android.view.View.dispatchSaveInstanceState(View.java:11839)
        at android.view.ViewGroup.dispatchFreezeSelfOnly(ViewGroup.java:2576)
        at android.support.v7.widget.RecyclerView.dispatchSaveInstanceState(SourceFile:220)
        at android.view.ViewGroup.dispatchSaveInstanceState(ViewGroup.java:2562)
        at android.view.ViewGroup.dispatchSaveInstanceState(ViewGroup.java:2562)
        at android.view.ViewGroup.dispatchSaveInstanceState(ViewGroup.java:2562)
        at android.view.ViewGroup.dispatchSaveInstanceState(ViewGroup.java:2562)
        at android.view.ViewGroup.dispatchSaveInstanceState(ViewGroup.java:2562)
        at android.view.ViewGroup.dispatchSaveInstanceState(ViewGroup.java:2562)
        at android.view.ViewGroup.dispatchSaveInstanceState(ViewGroup.java:2562)
        at android.view.View.saveHierarchyState(View.java:11822)
        at com.android.internal.policy.impl.PhoneWindow.saveHierarchyState(PhoneWindow.java:1566)
        at android.app.Activity.onSaveInstanceState(Activity.java:1188)
        at com.google.android.youtube.player.YouTubeBaseActivity.onSaveInstanceState(Unknown Source)
        at android.app.Activity.performSaveInstanceState(Activity.java:1137)
        at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1215)
        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3486)
        at android.app.ActivityThread.access$700(ActivityThread.java:130)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1201)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:4745)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
        at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.NoClassDefFoundError: rt
        at rs.<clinit>(SourceFile:17)
        at android.support.v7.widget.RecyclerView.onSaveInstanceState(SourceFile:201) 
        at android.view.View.dispatchSaveInstanceState(View.java:11839) 
        at android.view.ViewGroup.dispatchFreezeSelfOnly(ViewGroup.java:2576) 
        at android.support.v7.widget.RecyclerView.dispatchSaveInstanceState(SourceFile:220) 
        at android.view.ViewGroup.dispatchSaveInstanceState(ViewGroup.java:2562) 
        at android.view.ViewGroup.dispatchSaveInstanceState(ViewGroup.java:2562) 
        at android.view.ViewGroup.dispatchSaveInstanceState(ViewGroup.java:2562) 
        at android.view.ViewGroup.dispatchSaveInstanceState(ViewGroup.java:2562) 
        at android.view.ViewGroup.dispatchSaveInstanceState(ViewGroup.java:2562) 
        at android.view.ViewGroup.dispatchSaveInstanceState(ViewGroup.java:2562) 
        at android.view.ViewGroup.dispatchSaveInstanceState(ViewGroup.java:2562) 
        at android.view.View.saveHierarchyState(View.java:11822) 
        at com.android.internal.policy.impl.PhoneWindow.saveHierarchyState(PhoneWindow.java:1566) 
        at android.app.Activity.onSaveInstanceState(Activity.java:1188) 
        at com.google.android.youtube.player.YouTubeBaseActivity.onSaveInstanceState(Unknown Source) 
        at android.app.Activity.performSaveInstanceState(Activity.java:1137) 
        at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1215) 
        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3486) 
        at android.app.ActivityThread.access$700(ActivityThread.java:130) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1201) 
        at android.os.Handler.dispatchMessage(Handler.java:99) 
        at android.os.Looper.loop(Looper.java:137) 
        at android.app.ActivityThread.main(ActivityThread.java:4745) 
        at java.lang.reflect.Method.invokeNative(Native Method) 
        at java.lang.reflect.Method.invoke(Method.java:511) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 
        at dalvik.system.NativeStart.main(Native Method) 

Solution

  • Looks like the application is crashing when restarting because of a configuration change

    https://developer.android.com/guide/topics/resources/runtime-changes.html

    You can disable the automatic activity recreation for orientation changes, and handle it yourself.

    To do that, add

    android:configChanges="orientation|screenLayout|screenSize"
    

    With orientation alone it probably works, but the other ones I think were triggered also on some devices.

    You can then override onConfigurationChanged() to do stuff on an orientation change if you need it, like showing / hiding views, etc.. as Android will not recreate your layouts automatically (that's what it does when restarts the activity on an orientation change)

    So you can do:

    @Override
    public void onConfigurationChanged(final Configuration newConfiguration) {
    
          Log.wtf(
            "Orientation", 
            newConfiguration.orientation == Configuration.ORIENTATION_PORTRAIT 
                 ? "portrait"
                 : "landscape"
          );
    
    }