안드로이드 자바

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

teamnova 2023. 8. 4. 12:00
728x90

안녕하세요. 오늘은 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);
    }
}

 

실행 결과 화면입니다.