1

I am creating an android tv app in the app I am sliding infinity loop fragments (Image and Video URLs ). I use glide for image loading and exoplayer2 for video loading it's working perfectly in my emulator and other 2-3 devices but when I run it in my actual android tv it keeps crashing after some time with an error memory exception. I tested it In emulator using profiler how much memory it using but it is only using min 100 Mb not bigger than that I even check for a leak using leak cannery no leak was found I can't find any solution can someone please help me

Fragment:

`public class BannerFragment extends Fragment {

/*TODO TAGs*/
private String TAG = BannerFragment.class.getSimpleName();

/*TODO View Binding*/
private BannerFragmentBinding vb;

private PromotionalBanner promotionalBanner;
private int position;
private ArrayList<PromotionalBanner> promotionalBannerArrayList;
private CountDownTimer timer;


SimpleExoPlayer simpleExoPlayer;

private final String VIDEO_BUFFER_TIMER = "10000";


/*TODO Glide Listener*/
private RequestListener requestListener = new RequestListener<Drawable>() {
    @Override
    public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
        if (vb != null) {
            ShowToast(" Can't load image ");
            vb.avi.setVisibility(View.GONE);
            slideNextItem();

        }
        return false;
    }

    @Override
    public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
        if (vb != null) {

            vb.avi.setVisibility(View.GONE);
        }
        return false;
    }

};


/*TODO PlayerListener*/
private Player.Listener playerListener = new Player.Listener() {
    @Override
    public void onIsPlayingChanged(boolean isPlaying) {
        Log.e(TAG, "onIsPlayingChanged: " + isPlaying);
    }

    @Override
    public void onPlaybackStateChanged(int playbackState) {

        if (playbackState == Player.STATE_ENDED) {
            slideNextItem();

        } else if (playbackState == Player.STATE_READY) {

            vb.avi.setVisibility(View.GONE);
            if (timer != null) {
                timer.cancel();
                timer = null;
            }
            Log.e("TimerCheck", "onPlaybackStateChanged: endTimer  "+timer );

        } else if (playbackState == Player.STATE_BUFFERING) {

            vb.avi.setVisibility(View.VISIBLE);

            setSlideTimer(VIDEO_BUFFER_TIMER);
            Log.e("TimerCheck", "onPlaybackStateChanged: startTimer    "+timer );

        } else if (playbackState == Player.STATE_IDLE) {

            slideNextItem();


        }
    }

    @Override
    public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) {

    }
};


/*TODO get Fragment Instant*/
public static Fragment getInstantFragment(PromotionalBanner promotionalBanner,
                                          int index,
                                          ArrayList<PromotionalBanner> promotionalBannerArrayList) {


    BannerFragment fragment = new BannerFragment();
    Bundle bundle = new Bundle();
    bundle.putParcelable("promotionalBanner", promotionalBanner);
    bundle.putInt("position", index);
    bundle.putParcelableArrayList("list", promotionalBannerArrayList);
    fragment.setArguments(bundle);


    return fragment;
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    this.promotionalBanner = getArguments().getParcelable("promotionalBanner");
    this.position = getArguments().getInt("position");
    this.promotionalBannerArrayList = getArguments().getParcelableArrayList("list");

}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    vb = BannerFragmentBinding.inflate(getLayoutInflater());
    return vb.getRoot();
}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onResume() {
    super.onResume();


    if (!isImageFile(promotionalBanner.getMedia())) {
        showVideoViewContainer();

        setVideo(promotionalBanner);
    } else {

        hideVideoViewContainer();

        loadImage(promotionalBanner.getMedia(), promotionalBanner.getDuration());
        /*TODo set image Timer*/
        setSlideTimer(promotionalBanner.getDuration());

    }

}


/*TODO setVideo*/
private void setVideo(PromotionalBanner promotionalBanner) {

    Uri uri = Uri.parse(promotionalBanner.getMedia());
    Log.e("dataUriTest", "setVideo: " + uri);
    simplePlayer(uri);


}


/*TODO Simple Player*/
private void simplePlayer(Uri uri) {

    simpleExoPlayer = new SimpleExoPlayer.Builder(getContext()).build();
    simpleExoPlayer.addMediaItem(MediaItem.fromUri(uri));

    setSlideTimer(VIDEO_BUFFER_TIMER);
    Log.e("TimerCheck", "onPlaybackStateChanged:insideSimplePlayer startTimer    "+timer );

    vb.avi.setVisibility(View.VISIBLE);
    vb.videoView.hideController();
    vb.videoView.setPlayer(simpleExoPlayer);
    simpleExoPlayer.prepare();
    simpleExoPlayer.setPlayWhenReady(true);
    simpleExoPlayer.addListener(playerListener);


}

/*TODO Go To next From vide Slide*/
private void slideNextItem() {

    if(simpleExoPlayer != null){
        simpleExoPlayer.release();
        simpleExoPlayer = null;
    }
    int nextposition = position + 1;
    goToNextItem(nextposition);


}


@Override
public void onPause() {
    super.onPause();
    Log.e("LogBannerFragment", "onPause: ");

    if (timer != null) {

        timer.cancel();
    }



    if (simpleExoPlayer != null) {


        simpleExoPlayer.release();
        simpleExoPlayer = null;

    }



}

@Override
public void onDestroy() {
    super.onDestroy();
    Log.e("Destory", "onDestroy: " );
    if (playerListener != null) {
        playerListener = null;
    }

    if (requestListener != null) {
        requestListener = null;

    }


    if (vb != null) {
        vb = null;
    }



}


@Override
public void onDestroyView() {
    super.onDestroyView();


}


/*TODO load Image*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void loadImage(String media, String duration) {

    vb.avi.setVisibility(View.VISIBLE);

    Glide.with(getContext()).load(convert_http_https(media))
            .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
            .error(getContext().getDrawable(R.drawable.banner))
            .addListener(requestListener)

            .into(vb.imageView);


}


/*TODO convert url http to https in android studio*/
private String convert_http_https(String url) {

    String original;

    if (url.contains("https")) {
        original = url;
    } else {
        original = url.replace("http", "https");
    }

    return original;
}


/*TODO set Image timer*/
private void setSlideTimer(String duration) {


    timer = new CountDownTimer(Integer.parseInt(duration), 1000) {
        @Override
        public void onTick(long millisUntilFinished) {

        }

        @Override
        public void onFinish() {
            int nextPosition = position + 1;

// int nextPosition = DispolyActivity.vb.viewPager.getCurrentItem()+1;

            goToNextItem(nextPosition);


        }
    };
    timer.start();
}


/*TODO Next Position in arrayList*/
private void goToNextItem(int nextPosition) {

    HandlerCompat.createAsync(Looper.getMainLooper())
            .post(() ->

                    DispolyActivity.vb.viewPager.setCurrentItem(nextPosition)
            );
}

/*TODO is image file*/
public static boolean isImageFile(String path) {
    String mimeType = URLConnection.guessContentTypeFromName(path);
    return mimeType != null && mimeType.startsWith("image");
}


/*TODO Video view Container*/
private void showVideoViewContainer() {
    Log.e("datashow", "showVideoViewContainer: "+vb);
    vb.videoContainer.setVisibility(View.VISIBLE);
    vb.imageView.setVisibility(View.GONE);

}

/*TODO hide video view Container*/
private void hideVideoViewContainer() {


    vb.videoContainer.setVisibility(View.GONE);
    vb.imageView.setVisibility(View.VISIBLE);


}

/*TODO show Toast*/
private void ShowToast(String msg) {


    Toast.makeText(getContext(), msg, Toast.LENGTH_LONG).show();

}

}

`

My Adapter for slide fragment :

public class SliderAdapter extends FragmentStatePagerAdapter {

private String TAG = SliderAdapter.class.getSimpleName();
private ArrayList<PromotionalBanner> promotionalBannerArrayList;


public SliderAdapter(@NonNull FragmentManager fm,ArrayList<PromotionalBanner> promotionalBannerArrayList) {
    super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
    this.promotionalBannerArrayList = promotionalBannerArrayList;
}



@NonNull
@Override
public Fragment getItem(int position) {
    PromotionalBanner promotionalBanner = DispolyActivity.promotionalBannerArrayList.get(position);
    Log.e("positiondata", "dataPost: "+position );
    return BannerFragment.getInstantFragment(promotionalBanner,
            position,DispolyActivity.promotionalBannerArrayList);
}

@Override
public int getCount() {

    return DispolyActivity.promotionalBannerArrayList.size();
}

@Override
public int getItemPosition(@NonNull Object object) {
    return POSITION_UNCHANGED;
}

@Override
public void destroyItem(@NonNull ViewGroup container,
                        int position, @NonNull Object object) {
    super.destroyItem(container, position, object);
    Log.e("itemDestroy", "destroyItem: "+object );
}

/*TODO update Adapter Data*/
public void updateAdapter_Data(ArrayList<PromotionalBanner> promotionalBannersList){
    this.promotionalBannerArrayList  = promotionalBannersList;

// notifyDataSetChanged(); }

}

1 Answers1

0

When working with the player, you need to carefully monitor the life cycle.

simpleExoPlayer.release();
simpleExoPlayer = null;

Try to use this not only in onPause(), try it also in onDestroy and onDestroyView.
If the problem goes away, then go through which life cycle methods are called and leave the release call in the right places

You have an issue not with memory, most likely you have an issue related to the codec.

Each device has its own limited number of codecs. Some devices have more, some have less.

Therefore, on some devices, you can run the video more times, especially on emulators.

kirkadev
  • 355
  • 4
  • 10