Android

유튜브 API ν‚€μ›Œλ“œ κ²€μƒ‰ν•˜λ©΄ ν‚€μ›Œλ“œμ— λ§žλŠ” κ²Œμ‹œλ¬Όμ„ κ°€μ Έμ˜€λŠ” app개발

567Rabbit 2024. 6. 12. 15:45

https://codebunny99.tistory.com/163

 

유튜브 데이터 APIλ₯Ό Postman(포슀트맨)으둜 μ‚¬μš©ν•˜λŠ” 방법

https://console.cloud.google.com/welcome/new?hl=ko&project=eastern-surface-426200-r0&supportedpurview=project Google ν΄λΌμš°λ“œ ν”Œλž«νΌλ‘œκ·ΈμΈ Google ν΄λΌμš°λ“œ ν”Œλž«νΌμœΌλ‘œ 이동accounts.google.com  youtube data κ²€μƒ‰ν•΄μ„œ μ‚¬μš© λˆ„λ₯΄

codebunny99.tistory.com

 

ν‚€(key) 값을 μœ„μ˜ ν¬μŠ€νŒ…μ„ λ¨Όμ € μ°Έκ³ ν•΄ κ°€μ Έμ˜¨λ‹€.

 

 

 

유튜브 APIλ₯Ό Postman으둜 μ‹€ν–‰μ‹œν‚€λ©΄, λ‹€μŒκ³Ό 같이 Json νŒŒμΌμ„ μ€€λ‹€.

 

 

 

 

 

 

 

 

MainActivity

 

λ””μžμΈ(xml 파일)

 

 

 

 

java
λ‹«κΈ°
<?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:id="@+id/main" ​​​​android:layout_width="match_parent" ​​​​android:layout_height="match_parent" ​​​​tools:context=".MainActivity"> ​​​​<RelativeLayout ​​​​​​​​android:layout_width="match_parent" ​​​​​​​​android:layout_height="match_parent" ​​​​​​​​app:layout_constraintBottom_toBottomOf="parent" ​​​​​​​​app:layout_constraintEnd_toEndOf="parent" ​​​​​​​​app:layout_constraintStart_toStartOf="parent" ​​​​​​​​app:layout_constraintTop_toTopOf="parent"> ​​​​​​​​<LinearLayout ​​​​​​​​​​​​android:id="@+id/topLayout" ​​​​​​​​​​​​android:layout_width="match_parent" ​​​​​​​​​​​​android:layout_height="wrap_content" ​​​​​​​​​​​​android:layout_alignParentTop="true" ​​​​​​​​​​​​android:layout_margin="10dp" ​​​​​​​​​​​​android:orientation="horizontal"> ​​​​​​​​​​​​<EditText ​​​​​​​​​​​​​​​​android:id="@+id/editSearch" ​​​​​​​​​​​​​​​​android:layout_width="wrap_content" ​​​​​​​​​​​​​​​​android:layout_height="wrap_content" ​​​​​​​​​​​​​​​​android:layout_marginRight="5dp" ​​​​​​​​​​​​​​​​android:layout_weight="5" ​​​​​​​​​​​​​​​​android:ems="10" ​​​​​​​​​​​​​​​​android:hint="검색어 μž…λ ₯..." ​​​​​​​​​​​​​​​​android:inputType="text" ​​​​​​​​​​​​​​​​android:textSize="22sp" /> ​​​​​​​​​​​​<ImageView ​​​​​​​​​​​​​​​​android:id="@+id/imgSearch" ​​​​​​​​​​​​​​​​android:layout_width="45dp" ​​​​​​​​​​​​​​​​android:layout_height="45dp" ​​​​​​​​​​​​​​​​app:srcCompat="@drawable/search_24dp" /> ​​​​​​​​</LinearLayout> ​​​​​​​​<androidx.recyclerview.widget.RecyclerView ​​​​​​​​​​​​android:id="@+id/recyclerView" ​​​​​​​​​​​​android:layout_width="match_parent" ​​​​​​​​​​​​android:layout_height="match_parent" ​​​​​​​​​​​​android:layout_below="@id/topLayout" /> ​​​​​​​​<ProgressBar ​​​​​​​​​​​​android:id="@+id/progressBar" ​​​​​​​​​​​​style="?android:attr/progressBarStyle" ​​​​​​​​​​​​android:layout_width="wrap_content" ​​​​​​​​​​​​android:layout_height="wrap_content" ​​​​​​​​​​​​android:layout_centerInParent="true" /> ​​​​</RelativeLayout> </androidx.constraintlayout.widget.ConstraintLayout>

 

 

 

 

 

MainActivity.java (νŒŒμ‹±ν•˜κΈ°)

java
λ‹«κΈ°
package com.~.youtube; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.android.volley.Request; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.JsonObjectRequest; import com.android.volley.toolbox.Volley; import com.google.android.material.snackbar.Snackbar; import com.~.youtube.adapter.YoutubeAdapter; import com.~.youtube.config.Config; import com.~.youtube.model.Youtube; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { ​​​​ProgressBar progressBar; ​​​​ImageView imgSearch; ​​​​EditText editSearch; ​​​​// λ¦¬μ‚¬μ΄ν΄λŸ¬λ·°λŠ” κ΄€λ ¨λœ λ©€λ²„λ³€μˆ˜ 2개 더 μž‘μ„±ν•΄μ•Ό ν•œλ‹€ ​​​​RecyclerView recyclerView; ​​​​ArrayList<Youtube> YoutubeArrayList = new ArrayList<>(); ​​​​YoutubeAdapter adapter; ​​​​@Override ​​​​protected void onCreate(Bundle savedInstanceState) { ​​​​​​​​super.onCreate(savedInstanceState); ​​​​​​​​setContentView(R.layout.activity_main); ​​​​​​​​getSupportActionBar().setTitle("YoutubeApp"); ​​​​​​​​// λ‹€μŒ μ½”λ“œλŠ” 쌍으둜 무쑰건 같이 μž‘μ„± ​​​​​​​​recyclerView = findViewById(R.id.recyclerView); ​​​​​​​​recyclerView.setHasFixedSize(true); ​​​​​​​​recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this)); ​​​​​​​​progressBar = findViewById(R.id.progressBar); ​​​​​​​​imgSearch = findViewById(R.id.imgSearch); ​​​​​​​​editSearch = findViewById(R.id.editSearch); ​​​​​​​​// ν”„λ‘œκ·Έλ ˆμŠ€ λ°”λ₯Ό μœ μ €μ˜ λˆˆμ—μ„œ μ‚¬λΌμ§€κ²Œ ν•˜λŠ” μ½”λ“œ ​​​​​​​​progressBar.setVisibility(View.GONE); ​​​​​​​​imgSearch.setOnClickListener(new View.OnClickListener() { ​​​​​​​​​​​​@Override ​​​​​​​​​​​​public void onClick(View v) { ​​​​​​​​​​​​​​​​String keyword = editSearch.getText().toString().trim(); ​​​​​​​​​​​​​​​​if(keyword.isEmpty()){ ​​​​​​​​​​​​​​​​​​​​Snackbar.make(imgSearch, "검색어λ₯Ό μž…λ ₯ν•˜μ„Έμš”.", Snackbar.LENGTH_SHORT).show(); ​​​​​​​​​​​​​​​​​​​​return; ​​​​​​​​​​​​​​​​} ​​​​​​​​​​​​​​​​// ν”„λ‘œκ·Έλ ˆμŠ€ λ°”λ₯Ό μœ μ €μ˜ λˆˆμ— 보이게 ν•˜λŠ” μ½”λ“œ ​​​​​​​​​​​​​​​​progressBar.setVisibility(View.VISIBLE); ​​​​​​​​​​​​​​​​// 1. request queue λ₯Ό λ§Œλ“ λ‹€ ​​​​​​​​​​​​​​​​RequestQueue queue = Volley.newRequestQueue(MainActivity.this); ​​​​​​​​​​​​​​​​// 2. request(μš”μ²­)을 λ§Œλ“ λ‹€. ​​​​​​​​​​​​​​​​// 데이터 νƒ€μž…μ€, μ‘λ‹΅μ˜ json ν˜•μ‹μ„ 보고 κ²°μ •ν•œλ‹€. ​​​​​​​​​​​​​​​​JsonObjectRequest request = new JsonObjectRequest( ​​​​​​​​​​​​​​​​​​​​​​​​Request.Method.GET, ​​​​​​​​​​​​​​​​​​​​​​​​"https://www.googleapis.com/youtube/v3/search?key=" + Config.YoutubeKey + "&part=snippet&maxResults=20&order=date&q=" + keyword + "&type=video", ​​​​​​​​​​​​​​​​​​​​​​​​null, ​​​​​​​​​​​​​​​​​​​​​​​​new Response.Listener<JSONObject>() { ​​​​​​​​​​​​​​​​​​​​​​​​​​​​@Override ​​​​​​​​​​​​​​​​​​​​​​​​​​​​public void onResponse(JSONObject response) { ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​// ν”„λ‘œκ·Έλ ˆμŠ€ λ°”λ₯Ό μœ μ €μ˜ λˆˆμ—μ„œ μ‚¬λΌμ§€κ²Œ ν•˜λŠ” μ½”λ“œ ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​progressBar.setVisibility(View.GONE); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​try { ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​JSONArray items = response.getJSONArray("items"); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​YoutubeArrayList.clear(); // κΈ°μ‘΄ 데이터 μ΄ˆκΈ°ν™” ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​for (int i = 0; i < items.length(); i++) { ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​JSONObject data = items.getJSONObject(i); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​JSONObject id = data.getJSONObject("id"); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​String videoId = id.getString("videoId"); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​JSONObject snippet = data.getJSONObject("snippet"); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​String title = snippet.getString("title"); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​String description = snippet.getString("description"); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​JSONObject thumbnails = snippet.getJSONObject("thumbnails"); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​JSONObject medium = thumbnails.getJSONObject("medium"); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​String thumbUrl = medium.getString("url"); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​JSONObject high = thumbnails.getJSONObject("high"); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​String url = high.getString("url"); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​Youtube youtube = new Youtube(videoId, title, description, thumbUrl, url); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​YoutubeArrayList.add(youtube); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​} ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​// μ–΄λŒ‘ν„°λ₯Ό λ§Œλ“€κ³  ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​adapter = new YoutubeAdapter(MainActivity.this, YoutubeArrayList); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​// λ¦¬μ‚¬μ΄ν΄λŸ¬λ·°μ— μ–΄λŒ‘ν„°λ₯Ό μ μš©ν•˜λ©΄ 화면에 λ‚˜μ˜¨λ‹€ ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​recyclerView.setAdapter(adapter); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​} catch (JSONException e) { ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​Toast.makeText(MainActivity.this, "νŒŒμ‹± μ—λŸ¬", Toast.LENGTH_SHORT).show(); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​e.printStackTrace(); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​} ​​​​​​​​​​​​​​​​​​​​​​​​​​​​} ​​​​​​​​​​​​​​​​​​​​​​​​}, ​​​​​​​​​​​​​​​​​​​​​​​​new Response.ErrorListener() { ​​​​​​​​​​​​​​​​​​​​​​​​​​​​@Override ​​​​​​​​​​​​​​​​​​​​​​​​​​​​public void onErrorResponse(VolleyError volleyError) { ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​// ν”„λ‘œκ·Έλ ˆμŠ€ λ°”λ₯Ό μœ μ €μ˜ λˆˆμ—μ„œ μ‚¬λΌμ§€κ²Œ ν•˜λŠ” μ½”λ“œ ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​progressBar.setVisibility(View.GONE); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​Toast.makeText(MainActivity.this, "λ„€νŠΈμ›Œν¬ 톡신 μ—λŸ¬", Toast.LENGTH_SHORT).show(); ​​​​​​​​​​​​​​​​​​​​​​​​​​​​} ​​​​​​​​​​​​​​​​​​​​​​​​} ​​​​​​​​​​​​​​​​); ​​​​​​​​​​​​​​​​// 3. λ„€νŠΈμ›Œν¬λ‘œ 보낸닀. ​​​​​​​​​​​​​​​​queue.add(request); ​​​​​​​​​​​​} ​​​​​​​​}); ​​​​} }

 

 

 

 

 

Config 클래슀

 

java
λ‹«κΈ°
package com.~.youtube.config; public class Config { ​​​​public static final String YoutubeKey = "μžμ‹ μ˜ ν‚€κ°’ μž…λ ₯"; }

 

 

 

 

 

Youtube 클래슀

 

java
λ‹«κΈ°
package com.~.youtube.model; import java.io.Serializable; public class Youtube implements Serializable { ​​​​public String videoId; ​​​​public String thumbUrl; ​​​​public String url; ​​​​public String title; ​​​​public String description; ​​​​public Youtube(){ ​​​​} ​​​​public Youtube(String videoId, String title, String description, String thumbUrl, String url) { ​​​​​​​​this.videoId = videoId; ​​​​​​​​this.thumbUrl = thumbUrl; ​​​​​​​​this.url = url; ​​​​​​​​this.title = title; ​​​​​​​​this.description = description; ​​​​} }

 

 

 

 

 

activity_row .xml λ§Œλ“€κΈ°

 

λ””μžμΈ(xml 파일)

java
λ‹«κΈ°
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" ​​​​android:layout_width="match_parent" ​​​​android:layout_height="wrap_content" ​​​​android:orientation="vertical"> ​​​​<androidx.cardview.widget.CardView ​​​​​​​​android:id="@+id/cardView" ​​​​​​​​android:layout_width="match_parent" ​​​​​​​​android:layout_height="match_parent" ​​​​​​​​android:layout_marginLeft="15dp" ​​​​​​​​android:layout_marginTop="7dp" ​​​​​​​​android:layout_marginRight="15dp" ​​​​​​​​android:layout_marginBottom="7dp"> ​​​​​​​​<LinearLayout ​​​​​​​​​​​​android:layout_width="match_parent" ​​​​​​​​​​​​android:layout_height="wrap_content" ​​​​​​​​​​​​android:layout_margin="10dp" ​​​​​​​​​​​​android:orientation="vertical"> ​​​​​​​​​​​​<TextView ​​​​​​​​​​​​​​​​android:id="@+id/txtTitle" ​​​​​​​​​​​​​​​​android:layout_width="match_parent" ​​​​​​​​​​​​​​​​android:layout_height="wrap_content" ​​​​​​​​​​​​​​​​android:ellipsize="end" ​​​​​​​​​​​​​​​​android:maxLines="1" ​​​​​​​​​​​​​​​​android:text="TextView" ​​​​​​​​​​​​​​​​android:textSize="24sp" /> ​​​​​​​​​​​​<TextView ​​​​​​​​​​​​​​​​android:id="@+id/txtDescription" ​​​​​​​​​​​​​​​​android:layout_width="match_parent" ​​​​​​​​​​​​​​​​android:layout_height="wrap_content" ​​​​​​​​​​​​​​​​android:layout_marginLeft="20dp" ​​​​​​​​​​​​​​​​android:layout_marginTop="7dp" ​​​​​​​​​​​​​​​​android:layout_marginBottom="10dp" ​​​​​​​​​​​​​​​​android:ellipsize="end" ​​​​​​​​​​​​​​​​android:maxLines="2" ​​​​​​​​​​​​​​​​android:text="TextView" ​​​​​​​​​​​​​​​​android:textSize="20sp" /> ​​​​​​​​​​​​<ImageView ​​​​​​​​​​​​​​​​android:id="@+id/imgThumb" ​​​​​​​​​​​​​​​​android:layout_width="320dp" ​​​​​​​​​​​​​​​​android:layout_height="180dp" ​​​​​​​​​​​​​​​​android:layout_gravity="center" ​​​​​​​​​​​​​​​​android:src="@drawable/image_24dp" /> ​​​​​​​​</LinearLayout> ​​​​</androidx.cardview.widget.CardView> </LinearLayout>

 

 

 

 

 

Adapter λ§Œλ“€κΈ°

java
λ‹«κΈ°
package com.~.youtube.adapter; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.webkit.WebView; import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.~.youtube.R; import com.~.youtube.model.Youtube; import com.bumptech.glide.Glide; import java.util.ArrayList; public class YoutubeAdapter extends RecyclerView.Adapter<YoutubeAdapter.ViewHolder>{ ​​​​Context context; ​​​​ArrayList<Youtube> YoutubeArrayList; ​​​​public YoutubeAdapter(Context context, ArrayList<Youtube> YoutubeArrayList) { ​​​​​​​​this.context = context; ​​​​​​​​this.YoutubeArrayList = YoutubeArrayList; ​​​​} ​​​​@NonNull ​​​​@Override ​​​​public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { ​​​​​​​​View view = LayoutInflater.from(parent.getContext()) ​​​​​​​​​​​​​​​​.inflate(R.layout.activity_row, parent, false); ​​​​​​​​return new YoutubeAdapter.ViewHolder(view); ​​​​} ​​​​@Override ​​​​public void onBindViewHolder(@NonNull ViewHolder holder, int position) { ​​​​​​​​Youtube youtube = YoutubeArrayList.get(position); ​​​​​​​​holder.txtTitle.setText( youtube.title ); ​​​​​​​​holder.txtDescription.setText( youtube.description ); ​​​​​​​​Glide.with(context).load( youtube.thumbUrl ).into( holder.imgThumb ); ​​​​} ​​​​@Override ​​​​public int getItemCount() { ​​​​​​​​return YoutubeArrayList.size(); ​​​​} ​​​​public class ViewHolder extends RecyclerView.ViewHolder { ​​​​​​​​TextView txtTitle; ​​​​​​​​TextView txtDescription; ​​​​​​​​ImageView imgThumb; ​​​​​​​​public ViewHolder(@NonNull View itemView) { ​​​​​​​​​​​​super(itemView); ​​​​​​​​​​​​txtTitle = itemView.findViewById(R.id.txtTitle); ​​​​​​​​​​​​txtDescription = itemView.findViewById(R.id.txtDescription); ​​​​​​​​​​​​imgThumb = itemView.findViewById(R.id.imgThumb); ​​​​​​​​} ​​​​} }

 

 

 

 

 

 

μΉ΄λ“œλ·° μ„ νƒν•˜λ©΄ 유튜브둜 μ΄λ™ν•˜κ²Œ ν•˜κΈ°

 

- Adapterμ—μ„œ μΆ”κ°€ν•œλ‹€.

 

 

μΉ΄λ“œλ·°λ₯Ό ν΄λ¦­ν•˜λ©΄ 유튜브둜 μ΄λ™ν•˜λŠ” 것도 μΆ”κ°€ν•΄μ€€λ‹€.

 

 

 

java
λ‹«κΈ°
public class ViewHolder extends RecyclerView.ViewHolder { ​​​​​​​​TextView txtTitle; ​​​​​​​​TextView txtDescription; ​​​​​​​​ImageView imgThumb; ​​​​​​​​CardView cardView; ​​​​​​​​ ​​​​​​​​public ViewHolder(@NonNull View itemView) { ​​​​​​​​​​​​super(itemView); ​​​​​​​​​​​​txtTitle = itemView.findViewById(R.id.txtTitle); ​​​​​​​​​​​​txtDescription = itemView.findViewById(R.id.txtDescription); ​​​​​​​​​​​​imgThumb = itemView.findViewById(R.id.imgThumb); ​​​​​​​​​​​​cardView = itemView.findViewById(R.id.cardView); ​​​​​​​​​​​​cardView.setOnClickListener(new View.OnClickListener() { ​​​​​​​​​​​​​​​​@Override ​​​​​​​​​​​​​​​​public void onClick(View v) { ​​​​​​​​​​​​​​​​​​​​int index = getAdapterPosition(); ​​​​​​​​​​​​​​​​​​​​Youtube youtube = YoutubeArrayList.get(index); ​​​​​​​​​​​​​​​​​​​​String url = "https://www.youtube.com/watch?v=" + youtube.videoId; ​​​​​​​​​​​​​​​​​​​​openWebPage(url); ​​​​​​​​​​​​​​​​} ​​​​​​​​​​​​}); ​​​​​​​​} ​​​​​​​​// μ›ΉλΈŒλΌμš°μ € μ•‘ν‹°λΉ„ν‹°λ₯Ό μ‹€ν–‰μ‹œν‚€λŠ” ν•¨μˆ˜ ​​​​​​​​void openWebPage(String url){ ​​​​​​​​​​​​Uri uri = Uri.parse(url); ​​​​​​​​​​​​Intent intent = new Intent(Intent.ACTION_VIEW, uri); ​​​​​​​​​​​​context.startActivity(intent); ​​​​​​​​} ​​​​}