1

I tried implementing YouTube API in my Android Application in a ViewPager with multiple videos. The problem is that as soon as I slide to the second video in the ViewPager, I get this error of memory leak:

Service com.google.android.youtube.api.service.YouTubeService has leaked IntentReceiver aeny@5c159ff that was originally registered here. Are you missing a call to unregisterReceiver()?
    android.app.IntentReceiverLeaked: Service com.google.android.youtube.api.service.YouTubeService has leaked IntentReceiver aeny@5c159ff that was originally registered here. Are you missing a call to unregisterReceiver()?
        at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:928)
        at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:725)
        at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1182)
        at android.app.ContextImpl.registerReceiver(ContextImpl.java:1162)
        at android.app.ContextImpl.registerReceiver(ContextImpl.java:1156)
        at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:564)

I searched everywhere on the net, each and every Stack Overflow question but could not rectify the problem. Some places where I took reference from:

Fragment Class

public class YouTubePlayerFragment extends Fragment implements YouTubePlayer.OnInitializedListener {
    YouTubePlayerSupportFragment youtubeFragment;
    YouTubePlayer player;

    String video;

    boolean isFullScreen = false;

    private static final int YOUTUBE_RECOVERY_REQUEST = 1;

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Bundle bundle = getArguments();
        if (bundle != null) {
            video = bundle.getString("video_key");
        }

        return inflater.inflate(R.layout.fragment_youtube_video, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        youtubeFragment = YouTubePlayerSupportFragment.newInstance();

        youtubeFragment.initialize(Config.YOUTUBE_API_KEY, this);
        FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
        transaction.add(R.id.youtube_fragment, youtubeFragment).commit();
    }

    @Override
    public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer youTubePlayer, boolean wasRestored) {
        if (!wasRestored) {
            player = youTubePlayer;
            HomeActivity.youTubePlayerMain = youTubePlayer;
            player.setOnFullscreenListener(new YouTubePlayer.OnFullscreenListener() {
                @Override
                public void onFullscreen(boolean fullscreen) {
                    isFullScreen = fullscreen;
                    HomeActivity.isYouTubePlayerFullScreen = fullscreen;
                }
            });
            player.cueVideo(video);
        }
    }

    @Override
    public void onInitializationFailure(YouTubePlayer.Provider provider, YouTubeInitializationResult errorReason) {
        if (errorReason.isUserRecoverableError())
            errorReason.getErrorDialog(requireActivity(), YOUTUBE_RECOVERY_REQUEST).show();
        else {
            String errorMessage = String.format("There was an error initializing the YouTubePlayer (%1$s)", errorReason.toString());
            Toast.makeText(getActivity(), errorMessage, Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == YOUTUBE_RECOVERY_REQUEST)
            getYouTubePlayerProvider().initialize(Config.YOUTUBE_API_KEY, this);
    }

    private YouTubePlayer.Provider getYouTubePlayerProvider() {
        return youtubeFragment;
    }
}

Adapter Class

public class PageViewerAdapter extends FragmentStatePagerAdapter {
    private List<String> videoList;

    PageViewerAdapter(FragmentManager fm, List<String> videoList) {
        super(fm);
        this.videoList = videoList;
    }

    @Override
    public Fragment getItem(int position) {
        Bundle bundle = new Bundle();
        bundle.putString("video_key", videoList.get(position));
        YouTubePlayerFragment fragment = new YouTubePlayerFragment();
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public int getCount() {
        return videoList.size();
    }
}

Now the problem is, if according to the error, If I use unregisterReceiver(), what should I put in the parameter of this method. I haven't created any Broadcast Receiver.

halfer
  • 19,824
  • 17
  • 99
  • 186
AK-Android
  • 19
  • 2
  • Have you considered this [answer](https://stackoverflow.com/a/50777537/1889768) from your own list of SO questions? As far as I can tell (from the question-posts) the leak only occurs when playing multiple videos at the same time, either wait for the old `YouTubePlayerFragment` to stop before starting in the new `YouTubePlayerFragment`. Or reuse the same `YouTubePlayerFragment` instance which is something you cannot do while implementing `ViewPager`. – Abbas Dec 28 '18 at 18:32
  • Yes, I have tried creating a single instance of `YouTubePlayerFragment` but could not implement it as you also told that we cannot do that in ViewPager. Please can you elaborate about waiting for the old `YouTubePlayerFragment` to stop before starting in the new `YouTubePlayerFragment`. Please can you provide me any sample code or any reference where I can get any help. That would be really helpful as it's really urgent. Thanks – AK-Android Dec 29 '18 at 05:27
  • Please read [Under what circumstances may I add “urgent” or other similar phrases to my question, in order to obtain faster answers?](//meta.stackoverflow.com/q/326569) - the summary is that this is not an ideal way to address volunteers, and is probably counterproductive to obtaining answers. Please refrain from adding this to your questions/comments. – halfer Dec 29 '18 at 10:50
  • Okay, I understand. Was not knowing about this. Thanks – AK-Android Jan 05 '19 at 12:10

0 Answers0