I am creating movie streaming app in android studio i have used recyclerview and exoplayer . everything is perfect there is one final touch which is episodes creation. i would like to add episode to the videos and auto play them after completion of current video exactly like youtube player does. i am adding my json file , main activity video player activity for reference .
what i know is i can create another recycler inside movie activity (where i would display all my episodes list in recyclerview)
i need to create a model and new adapter file for this episodes list also i think i have to create seperate JSon data for this since its different and specific from rest
Main Activity . java program
package com.threeminutesfix.gospelvideos;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.widget.NestedScrollView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager.widget.ViewPager;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import com.threeminutesfix.gospelvideos.Utility.NetworkChangeListerner;
import com.threeminutesfix.gospelvideos.adapter.BannerMoviesPagerAdapter;
import com.threeminutesfix.gospelvideos.adapter.ItemRecyclerAdapter;
import com.threeminutesfix.gospelvideos.adapter.MainRecyclerAdapter;
import com.threeminutesfix.gospelvideos.model.AllCategory;
import com.threeminutesfix.gospelvideos.model.BannerMovies;
import com.threeminutesfix.gospelvideos.retrofit.RetrofitClient;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.tabs.TabLayout;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.observers.DisposableObserver;
import io.reactivex.schedulers.Schedulers;
public class MainActivity extends AppCompatActivity {
BannerMoviesPagerAdapter bannerMoviesPagerAdapter;
NetworkChangeListerner networkChangeListerner = new NetworkChangeListerner();
TabLayout IndicatorTab, categoryTab;
ViewPager bannerMoviesViewpager;
List<BannerMovies> homeBannerList;
List<BannerMovies> tvBannerList;
List<BannerMovies> songBannerList;
List<BannerMovies> audioBannerList;
NestedScrollView nestedScrollView;
AppBarLayout appBarLayout;
MainRecyclerAdapter mainRecyclerAdapter;
RecyclerView mainRecycler;
List<AllCategory> allCategoryList;
ItemRecyclerAdapter itemRecyclerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Objects.requireNonNull(getSupportActionBar()).setLogo(R.drawable.main_logo);
getSupportActionBar().setDisplayUseLogoEnabled(true);
IndicatorTab = findViewById(R.id.tab_indicator);
categoryTab = findViewById(R.id.tabLayout);
nestedScrollView = findViewById(R.id.nested_scroll);
appBarLayout = findViewById(R.id.appbar);
homeBannerList = new ArrayList<>();
tvBannerList = new ArrayList<>();
songBannerList = new ArrayList<>();
audioBannerList = new ArrayList<>();
getBannerData();
getAllMoviesData(1);
categoryTab.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
switch (tab.getPosition()) {
case 1:
setBannerMoviesPagerAdapter(tvBannerList);
getAllMoviesData(2);
return;
case 2:
setBannerMoviesPagerAdapter(songBannerList);
getAllMoviesData(3);
return;
case 3:
setBannerMoviesPagerAdapter(audioBannerList);
getAllMoviesData(4);
return;
default:
setBannerMoviesPagerAdapter(homeBannerList);
getAllMoviesData(1);
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
//titles
allCategoryList = new ArrayList<>();
}
private void setBannerMoviesPagerAdapter(List<BannerMovies> bannerMoviesList) {
bannerMoviesViewpager = findViewById(R.id.banner_viewPager);
bannerMoviesPagerAdapter = new BannerMoviesPagerAdapter(this, bannerMoviesList);
bannerMoviesViewpager.setAdapter(bannerMoviesPagerAdapter);
IndicatorTab.setupWithViewPager(bannerMoviesViewpager);
}
public void setMainRecycler(List<AllCategory> allCategoryList) {
mainRecycler = findViewById(R.id.main_recycler);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this, RecyclerView.VERTICAL, false);
mainRecycler.setLayoutManager(layoutManager);
mainRecyclerAdapter = new MainRecyclerAdapter(this, allCategoryList);
mainRecycler.setAdapter(mainRecyclerAdapter);
mainRecyclerAdapter.notifyDataSetChanged();
}
private void getBannerData() {
CompositeDisposable compositeDisposable = new CompositeDisposable();
compositeDisposable.add(RetrofitClient.getRetroFitClient().getAllBanners()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableObserver<List<BannerMovies>>() {
@Override
public void onNext(List<BannerMovies> bannerMovies) {
for (int i = 0; i < bannerMovies.size(); i++) {
if (bannerMovies.get(i).getBannerCategoryId().toString().equals("1")) {
homeBannerList.add(bannerMovies.get(i));
} else if (bannerMovies.get(i).getBannerCategoryId().toString().equals("2")) {
tvBannerList.add(bannerMovies.get(i));
} else if (bannerMovies.get(i).getBannerCategoryId().toString().equals("3")) {
songBannerList.add(bannerMovies.get(i));
} else if (bannerMovies.get(i).getBannerCategoryId().toString().equals("4")) {
audioBannerList.add(bannerMovies.get(i));
} else {
homeBannerList.add(bannerMovies.get(i));
}
}
}
@Override
public void onError(Throwable e) {
Log.d("bannerData", "" + e);
}
@Override
public void onComplete() {
setBannerMoviesPagerAdapter(homeBannerList);
}
})
);
}
private void getAllMoviesData(Integer categoryId) {
CompositeDisposable compositeDisposable = new CompositeDisposable();
compositeDisposable.add(RetrofitClient.getRetroFitClient().getAllCategoryMovies(categoryId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableObserver<List<AllCategory>>() {
@Override
public void onNext(List<AllCategory> allCategoryList) {
for (int i = 0; i < allCategoryList.size(); i++) {
setMainRecycler(allCategoryList);
}
}
@Override
public void onError(Throwable e) {
Log.d("bannerData", "" + e);
}
@Override
public void onComplete() {
}
})
);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu,menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();
switch (id){
case R.id.refresh_folders:
finish();
startActivity(getIntent());
break;
case R.id.share_app:
Intent share_intent= new Intent();
share_intent.setAction(Intent.ACTION_SEND);
share_intent.putExtra(Intent.EXTRA_TEXT,"check this app via \n"+"https://play.google.com/store/apps/details?id="+getApplicationContext().getPackageName());
share_intent.setType("text/plain");
startActivity(Intent.createChooser(share_intent,"Share App via"));
break;
}
return true;
}
private boolean doubleBackToExitPressedOnce = false;
@Override
protected void onResume() {
super.onResume();
// .... other stuff in my onResume ....
this.doubleBackToExitPressedOnce = false;
}
@Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, R.string.exit_press_back_twice_message, Toast.LENGTH_SHORT).show();
}
@Override
protected void onStart() {
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(networkChangeListerner,filter);
super.onStart();
}
@Override
protected void onStop() {
unregisterReceiver(networkChangeListerner);
super.onStop();
}
}
Movie Details.java
package com.threeminutesfix.gospelvideos;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.widget.NestedScrollView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.threeminutesfix.gospelvideos.Utility.NetworkChangeListerner;
import com.threeminutesfix.gospelvideos.adapter.SimilarRecyclerAdapter;
import com.threeminutesfix.gospelvideos.model.AllCategory;
import com.threeminutesfix.gospelvideos.retrofit.RetrofitClient;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.observers.DisposableObserver;
import io.reactivex.schedulers.Schedulers;
public class MovieDetails extends AppCompatActivity
{
RecyclerView mainRecycler;
TextView video_timer;
ImageView movieImage;
ImageView MovieThumb;
TextView movieName;
TextView movieDesc;
TextView Language;
TextView Singers;
Button playButton;
List<AllCategory> allCategoryList;
NestedScrollView nestedScrollView;
ImageView Trailer;
String mName;
String mImage;
String mId;
String mFileUrl;
String subFileUrl;
String Msmall;
String Mdesc;
String Mlang;
String Msinger;
String Vtimer;
String Turl;
int CatId;
NetworkChangeListerner networkChangeListerner = new NetworkChangeListerner();
SimilarRecyclerAdapter similarRecyclerAdapter;
@SuppressLint("CutPasteId")
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_movie_details);
movieImage = findViewById(R.id.movie_image);
movieName = findViewById(R.id.movie_name);
movieDesc=findViewById(R.id.desc);
playButton = findViewById(R.id.play_button);
Trailer=findViewById(R.id.Trailer);
video_timer= findViewById(R.id.video_timer);
MovieThumb=findViewById(R.id.smallThumb);
Language=findViewById(R.id.Language);
Singers=findViewById(R.id.Singer);
nestedScrollView= findViewById(R.id.scroll_movie);
mName = getIntent().getStringExtra("movieName");
mImage = getIntent().getStringExtra("movieImageUrl");
mFileUrl = getIntent().getStringExtra("movieFile");
Msmall=getIntent().getStringExtra("smallThumb");
Mdesc=getIntent().getStringExtra("MovieDesc");
Mlang=getIntent().getStringExtra("Language");
Msinger=getIntent().getStringExtra("Singers");
Turl=getIntent().getStringExtra("TrailerUrl");
subFileUrl=getIntent().getStringExtra("SrtUrl");
Vtimer= getIntent().getStringExtra("VideoTiming");
setTitle(mName);
Glide.with(this).load(mImage).placeholder(R.drawable.film).into(movieImage);
Glide.with(this).load(Msmall).placeholder(R.drawable.thumb).into(MovieThumb);
Glide.with(this).load(mImage).placeholder(R.drawable.thumb).into(Trailer);
movieName.setText(mName);
movieDesc.setText(Mdesc);
Language.setText(Mlang);
Singers.setText(Msinger);
video_timer.setText(Vtimer);
CatId = getIntent().getIntExtra("categoryId", 0);
getMovies(CatId);
allCategoryList = new ArrayList<>();
playButton.setOnClickListener(v -> {
if(mFileUrl==null) {
Toast.makeText(this, "Error Occurred while fetching this video. try again later or restart this app", Toast.LENGTH_LONG).show();
}
else{
Intent i = new Intent(MovieDetails.this, VideoPlayerActivity
.class);
i.putExtra("movieId", mId);
i.putExtra("url", mFileUrl);
i.putExtra("movieName", mName);
i.putExtra("MovieThumb", Msmall);
i.putExtra("SrtUrl",subFileUrl);
startActivity(i);
}
});
Trailer.setOnClickListener(v -> {
if (Turl == null)
{
Toast.makeText(this, "Trailer not available or not added by original owners", Toast.LENGTH_LONG).show();
}
else{
Intent i = new Intent(MovieDetails.this, TrailerActivity.class);
i.putExtra("url", Turl);
i.putExtra("movieName",mName);
startActivity(i);
}
});
}
@Override
protected void onStart() {
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(networkChangeListerner,filter);
super.onStart();
}
@Override
protected void onStop() {
unregisterReceiver(networkChangeListerner);
super.onStop();
}
public void setMainRecycler(List<AllCategory> allCategoryList) {
mainRecycler = findViewById(R.id.Similar_rv);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this, RecyclerView.VERTICAL, false);
mainRecycler.setLayoutManager(layoutManager);
similarRecyclerAdapter = new SimilarRecyclerAdapter(this, allCategoryList);
mainRecycler.setAdapter(similarRecyclerAdapter);
similarRecyclerAdapter.notifyDataSetChanged();
}
private void getMovies(Integer categoryId) {
CompositeDisposable compositeDisposable = new CompositeDisposable();
compositeDisposable.add(RetrofitClient.getRetroFitClient2().getMovies(categoryId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableObserver<List<AllCategory>>() {
@Override
public void onNext(List<AllCategory> allCategoryList) {
for (int i = 0; i < allCategoryList.size(); i++) {
setMainRecycler(allCategoryList);
}
}
@Override
public void onError(Throwable e) {
Log.d("bannerData", "" + e);
}
@Override
public void onComplete() {
}
})
);
}
}
categoryItemlist.java (model file)
package com.threeminutesfix.gospelvideos.model;
import java.io.Serializable;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class AllCategory implements Serializable {
@SerializedName("categoryId")
@Expose
private Integer categoryId;
@SerializedName("categoryTitle")
@Expose
private String categoryTitle;
@SerializedName("categoryImage")
@Expose
private String categoryImage;
@SerializedName("categoryItemList")
@Expose
private List<CategoryItemList> categoryItemList = null;
public Integer getCategoryId() {
return categoryId;
}
public void setCategoryId(Integer categoryId) {
this.categoryId = categoryId;
}
public String getCategoryTitle() {
return categoryTitle;
}
public void setCategoryTitle(String categoryTitle) {
this.categoryTitle = categoryTitle;
}
public String getCategoryImage() {
return categoryImage;
}
public void setCategoryImage(String categoryImage) {
this.categoryImage = categoryImage;
}
public List<CategoryItemList> getCategoryItemList() {
return categoryItemList;
}
public void setCategoryItemList(List<CategoryItemList> categoryItemList) {
this.categoryItemList = categoryItemList;
}
}
package com.threeminutesfix.gospelvideos.model;
import java.io.Serializable;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class AllCategory implements Serializable {
@SerializedName("categoryId")
@Expose
private Integer categoryId;
@SerializedName("categoryTitle")
@Expose
private String categoryTitle;
@SerializedName("categoryImage")
@Expose
private String categoryImage;
@SerializedName("categoryItemList")
@Expose
private List<CategoryItemList> categoryItemList = null;
public Integer getCategoryId() {
return categoryId;
}
public void setCategoryId(Integer categoryId) {
this.categoryId = categoryId;
}
public String getCategoryTitle() {
return categoryTitle;
}
public void setCategoryTitle(String categoryTitle) {
this.categoryTitle = categoryTitle;
}
public String getCategoryImage() {
return categoryImage;
}
public void setCategoryImage(String categoryImage) {
this.categoryImage = categoryImage;
}
public List<CategoryItemList> getCategoryItemList() {
return categoryItemList;
}
public void setCategoryItemList(List<CategoryItemList> categoryItemList) {
this.categoryItemList = categoryItemList;
}
}
ready to add further files if needed
It is very easy just follow below steps:-
1]Add your all video to the list and set that list to your exo player object as below
for (i in videoList.indices){ var songPath:String = videoList.get(i) val item: MediaItem = MediaItem.fromUri(songPath) exoPlayerManager.addMediaItem(item) } exoPlayerManager.prepare() exoPlayerManager.play()
2]Add/enable next, previous switch in xml layout
<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/playerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/playerViewFrameLayout"
app:repeat_toggle_modes="all"
app:controller_layout_id="@layout/exo_playback_control_view"
app:resize_mode="fit"
app:show_buffering="always"
app:show_shuffle_button="true"
/>
3] Just check by clicking next button from the media controller if that works then you are done, now the videos will be played automatically once finished the current one.