Official Website for YouTube API V3 https://developers.google.com/youtube/v3/getting-started
In YouTube API we can load videos with authentication or credential.
Google Sample for getting credential in android https://github.com/googlesamples/android-credentials , but we will modify it for our sample application step by step.
Create a OAuth 2.0 client IDs in Google API Console with your application package name for API for Android and this API key is not needed to be copied or pasted in your application its just to register your project for OAuth 2.0.
Add these library in your gradle file:
Create a UI activity.xml:
In YouTube API we can load videos with authentication or credential.
Google Sample for getting credential in android https://github.com/googlesamples/android-credentials , but we will modify it for our sample application step by step.
Create a OAuth 2.0 client IDs in Google API Console with your application package name for API for Android and this API key is not needed to be copied or pasted in your application its just to register your project for OAuth 2.0.
Add these library in your gradle file:
compile 'com.google.android.gms:play-services-auth:9.0.2'
compile 'com.google.api-client:google-api-client-android:1.22.0'
compile 'com.google.apis:google-api-services-youtube:v3-rev171-1.22.0'
compile 'com.github.bumptech.glide:glide:3.6.1'
compile 'com.android.support:design:23.4.0'
compile 'com.android.support:cardview-v7:23.4.0'
Create some interface to handle the Youtube Response:
public interface ServerResponseListener { public void prepareRequest(Object... objects); public void goBackground(Object... objects); public void completedRequest(Object... objects); }
public interface ServiceTaskInterface {
NetHttpTransport transport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
}
public interface UserRecoverableAuth {
void handelUserRecoverableAuth(boolean state,
UserRecoverableAuthIOException authException);
}
Create a AsyncTask for network call and to get videos from youtube api.
public class MyUploads extends AsyncTask<Object, Void, Object[]> implements
ServiceTaskInterface {
private static final String TAG = MyUploads.class.getSimpleName();
private ServerResponseListener mServerResponseListener = null;
private int mRequestCode = 0;
GoogleAccountCredential credential;
Context mContext;
public static final int CHANNEL_VIDEO = 1; public static final int PLAYLIST_VIDEO = 2; public static final int CHANNEL_DETAILS = 3;
public void setmServerResponseListener(ServerResponseListener mServerResponseListener) { this.mServerResponseListener = mServerResponseListener; } public MyUploads(Context mContext, int iReqCode, GoogleAccountCredential credential) { mRequestCode = iReqCode; this.credential = credential; this.mContext = mContext; } @Override protected void onPreExecute() { super.onPreExecute(); mServerResponseListener.prepareRequest(mRequestCode); } @Override protected Object[] doInBackground(Object... params) { if (params == null) throw new NullPointerException("Parameters to the async task can never be null"); mServerResponseListener.goBackground(); Object[] resultDetails = new Object[2]; resultDetails[0] = mRequestCode; switch (mRequestCode) { case CHANNEL_DETAILS: resultDetails[1] = getChannel((String) params[0]); break; case CHANNEL_VIDEO: resultDetails[1] = getPlaylistItemListResponse((String) params[0]); break; case PLAYLIST_VIDEO: resultDetails[1] = getVideos((String) params[0], (String) params[1]); break; } return resultDetails; } @Override protected void onPostExecute(Object[] result) { super.onPostExecute(result); mServerResponseListener.completedRequest(result); } private ChannelListResponse getChannel(String forUserName) { try { YouTube youtube = new YouTube.Builder(transport, jsonFactory, credential) .setApplicationName(AppConstants.APP_NAME).build(); ChannelListResponse channelRequest = youtube.channels() .list("snippet,contentDetails").setForUsername(forUserName).execute(); List<Channel> channelsList = channelRequest.getItems(); if (channelsList != null) { return channelRequest; } } catch (GoogleJsonResponseException e) { e.printStackTrace(); System.err.println("There was a service error: " + e.getDetails() .getCode() + " : " + e.getDetails().getMessage()); } catch (UserRecoverableAuthIOException ue) { handleException(ue); } catch (Throwable t) { t.printStackTrace(); } return null; } private PlaylistItemListResponse getPlaylistItemListResponse(String forUserName) { try { YouTube youtube = new YouTube.Builder(transport, jsonFactory, credential) .setApplicationName(mContext.getString(R.string.app_name)).build(); ChannelListResponse channelRequest = youtube.channels().list("contentDetails") .setForUsername(forUserName).execute(); List<Channel> channelsList = channelRequest.getItems(); if (channelsList != null) { String uploadPlaylistId = channelsList.get(0).getContentDetails() .getRelatedPlaylists().getUploads(); YouTube.PlaylistItems.List playlistItemRequest = youtube.playlistItems() .list("id,snippet,contentDetails"); playlistItemRequest.setPlaylistId(uploadPlaylistId); playlistItemRequest.setMaxResults((long) 50); playlistItemRequest.setPart("snippet"); String nextToken = ""; playlistItemRequest.setPageToken(nextToken); PlaylistItemListResponse playlistItemResult = playlistItemRequest.execute(); return playlistItemResult; } } catch (GoogleJsonResponseException e) { e.printStackTrace(); } catch (UserRecoverableAuthIOException ue) { handleException(ue); } catch (Throwable t) { t.printStackTrace(); } return null; } private PlaylistItemListResponse getVideos(String nextToken, String uploadPlaylistId) { try { YouTube youtube = new YouTube.Builder(transport, jsonFactory, credential) .setApplicationName(mContext.getString(R.string.app_name)).build(); YouTube.PlaylistItems.List playlistItemRequest = youtube.playlistItems() .list("id,snippet,contentDetails"); playlistItemRequest.setPlaylistId(uploadPlaylistId); playlistItemRequest.setMaxResults((long) 50); playlistItemRequest.setPart("snippet"); playlistItemRequest.setPageToken(nextToken); PlaylistItemListResponse playlistItemResult = playlistItemRequest.execute(); return playlistItemResult; } catch (GoogleJsonResponseException e) { e.printStackTrace(); } catch (UserRecoverableAuthIOException ue) { handleException(ue); } catch (Throwable t) { t.printStackTrace(); } return null; }
private void handleException(Exception e) {
if (e.getClass().equals(UserRecoverableAuthIOException.class)) {
UserRecoverableAuthIOException r = (UserRecoverableAuthIOException) e;
Intent intent = null;
try {
intent = r.getIntent();
} catch (Exception ee) {
// ignore, this happens if we kill the activity quickly before
//our async task finishes
}
if (intent != null)
doHandleAuthIntent(r);
} else if (e.getClass().equals(GoogleAuthIOException.class)) {
// could be a bad user name, let's pass it to the listener to check
doHandleAuthIntent(null);
} else if (e.getClass().equals(GoogleJsonResponseException.class)) {
GoogleJsonResponseException r = (GoogleJsonResponseException) e;
e.printStackTrace();
doHandleExceptionMessage("JSON Error: " + r.getDetails().getCode() +
" : " + r.getDetails().getMessage());
} else {
doHandleExceptionMessage("Exception Occurred: " + e.toString());
e.printStackTrace();
}
}
private void doHandleAuthIntent(UserRecoverableAuthIOException authIntent) {
UserRecoverableAuth userRecoverableAuth = (UserRecoverableAuth) mContext;
userRecoverableAuth.handelUserRecoverableAuth(true, authIntent);
//toast(mContext, "Need Authorization");
}
private void doHandleExceptionMessage(String message) {
toast(mContext, message);
}
public static void toast(Context context, final String message) { // Toasts only work on the main thread if (context != null && message != null) { final Context appContext = context.getApplicationContext(); Handler handler = new Handler(Looper.getMainLooper()); handler.post(new Runnable() { @Override public void run() { Toast.makeText(appContext, message, Toast.LENGTH_SHORT).show(); } }); } }
}
Create a UI activity.xml:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:gravity="center"
android:orientation="vertical"
android:weightSum="3">
<android.support.v7.widget.RecyclerView
android:id="@+id/listRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:scrollbars="vertical"></android.support.v7.widget.RecyclerView>
<LinearLayout
android:id="@+id/google_signIn"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
android:gravity="center"
android:orientation="vertical">
<com.google.android.gms.common.SignInButton
android:id="@+id/sign_in_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</com.google.android.gms.common.SignInButton>
</LinearLayout>
</LinearLayout>
Create a YoutubeActivity.class:
It has a limit of 50 videos at a time can be feteched from api.
public class YoutubeActivity extends ActivityBase implements View.OnClickListener,
ServerResponseListener,
GoogleApiClient.OnConnectionFailedListener, UserRecoverableAuth{
private static final String TAG = "YoutubeActivity";
private static final int RC_SIGN_IN = 9001;
private static final int REQUEST_ACCOUNT_PICKER = 2;
private static final int REQUEST_AUTHORIZATION = 3;
public static final String ACCOUNT_KEY = "accountName";
private String mChosenAccountName;
GoogleAccountCredential credential;
private GoogleApiClient mGoogleApiClient;
Context mContext;
String userNameYoutube = "";
LinearLayout googleSignInLinearLayout;
RecyclerView listRecyclerView;
YoutubeAdapter youtubeAdapter;
LinearLayoutManager mLayoutManager;
List<PlaylistItem> videoList = new ArrayList<PlaylistItem>();
List<YoutubeVideos> youtubeVideosList = new ArrayList<YoutubeVideos>();
String nextToken = "-1";
String playlistId = "";
public int totalLength = 0;
private int previousTotal = 0;
private boolean loading = true;
private int visibleThreshold = 5;
int firstVisibleItem, visibleItemCount, totalItemCount;
final String[] SCOPES = {Scopes.PROFILE, YouTubeScopes.YOUTUBE};
public static final int CHANNEL_VIDEO = 1; public static final int PLAYLIST_VIDEO = 2; public static final int CHANNEL_DETAILS = 3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity); mContext = this; initializeViews();
//we need read contacts permission for more on Marshmallow 6.0 permission
//check this link
//http://yuvarockers.blogspot.in/2016/04/android-marshmallow-60-permissions.html
if (Build.VERSION.SDK_INT >= 23) {
if (!Constant_Methods.hasPermissions(this, Constant_Methods.PERMISSIONS)) {
ActivityCompat.requestPermissions(this, Constant_Methods.PERMISSIONS, 1);
}
}
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(
GoogleSignInOptions.DEFAULT_SIGN_IN) .requestEmail() .build(); mGoogleApiClient = new GoogleApiClient.Builder(this) .enableAutoManage(this, this) .addApi(Auth.GOOGLE_SIGN_IN_API, gso) .build(); SignInButton signInButton = (SignInButton) findViewById(R.id.sign_in_button); signInButton.setSize(SignInButton.SIZE_WIDE); signInButton.setScopes(gso.getScopeArray()); credential = GoogleAccountCredential.usingOAuth2(getApplicationContext(), Arrays.asList(SCOPES)); // set exponential backoff policy credential.setBackOff(new ExponentialBackOff()); if (savedInstanceState != null) { mChosenAccountName = savedInstanceState.getString(ACCOUNT_KEY); } else { loadAccount(); } credential.setSelectedAccountName(mChosenAccountName); } public void initializeViews() { googleSignInLinearLayout = (LinearLayout) findViewById(R.id.google_signIn); listRecyclerView = (RecyclerView) findViewById(R.id.listRecyclerView); findViewById(R.id.sign_in_button).setOnClickListener(this); setRecyclerViewAdapter(); } public void setRecyclerViewAdapter() { youtubeAdapter = new YoutubeAdapter(mContext, videoList, youtubeVideosList); listRecyclerView.setHasFixedSize(true); mLayoutManager = new LinearLayoutManager(getApplicationContext()); listRecyclerView.setLayoutManager(mLayoutManager); youtubeAdapter.setData(videoList); listRecyclerView.setItemAnimator(new DefaultItemAnimator()); listRecyclerView.addItemDecoration(new DividerItemDecoration(this,
LinearLayoutManager.VERTICAL));
listRecyclerView.setAdapter(youtubeAdapter);
youtubeAdapter.notifyDataSetChanged();
listRecyclerView.addOnItemTouchListener(new RecyclerItemClickListener(mContext,
new RecyclerItemClickListener.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
TextView yearTag = (TextView) view.findViewById(R.id.item_date);
String videoId = yearTag.getTag().toString();
try {
Intent intent = new Intent(Intent.ACTION_VIEW,
Uri.parse("vnd.youtube:" + videoId));
startActivity(intent);
} catch (ActivityNotFoundException ex) {
}
}
}));
listRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = listRecyclerView.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
}
}
if (!loading && (totalItemCount - visibleItemCount) <=
(firstVisibleItem + visibleThreshold)) {
if (!nextToken.equals("-1")) {
MyUploads myUploads = new MyUploads(mContext, PLAYLIST_VIDEO,
credential);
myUploads.setmServerResponseListener(YoutubeActivity.this);
myUploads.execute(new String[]{nextToken, playlistId});
loading = true;
}
}
}
});
}
@Override
public void onStart() {
super.onStart();
OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(
mGoogleApiClient);
if (opr.isDone()) {
// If the user's cached credentials are valid, the OptionalPendingResult
// will be "done"
// and the GoogleSignInResult will be available instantly.
Log.d(TAG, "Got cached sign-in");
GoogleSignInResult result = opr.get();
handleSignInResult(result);
} else {
// If the user has not previously signed in on this device or the sign-in
// has expired,
// this asynchronous branch will attempt to sign in the user silently.
// Cross-device
// single sign-on will occur in this branch.
//showProgressDialog();
opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
@Override
public void onResult(GoogleSignInResult googleSignInResult) {
//hideProgressDialog();
handleSignInResult(googleSignInResult);
}
});
}
}
private void handleSignInResult(GoogleSignInResult result) {
Log.d(TAG, "handleSignInResult:" + result.isSuccess());
if (result.isSuccess()) {
// Signed in successfully, show authenticated UI.
GoogleSignInAccount acct = result.getSignInAccount();
String accountName = acct.getEmail();
if (accountName != null) {
mChosenAccountName = accountName;
credential.setSelectedAccountName(accountName);
saveAccount();
}
updateUI(true);
} else {
// Signed out, show unauthenticated UI.
updateUI(false);
}
}
private void signIn() {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
private void updateUI(boolean signedIn) {
if (signedIn) {
findViewById(R.id.google_signIn).setVisibility(View.GONE);
listRecyclerView.setVisibility(View.VISIBLE);
if (totalLength == 0) {
MyUploads myUploads = new MyUploads(mContext, CHANNEL_DETAILS, credential);
myUploads.setmServerResponseListener(this);
myUploads.execute(new String[]{userNameYoutube});
}
} else {
findViewById(R.id.google_signIn).setVisibility(View.VISIBLE);
listRecyclerView.setVisibility(View.GONE);
}
}
public void loadAccount() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(
getApplicationContext());
mChosenAccountName = sp.getString(ACCOUNT_KEY, null);
invalidateOptionsMenu();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case RC_SIGN_IN:
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(
data);
handleSignInResult(result);
break;
case REQUEST_AUTHORIZATION:
if (resultCode != Activity.RESULT_OK) {
chooseAccount();
}
break;
case REQUEST_ACCOUNT_PICKER:
if (resultCode == Activity.RESULT_OK && data != null && data.getExtras()
!= null) {
String accountName = data.getExtras().getString(
AccountManager.KEY_ACCOUNT_NAME);
if (accountName != null) {
mChosenAccountName = accountName;
credential.setSelectedAccountName(accountName);
saveAccount();
}
}
break;
}
}
private void chooseAccount() {
startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
}
public void saveAccount() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(
SampleApplication.getAppContext());
sp.edit().putString(ACCOUNT_KEY, mChosenAccountName).commit();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(ACCOUNT_KEY, mChosenAccountName);
Log.e("mChosenAccountName", "" + mChosenAccountName);
}
@Override
public void onClick(View v) {
int id = v.getId();
switch (id) {
case R.id.sign_in_button:
signIn();
break;
}
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
if (connectionResult.hasResolution()) {
Toast.makeText(getApplicationContext(),
R.string.connection_to_google_play_failed, Toast.LENGTH_SHORT)
.show();
Log.e("TAG", String.format(
"Connection to Play Services Failed, error: %d, reason: %s",
connectionResult.getErrorCode(),
connectionResult.toString()));
try {
connectionResult.startResolutionForResult(YoutubeActivity.this, 0);
} catch (IntentSender.SendIntentException e) {
Log.e("TAG", e.toString(), e);
}
}
}
@Override
public void prepareRequest(Object... objects) {
// Parse the response based upon type of request
Integer reqCode = (Integer) objects[0];
if (reqCode == null || reqCode == 0)
throw new NullPointerException("Request Code's value is Invalid.");
switch (reqCode) {
case CHANNEL_DETAILS:
break;
case CHANNEL_VIDEO:
break;
case PLAYLIST_VIDEO:
break;
}
}
@Override
public void goBackground(Object... objects) {
}
@Override
public void completedRequest(Object... objects) {
// Parse the response based upon type of request
Integer reqCode = (Integer) objects[0];
if (reqCode == null || reqCode == 0)
throw new NullPointerException("Request Code's value is Invalid.");
switch (reqCode) {
case CHANNEL_DETAILS: //To get the channel details
ChannelListResponse channelsResponse = (ChannelListResponse) objects[1];
if (channelsResponse != null) {
if (channelsResponse.getItems().size() > 0) {
channelsResponse.getItems().get(0).getSnippet().getDescription());
}
}
if (NetworkUtils.isConnectingToInternet(mContext)) {
MyUploads myUploads1 = new MyUploads(mContext, CHANNEL_VIDEO, credential);
myUploads1.setmServerResponseListener(this);
myUploads1.execute(new String[]{userNameYoutube});
} else {
Toast.makeText(getApplicationContext(), "No Internet Connection",
Toast.LENGTH_LONG).show();
}
break;
case CHANNEL_VIDEO://To get the channel's first 50 videos
PlaylistItemListResponse playlistItemListResponse = (PlaylistItemListResponse)
objects[1];
if (playlistItemListResponse != null) {
totalLength = playlistItemListResponse.getPageInfo().getTotalResults();
videoList.addAll(playlistItemListResponse.getItems());
nextToken = (playlistItemListResponse.containsKey("nextPageToken"))
? playlistItemListResponse.getNextPageToken() : "-1";
playlistId = (playlistItemListResponse.getItems().size() > 0) ?
playlistItemListResponse.getItems().get(0).getSnippet()
.getPlaylistId() : "";
if (playlistItemListResponse.getItems().size() > 0) {
for (int i = 0; i < playlistItemListResponse.getItems().size(); i++) {
YoutubeVideos youtubeVideos = new YoutubeVideos();
youtubeVideos.setId(playlistItemListResponse.getItems()
.get(i).getId());
youtubeVideos.setSeen(false);
youtubeVideosList.add(youtubeVideos);
}
youtubeVideos = null;
}
setRecyclerViewAdapter();
}
}
break;
case PLAYLIST_VIDEO: //Get videos using next token to get another list of videos
PlaylistItemListResponse playlistItemListResponse1 = (PlaylistItemListResponse)
objects[1];
if (playlistItemListResponse1 != null) {
videoList.addAll(playlistItemListResponse1.getItems());
nextToken = (playlistItemListResponse1.containsKey("nextPageToken"))
? playlistItemListResponse1.getNextPageToken() : "-1";
playlistId = (playlistItemListResponse1.getItems().size() > 0)
? playlistItemListResponse1.getItems().get(0)
.getSnippet().getPlaylistId() : "";
if (playlistItemListResponse1.getItems().size() > 0) {
for (int i = 0; i < playlistItemListResponse1.getItems().size(); i++) {
YoutubeVideos youtubeVideos = new YoutubeVideos();
youtubeVideos.setId(playlistItemListResponse1.getItems()
.get(i).getId());
youtubeVideos.setSeen(false);
youtubeVideosList.add(youtubeVideos);
}
youtubeVideos = null;
}
youtubeAdapter.notifyDataSetChanged();
}
}
break;
}
}
@Override
public void handelUserRecoverableAuth(boolean state,
UserRecoverableAuthIOException authException) {
startActivityForResult(authException.getIntent(), REQUEST_AUTHORIZATION);
}
}
Create a YoutubeAdapter for loading the videos thumbnail and show description:
I have used this library https://github.com/yuvaraj119/android-parallax-recyclerview for YoutubeAdapter.
public class YoutubeAdapter extends ParallaxRecyclerAdapter<PlaylistItem> {
private List<PlaylistItem> videoList;
Context mContext;
List<YoutubeVideos> youtubeVideosList = new ArrayList<YoutubeVideos>();
public YoutubeAdapter(Context mContext, List<PlaylistItem> moviesList,
List<YoutubeVideos> youtubeVideosList) {
super(moviesList);
this.mContext = mContext;
this.videoList = moviesList;
this.youtubeVideosList = youtubeVideosList;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView title, year, genre;
public ImageView imageViewVideoThumb;
public MyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.item_heading);
genre = (TextView) view.findViewById(R.id.item_content);
year = (TextView) view.findViewById(R.id.item_date);
imageViewVideoThumb = (ImageView) view.findViewById(R.id.imageViewVideoThumb);
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolderImpl(ViewGroup parent,
ParallaxRecyclerAdapter<PlaylistItem> adapter, int i) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(
R.layout.youtube_item_view, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolderImpl(RecyclerView.ViewHolder viewHolder,
ParallaxRecyclerAdapter<PlaylistItem> adapter, int position) {
MyViewHolder holder = (MyViewHolder) viewHolder;
PlaylistItem playlistItem = videoList.get(position);
YoutubeVideos youtubeVideos = youtubeVideosList.get(position);
holder.title.setText(playlistItem.getSnippet().getTitle());
holder.genre.setText(playlistItem.getSnippet().getDescription());
holder.year.setText(playlistItem.getSnippet().getPublishedAt().toString());
holder.year.setTag("" + playlistItem.getSnippet().getResourceId().getVideoId());
try {
String imageUrl = (playlistItem.getSnippet().getThumbnails()
.containsKey("standard")) ? playlistItem.getSnippet()
.getThumbnails().getStandard().getUrl()
: playlistItem.getSnippet().getThumbnails().getDefault().getUrl();
Glide.with(mContext)
.load(imageUrl)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.crossFade()
.into(holder.imageViewVideoThumb);
} catch (NullPointerException ne) {
ne.printStackTrace();
} catch (IllegalArgumentException ia) {
ia.printStackTrace();
}
}
@Override
public int getItemCountImpl(ParallaxRecyclerAdapter<PlaylistItem> adapter) {
return videoList.size();
}
}
Create a youtube_item_view layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="180dp"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:elevation="5dp">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/imageViewVideoThumb"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="centerCrop" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:background="@color/very_dark_grayish_cyan"
android:orientation="vertical">
<TextView
android:id="@+id/item_heading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:textAppearance="@android:style/TextAppearance.Small"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="3">
<TextView
android:id="@+id/item_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".8"
android:layout_marginLeft="5dp"
android:textAppearance="@android:style/TextAppearance.Small"
android:gravity="left|bottom"
android:ellipsize="end"
android:maxLines="2" />
<TextView
android:id="@+id/item_invisible"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@android:style/TextAppearance.Small"
android:layout_weight="1.2"
android:visibility="invisible" />
<TextView
android:id="@+id/item_date"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginRight="5dp"
android:textAppearance="@android:style/TextAppearance.Small"
android:layout_weight="1"
android:gravity="right|bottom" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
</android.support.v7.widget.CardView>
Utilizing the YouTube API V3 for Android opens up a world of possibilities for developers looking to integrate rich multimedia functionality into their apps. With seamless access to YouTube's vast library of videos, live streams, and user data, developers can create immersive experiences tailored to their users' preferences. Whether it's building a video-sharing app, implementing advanced search features, or integrating personalized recommendations, the YouTube API V3 empowers developers to craft innovative solutions that engage and delight users on the Android platform.
ReplyDelete