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(); }
}