Formulation of the problem:
Under the link to the video from youtube.com or vimeo.com get a preview of the video and display it in the list on the screen.
Wherein:
- The maximum you can add 10 videos;
- Do not add existing videos.
You can add previews by three types of links:
https://www.youtube.com/watch?v=XXXXXXXXXXXhttps://youtu.be/XXXXXXXXXXXhttps://vimeo.com/XXXXXXXXX
Decision:
Create an activity_video_preview.xml :
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_video_preview" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v7.widget.RecyclerView android:id="@+id/video_preview_recycler_view" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"> </android.support.v7.widget.RecyclerView> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="4dp"> <EditText android:id="@+id/add_edit_text" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"/> <Button android:id="@+id/add_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Add"/> </LinearLayout> </LinearLayout>
Create item_video_preview.xml :
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" card_view:cardCornerRadius="5dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="20dp"> <ImageView android:id="@+id/item_video_preview_image_view" android:layout_width="120dp" android:layout_height="90dp" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginRight="20dp"/> <TextView android:id="@+id/item_video_preview_link_text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/item_video_preview_image_view"/> <TextView android:id="@+id/item_video_preview_link_preview_text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/item_video_preview_image_view" android:layout_below="@id/item_video_preview_link_text_view"/> </RelativeLayout> </android.support.v7.widget.CardView>
Create (for convenience) interface VideoTypes :
public interface VideoTypes { int TYPE_UNKNOWN = 0; int TYPE_YOUTUBE = 1; int TYPE_VIMEO = 2; }
Create a VideoPreview data model class:
public class VideoPreview { private String mVideoLink; private String mPreviewLink; public VideoPreview(String videoLink, String previewLink) { mVideoLink = videoLink; mPreviewLink = previewLink; } public String getVideoLink() { return mVideoLink; } public String getPreviewLink() { return mPreviewLink; } }
Create a VideoMethods class to handle video links:
public class VideoMethods implements VideoTypes { public static int getLinkType(String link) { Pattern pattern = Pattern.compile("^https:\\/\\/www\\.(youtube\\.com)\\/watch\\?v=[\\w-]{11}$|^https:\\/\\/(youtu\\.be)\\/[\\w-]{11}$|^https:\\/\\/(vimeo\\.com)\\/[0-9]*$"); Matcher matcher = pattern.matcher(link); if (!matcher.matches()) return TYPE_UNKNOWN; for (int i=1; i<=matcher.groupCount(); i++) { if (matcher.group(i) != null) { switch (i) { case 1: case 2: return TYPE_YOUTUBE; case 3: return TYPE_VIMEO; default: return TYPE_UNKNOWN; } } } return TYPE_UNKNOWN; } public static String getId(String link) { Pattern pattern = Pattern.compile("^https:\\/\\/www\\.youtube\\.com\\/watch\\?v=([\\w-]{11})$|^https:\\/\\/youtu\\.be\\/([\\w-]{11})$|^https:\\/\\/vimeo\\.com\\/([0-9]*)$"); Matcher matcher = pattern.matcher(link); matcher.matches(); for (int i=1; i<=matcher.groupCount(); i++) { if (matcher.group(i) != null) { return matcher.group(i); } } return null; } }
Adapter for RecyclerView :
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> { private ArrayList<VideoPreview> mItems; private Context mContext; public DataAdapter(Context context) { mContext = context; mItems = new ArrayList<>(); } @Override public DataAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_video_preview, viewGroup, false); return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder viewHolder, int i) { viewHolder.mPreviewLinkTextView.setText(mItems.get(i).getVideoLink()); viewHolder.mPreviewLinkPreviewTextView.setText(mItems.get(i).getPreviewLink()); Picasso.with(mContext).load(mItems.get(i).getPreviewLink()).resize(120, 90).into(viewHolder.mPreviewImageView); } @Override public int getItemCount() { return mItems.size(); } public void addItem(VideoPreview videoPreview) { mItems.add(videoPreview); notifyDataSetChanged(); } public boolean contains(VideoPreview newVideoPreview) { for (VideoPreview videoPreview : mItems) { if (videoPreview.getVideoLink().equals(newVideoPreview.getVideoLink())) return true; } return false; } public class ViewHolder extends RecyclerView.ViewHolder{ ImageView mPreviewImageView; TextView mPreviewLinkTextView; TextView mPreviewLinkPreviewTextView; public ViewHolder(View view) { super(view); mPreviewImageView = (ImageView) view.findViewById(R.id.item_video_preview_image_view); mPreviewLinkTextView = (TextView) view.findViewById(R.id.item_video_preview_link_text_view); mPreviewLinkPreviewTextView = (TextView) view.findViewById(R.id.item_video_preview_link_preview_text_view); } } }
And finally, VideoPreviewActivity :
public class VideoPreviewActivity extends AppCompatActivity implements VideoTypes { private RecyclerView mVideoPreviewRecyclerView; private EditText mAddEditText; private Button mAddButton; private OkHttpClient httpClient; private DataAdapter mDataAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_video_preview); mVideoPreviewRecyclerView = (RecyclerView) findViewById(R.id.video_preview_recycler_view); mAddEditText = (EditText) findViewById(R.id.add_edit_text); mAddButton = (Button) findViewById(R.id.add_button); mVideoPreviewRecyclerView = (RecyclerView)findViewById(R.id.video_preview_recycler_view); mVideoPreviewRecyclerView.setHasFixedSize(true); RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext()); mVideoPreviewRecyclerView.setLayoutManager(layoutManager); mDataAdapter = new DataAdapter(getApplicationContext()); mVideoPreviewRecyclerView.setAdapter(mDataAdapter); httpClient = new OkHttpClient(); mAddButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mDataAdapter.getItemCount() == 10) { Toast.makeText(getApplicationContext(), "You can not add more than 10 videos!", Toast.LENGTH_SHORT).show(); return; } String videoLink = mAddEditText.getText().toString(); int videoType = VideoMethods.getLinkType(videoLink); if (videoType == TYPE_UNKNOWN) { Toast.makeText(getApplicationContext(), "Incorrect link!", Toast.LENGTH_SHORT).show(); return; } mAddEditText.getText().clear(); InputMethodManager inputMethodManager = (InputMethodManager) VideoPreviewActivity.this.getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(VideoPreviewActivity.this.getCurrentFocus().getWindowToken(), 0); String videoId = VideoMethods.getId(videoLink); switch (videoType) { case TYPE_YOUTUBE: VideoPreview videoPreview = new VideoPreview(videoLink, "http://img.youtube.com/vi/" + videoId + "/1.jpg"); if (!mDataAdapter.contains(videoPreview)) { mDataAdapter.addItem(videoPreview); mVideoPreviewRecyclerView.scrollToPosition(mDataAdapter.getItemCount()-1); } else { Toast.makeText(getApplicationContext(), "This video already exists!", Toast.LENGTH_SHORT).show(); } break; case TYPE_VIMEO: try { getVimeoPreview(videoLink, videoId); } catch (Exception e) { Toast.makeText(getApplicationContext(), "Something going wrong!", Toast.LENGTH_SHORT).show(); } break; } } }); } public void getVimeoPreview(final String videoLink, final String videoId) throws Exception { Request request = new Request.Builder() .url("http://vimeo.com/api/v2/video/" + videoId + ".xml") .build(); httpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Toast.makeText(getApplicationContext(), "Something going wrong!", Toast.LENGTH_SHORT).show(); } @Override public void onResponse(Call call, Response response) throws IOException { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); String s = response.body().string(); Pattern p = Pattern.compile("<thumbnail_small>(.*)<\\/thumbnail_small>"); final Matcher m = p.matcher(s); m.find(); runOnUiThread(new Runnable() { @Override public void run() { VideoPreview videoPreview = new VideoPreview(videoLink, m.group(1)); if (!mDataAdapter.contains(videoPreview)) { mDataAdapter.addItem(videoPreview); mVideoPreviewRecyclerView.scrollToPosition(mDataAdapter.getItemCount()-1); } else { Toast.makeText(getApplicationContext(), "This video already exists!", Toast.LENGTH_SHORT).show(); } } }); } }); } }
Do not forget to add to build.gradle :
compile 'com.squareup.okhttp3:okhttp:3.4.1' compile 'com.squareup.picasso:picasso:2.5.2'
As a result, we obtain:

List.get()in no case adds an item to the list. He is the opposite - he gets it. But still, it is not clear where you want to add, and what. - Vladyslav Matviienko