본문 바로가기
안드로이드 자바

[Android][Java]유튜브 API를 이용해서 유뷰트 비디오 검색하기

by teamnova 2023. 8. 4.

안녕하세요. 오늘은 YOUTUBE API를 사용해서 유뷰트 비디오를 검색하고, 그에 맞는 정보를 받아와서  리싸이클러뷰에 담아주는 방법을 알아보도록 하겠습니다. 

 

다음의 포스팅을 참고하셔서 YOUTUBE API를 먼저 설정해주세요.

https://stickode.tistory.com/331 

 

[JAVA][Android] Youtube API 사용법

이번에는 유튜브 API 를 사용해보겠습니다. https://stickode.com/detail.html?no=2714 스틱코드 stickode.com 위의 포스트를 즐겨찾기 하시면 'Activity_Youtube.java' 를 입력하여, 해당 코드를 사용할 수 있습니다. 1.

stickode.tistory.com

build.gradle 파일에 다음의 depencies를 추가해주세요.

implementation 'com.github.bumptech.glide:glide:4.15.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'

main.xml  파일입니다. 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <!--검색어 입력창-->
    <EditText
        android:id="@+id/search"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="26dp"
        android:layout_marginEnd="13dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text=""
        app:layout_constraintEnd_toStartOf="@+id/button"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <!--검색버튼-->
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="22dp"
        android:layout_marginEnd="5dp"
        android:layout_marginBottom="47dp"
        android:text="Button"
        app:layout_constraintBottom_toTopOf="@+id/recyclerview"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/search"
        app:layout_constraintTop_toTopOf="parent" />

<!--리싸이클러뷰-->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="23dp"
        android:layout_marginEnd="23dp"
        android:layout_marginBottom="36dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button" />

</androidx.constraintlayout.widget.ConstraintLayout>

다음은 리싸이클러뷰 item을 담아줄 item_utube.xml 파일입니다. 

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >
<!-- 썸네일 이미지뷰-->
    <ImageView
        android:id="@+id/titleImage"
        android:layout_width="200dp"
        android:layout_height="100dp"
        android:src="@color/cardview_dark_background"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"></ImageView>

    <!-- 제목표시 텍스트뷰-->
    <TextView
        android:id="@+id/titleText"
        android:layout_width="200dp"
        android:layout_height="50dp"
        android:ellipsize="end"
        android:maxLines="2"
        android:text="title"
        app:layout_constraintStart_toEndOf="@+id/titleImage"
        app:layout_constraintTop_toTopOf="parent"></TextView>
    <!-- 날짜표시 텍스트뷰-->
    <TextView
        android:id="@+id/dateText"
        android:layout_width="200dp"
        android:layout_height="50dp"
        android:layout_gravity="center"
        android:singleLine="true"
        android:text="time"
        app:layout_constraintStart_toStartOf="@+id/titleText"
        app:layout_constraintTop_toBottomOf="@+id/titleText"></TextView>



</androidx.constraintlayout.widget.ConstraintLayout>

main.java 파일입니다.

package com.example.youtubesearch;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.nfc.Tag;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;

import javax.security.auth.login.LoginException;

public class MainActivity extends AppCompatActivity {

    EditText search;
    Button button;
    RecyclerView recyclerview;
    UtubeAdapter utubeAdapter;
    AsyncTask<?, ?, ?> searchTask;

    ArrayList<SearchData> sdata = new ArrayList<SearchData>();

    final String serverKey="본인의 유튜브 API 키를 입력해주세요";




    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        search = findViewById(R.id.search);
        button = findViewById(R.id.button);
        recyclerview= findViewById(R.id.recyclerview);
        LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(this);
        recyclerview.setLayoutManager(mLinearLayoutManager);

        //버튼 클릭시 검색한 정보를 가져옴. 
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                
                searchTask = new searchTask().execute();

            }
        });
    }

    private class searchTask extends AsyncTask<Void, Void, Void> { 
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected Void doInBackground(Void... params) {
            try {
                paringJsonData(getUtube()); //비동기로 가져온 데이터를 파싱

            } catch (JSONException | IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            utubeAdapter = new UtubeAdapter(MainActivity.this, sdata);
            recyclerview.setAdapter(utubeAdapter);
            utubeAdapter.notifyDataSetChanged(); //가져온 데이터 리싸이클러뷰에 업데이트
        }
    }

    //검색한 결과들을 json 객체로 생성
    public JSONObject getUtube() throws IOException {


        String originUrl = "https://www.googleapis.com/youtube/v3/search?"
                + "part=snippet&q=" + search.getText().toString()
                + "&key="+ serverKey+"&maxResults=50";

        String myUrl = String.format(originUrl);

        URL url = new URL(myUrl);

        HttpURLConnection connection =(HttpURLConnection)url.openConnection();
        connection.setRequestMethod("GET");
        connection.setReadTimeout(10000);
        connection.setConnectTimeout(15000);
        connection.connect();

        String line;
        String result="";
        InputStream inputStream=connection.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuffer response = new StringBuffer();

        while ((line = reader.readLine())!=null){
            response.append(line);
        }
        System.out.println("검색결과"+ response);
        result=response.toString();


        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject = new JSONObject(result);
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return jsonObject;
    }

    //json 객체 파싱
    private void paringJsonData(JSONObject jsonObject) throws JSONException {
        //재검색할때 데이터들이 쌓이는걸 방지하기 위해 리스트를 초기화 시켜준다.
        sdata.clear();

        JSONArray contacts = jsonObject.getJSONArray("items");
        for (int i = 0; i < contacts.length(); i++) {
            JSONObject c = contacts.getJSONObject(i);
            String kind =  c.getJSONObject("id").getString("kind"); // 종류를 체크하여 playlist도 저장
            if(kind.equals("youtube#video")){
                // 유튜브 비디오 검색
                vodid = c.getJSONObject("id").getString("videoId");
            }else{
                // 유튜브 채널검색
                vodid = c.getJSONObject("id").getString("playlistId");
            }

            String title = c.getJSONObject("snippet").getString("title"); //유튜브 제목

            String changString = stringToHtmlSign(title);

            String date = c.getJSONObject("snippet").getString("publishedAt") //등록날짜
                    .substring(0, 10);
            String imgUrl = c.getJSONObject("snippet").getJSONObject("thumbnails")
                    .getJSONObject("default").getString("url");  //썸네일 이미지 URL값

            String channel = c.getJSONObject("snippet").getString("channelTitle");
           
            //JSON으로 파싱한 정보들을 객체화 시켜서 리스트에 담아준다.
            sdata.add(new SearchData(vodid, changString, imgUrl, date));
        }
    }
    
    String vodid = "";


    //영상 제목을 받아올때 &quot; &#39; 문자가 그대로 출력되기 때문에 다른 문자로 대체 
    private String stringToHtmlSign(String str) {

        return str.replaceAll("&amp;", "[&]")

                .replaceAll("[<]", "&lt;")

                .replaceAll("[>]", "&gt;")

                .replaceAll("&quot;", "'")

                .replaceAll("&#39;", "'");
    }


}

받아온 데이터를 담아줄 SearchData.java 파일입니다.

package com.example.youtubesearch;

public class SearchData {
    String videoId;
    String title;
    String ImageUrl;
    String publishedAt;

    public SearchData(String videoId, String title, String ImageUrl,
                      String publishedAt) {
        super();
        this.videoId = videoId;
        this.title = title;
        this.ImageUrl = ImageUrl;
        this.publishedAt = publishedAt;
    }

    public String getVideoId() {
        return videoId;
    }

    public void setVideoId(String videoId) {
        this.videoId = videoId;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getImageUrl() {
        return ImageUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.ImageUrl = imageUrl;
    }

    public String getPublishedAt() {
        return publishedAt;
    }

    public void setPublishedAt(String publishedAt) {
        this.publishedAt = publishedAt;
    }
}

UtubeAdapter.java 파일입니다.

package com.example.youtubesearch;

import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import java.util.ArrayList;

public class UtubeAdapter extends RecyclerView.Adapter<UtubeAdapter.UtubeViewHolder> {

    ArrayList<SearchData> mList;
    Context context;

    public UtubeAdapter(Context context, ArrayList<SearchData> list) {
        this.context = context;
        this.mList = list;
    }

    public class UtubeViewHolder extends RecyclerView.ViewHolder{

        ImageView titleImage;
        TextView titleText;
        TextView dateText;

        public UtubeViewHolder(@NonNull View itemView) {
            super(itemView);

            this.titleImage=itemView.findViewById(R.id.titleImage);
            this.titleText=itemView.findViewById(R.id.titleText);
            this.dateText=itemView.findViewById(R.id.dateText);

        }
    }
    

    @NonNull
    @Override
    public UtubeAdapter.UtubeViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {


        //item_utube xml파일을 객체화 
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_utube, viewGroup, false);
        UtubeAdapter.UtubeViewHolder holder = new UtubeAdapter.UtubeViewHolder(view);

        return holder;
    }

    @Override
    public void onBindViewHolder(@NonNull UtubeAdapter.UtubeViewHolder viewholder, int position) {


        //영상제목 세팅
        viewholder.titleText.setText(mList.get(position).getTitle());
        //날짜 세팅
        viewholder.dateText.setText(mList.get(position).getPublishedAt());


        //이미지를 넣어주기 위해 이미지url을 가져온다.
        String imageUrl = mList.get(position).getImageUrl();
        //영상 썸네일 세팅
        Glide.with(viewholder.titleImage)
                .load(imageUrl)
                .into(viewholder.titleImage);


    }

    @Override
    public int getItemCount() {
        return (null != mList ? mList.size() : 0);
    }
}

 

실행 결과 화면입니다.