I will try to present the question correctly (open for comments / edits).

Perhaps I'll start from the beginning. There is a button by clicking on which the dialog opens. In the dialogue, the user can insert a link from vimeo and youtube. After the link is inserted into the dialog box and the "OK" button is pressed, in the getIdUrl method, the id is pulled out of the link, after which the picture itself is added from the video (preview) - the user (roughly speaking) sees how the picture from this video was added (hence the video uploaded).

At the moment, the application is implemented in such a way that the user can add an n-th video count (with the same links), which by itself is unacceptable.

The challenge is to find a solution to this problem, namely:

  • Add the ability for the user to add no more than 10 files.
  • If the link is repeated (url video), do not add it.

Excerpt dialogue:

public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); Toast.makeText(getContext(), "ОК", Toast.LENGTH_SHORT).show(); String string = input.getText().toString(); getIdUrl(string, pos); } 

And part of the implementation of the getIdUrl method for youtube:

 void getIdUrl(String url, int position) { String video_id = ""; String expression = ""; if (url != null && url.trim().length() > 0 && url.matches(".*\\byoutube\\b.*")) { expression = "^.*((youtu.be" + "\\/)" + "|(v\\/)|(\\/u\\/w\\/)|(embed\\/)|(watch\\?))\\??v?=?([^#\\&\\?]*).*"; CharSequence input = url; Pattern pattern = Pattern.compile(expression, Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(input); if (matcher.matches()) { String groupIndex1 = matcher.group(7); if (groupIndex1 != null && groupIndex1.length() == 11) video_id = groupIndex1; } ImageUpload imageUpload = new ImageUpload(); imageUpload.setLoadImage(true); OutputMetadata outputMetadata = new OutputMetadata(); outputMetadata.setVideoUrl("http://img.youtube.com/vi/" + video_id + "/0.jpg"); outputMetadata.setFilename("http://img.youtube.com/vi/" + video_id + "/0.jpg"); imageUpload.setOutputMetadata(outputMetadata); controlList.get(position).getImageUploads().add(imageUpload); adapterForm.notifyDataSetChanged(); 

In addition to parsing: Model VideoUpload

 public class VideoUpload { @SerializedName("id") @Expose private String id; @SerializedName("videoUrl") @Expose String videoUrl; @SerializedName("user_portrait_huge") @Expose private String userPortraitHuge; @SerializedName("url") @Expose private String url; public String getUserPortraitHuge() { return userPortraitHuge; } 

All get'ry and set'ry are registered.

Method contains (in fragment)

  public boolean contains(VideoUpload newVideoUpload) { for (VideoUpload videoUpload : videoUploads) { if (videoUpload.getUrl().equals(newVideoUpload.getUrl())) return true; } return false; } 
  • one
    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
  • @metalurgus at the moment I get one picture (preview) from the video I have processed, after which I can’t add more (the button itself disappears, because I assume that one position is added due to get (0)), but I need to enlarge number of added pictures. Shove something like list add probably. - Morozov
  • Well, so do not hide the button, what's the problem? - Vladyslav Matviienko
  • one
    At the moment your problem is not clear. Try to formulate something else. Type "I have an array of addresses of video files and I want to download everything at once by pressing the button. But I can only download one file." - Yuriy SPb ♦
  • Cycles are used to do any repeated operation N times, so based on the vague explanation that you provided, I advise you to use the cycle for those “dark rituals” that you are trying to crank;) - Eugene Troyanskii

2 answers 2

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=XXXXXXXXXXX
  • https://youtu.be/XXXXXXXXXXX
  • https://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:

enter image description here

  • Thanks, really great answer, helped me figure out the many nuances. At the moment I try, though partially, to transfer the implementation to my project. For example, there is a hitch in your contains method, I also refer to my String model, and it gives me required java.lang.string, found ... image.VideoUpload. Perhaps tell me what could be the snag? - Morozov
  • The problem is type mismatch. Using equals(...) I compare video links (such as String ) of one object with another. And you? - post_zeew
  • Yes, I understood that. But I also have a type String getVideoUrl in my model, and I don’t really understand why such a mistake. - Morozov
  • Show your data model and adapter's contains(...) method. - post_zeew
  • Completed the question. - Morozov

My understanding of the problem is:

The author has a public void success(ArrayList<VideoUpload> videoUpload, Response response) method public void success(ArrayList<VideoUpload> videoUpload, Response response) , in this method he wants to change the data controlList.get(pos).getImageUploads() , which, apparently, is ArrayList<SomeObject> according to the received ArrayList<VideoUpload> videoUpload .

At the moment, it changes the data of only the first element controlList.get(pos).getImageUploads() in accordance with the first element of ArrayList<VideoUpload> videoUpload (as indicated by calling the get(...) method on both lists with parameter 0 ).

Based on the foregoing, it follows that the size of ArrayList<VideoUpload> videoUpload and controlList.get(pos).getImageUploads() must match.

Thus, the solution to the problem is the following code for the method success(...) :

 @Override public void success(ArrayList<VideoUpload> videoUpload, Response response) { for(int i=0; i<videoUpload.size(); i++) { controlList.get(pos).getImageUploads().get(i).setLoadImage(true); controlList.get(pos).getImageUploads().get(i).getOutputMetadata().setVideoUrl(videoUpload.get(i).getUserPortraitHuge()); controlList.get(pos).getImageUploads().get(i).getOutputMetadata().setFilename(videoUpload.get(i).getUserPortraitHuge()); } adapterForm.notifyDataSetChanged(); Log.d("succes", "sisisihjdf"); } 

UPD.

 public void success(ArrayList<VideoUpload> videoUpload, Response response) { ImageUpload imageUpload = new ImageUpload(); imageUpload.setLoadImage(true); imageUpload.getOutputMetadata().setVideoUrl(videoUpload.get().getUserPortraitHuge()); imageUpload.getOutputMetadata().setFilename(videoUpload.get().getUserPortraitHuge()); } 

Tell me what value can be inserted into the value of get (?)?

Any integer i such that 0 <= i < videoUpload.size() depending on which videoUpload list videoUpload you want to receive.

  • one
    You have a very incomprehensible ( at least for me ) context. As an option - edit your question in this way: first, fully and clearly formulate your task in words (without code). Then in parts describe (with a code) how you solve this problem. Well, in the end write what does not work. - post_zeew
  • Thank you, this time I tried to take into account all the points. I worked on the bugs, adding to the decision, and then updated the question. - Morozov
  • Will you be satisfied if I write you a solution to your problem from scratch? - post_zeew
  • Is it really so bad in my code? (Plus I am not sure that your code will work for me, at the moment this is a priority (although I don’t hide it, there is no doubt that you will be interested in your implementation). I’m just afraid that I will not be able to implement it, if suddenly. - Morozov
  • I don’t really like to recycle large fragments of someone else’s code, especially under the assumption that something there might not work correctly. - post_zeew pm