본문 바로가기
Android

Android [유튜브API동영상리스트불러오는앱] 페이징처리, url파싱, 카드뷰 선택시 웹브라우저 실행

by leopard4 2023. 2. 8.

살펴보아야할부분

url파싱

페이징처리 ( addNetworkData() 함수)

아래코드에서 호출한 url

 

 

 

 

메인액티비티.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">

    <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/layoutTop"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_marginStart="10dp"
            android:layout_marginTop="10dp"
            android:layout_marginEnd="10dp"
            android:layout_marginBottom="10dp"
            android:orientation="horizontal">

            <EditText
                android:id="@+id/editSearch"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:ems="10"
                android:hint="검색어 입력..."
                android:inputType="textPersonName"
                android:textSize="26sp" />

            <ImageView
                android:id="@+id/imgSearch"
                android:layout_width="45dp"
                android:layout_height="45dp"
                android:layout_gravity="center"
                app:srcCompat="@drawable/ic_baseline_search_24" />
        </LinearLayout>

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/layoutTop"
            android:layout_alignParentBottom="false" />

        <ProgressBar
            android:id="@+id/progressBar"
            style="?android:attr/progressBarStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:visibility="gone" />

    </RelativeLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

 

video_row.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <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"
                app:srcCompat="@drawable/ic_baseline_ondemand_video_24" />
        </LinearLayout>
    </androidx.cardview.widget.CardView>
</LinearLayout>

 

기능추가 ( 카드뷰 선택시 웹브라우저 실행(유튜브 앱이있다면 앱이 실행됨), 썸네일 선택시 썸네일확대)

 

 

메인액티비티

package com.leopard4.youtubeapiapp;

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

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;

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.leopard4.youtubeapiapp.adapter.VideoAdapter;
import com.leopard4.youtubeapiapp.config.Config;
import com.leopard4.youtubeapiapp.model.Video;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    EditText editSearch;
    ImageView imgSearch;
    ProgressBar progressBar;

    RecyclerView recyclerView;
    VideoAdapter adapter;
    ArrayList<Video> videoList = new ArrayList<>();

    String keyword;
    String pageToken;

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

        editSearch = findViewById(R.id.editSearch);
        imgSearch = findViewById(R.id.imgSearch);
        progressBar = findViewById(R.id.progressBar);
        recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));

        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
            }

            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                // 맨 마지막 데이터가 화면에 보이면!!!!
                // 네트워크 통해서 데이터를 추가로 받아와라!!
                int lastPosition = ((LinearLayoutManager)recyclerView.getLayoutManager()).findLastCompletelyVisibleItemPosition();
                int totalCount = recyclerView.getAdapter().getItemCount();

                // 스크롤을 데이터 맨 끝까지 한 상태.
                if(lastPosition + 1 == totalCount){
                    // 네트워크 통해서 데이터를 받아오고, 화면에 표시!
                    addNetworkData();
                }



            }
        });
        // editSearch를 클릭했을때
        // editSearch에 있는 텍스트를 지워준다.
        editSearch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                editSearch.setText("");
            }
        });


        imgSearch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                keyword = editSearch.getText().toString().trim();

                if(keyword.isEmpty()){
                    return;
                }

                // 네트워크 데이터 처리하는 함수 호출
                getNetworkData();

            }
        });

    }

    private void getNetworkData() {
        // 유투브 API 호출
        RequestQueue queue = Volley.newRequestQueue(MainActivity.this);
        String url = Config.BASE_URL + Config.PATH
                + Config.API_KEY
                + "&part=snippet&q="+keyword
                +"&maxResults=20&type=video";

        JsonObjectRequest request = new JsonObjectRequest(
                Request.Method.GET,
                url,
                null,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {

                        progressBar.setVisibility(View.GONE);

                        // 검색어를 다른것으로 바꿧을때처리
                        // 초기화 작업
                        videoList.clear();
                        pageToken = null;

                        try {

                            pageToken = response.getString("nextPageToken");

                            JSONArray items = response.getJSONArray("items");

                            for(int i = 0; i < items.length(); i++){
                                JSONObject item = items.getJSONObject(i);

                                String videoId = item.getJSONObject("id").getString("videoId");
                                String title = item.getJSONObject("snippet").getString("title");
                                String description = item.getJSONObject("snippet").getString("description");
                                String mediumUrl = item.getJSONObject("snippet").getJSONObject("thumbnails").getJSONObject("medium").getString("url");
                                String highUrl = item.getJSONObject("snippet").getJSONObject("thumbnails").getJSONObject("high").getString("url");

                                Video video = new Video(videoId, title, description, mediumUrl, highUrl);

                                videoList.add(video);

                            }

                        } catch (JSONException e) {
                            e.printStackTrace();
                            return;
                        }

                        // 어댑터가 null이면 새로 만들어주고, null이 아니면 데이터를 갱신해준다.
                        if(adapter == null){
                            adapter = new VideoAdapter(MainActivity.this, videoList);
                            recyclerView.setAdapter(adapter);
                        }else{
                            adapter.notifyDataSetChanged();
                        }

                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        progressBar.setVisibility(View.GONE);
                    }
                }
        );

        progressBar.setVisibility(View.VISIBLE);
        queue.add(request);
    }

    private void addNetworkData(){

        RequestQueue queue = Volley.newRequestQueue(MainActivity.this);
        String url = Config.BASE_URL + Config.PATH
                + Config.API_KEY
                + "&part=snippet&q="+keyword
                +"&type=video&maxResults=20&pageToken="+pageToken;

        JsonObjectRequest request = new JsonObjectRequest(
                Request.Method.GET,
                url,
                null,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {

                        progressBar.setVisibility(View.GONE);

                        try {

                            pageToken = response.getString("nextPageToken");

                            JSONArray items = response.getJSONArray("items");

                            for(int i = 0; i < items.length(); i++){
                                JSONObject item = items.getJSONObject(i);

                                String videoId = item.getJSONObject("id").getString("videoId");
                                String title = item.getJSONObject("snippet").getString("title");
                                String description = item.getJSONObject("snippet").getString("description");
                                String mediumUrl = item.getJSONObject("snippet").getJSONObject("thumbnails").getJSONObject("medium").getString("url");
                                String highUrl = item.getJSONObject("snippet").getJSONObject("thumbnails").getJSONObject("high").getString("url");

                                Video video = new Video(videoId, title, description, mediumUrl, highUrl);

                                videoList.add(video);

                            }

                        } catch (JSONException e) {
                            return;
                        }

                        adapter.notifyDataSetChanged();

                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        progressBar.setVisibility(View.GONE);
                    }
                }
        );

        progressBar.setVisibility(View.VISIBLE);
        queue.add(request);
    }
    // 웹 브라우저 실행시키는 인텐트
    public void openWebPage(String url) {
        Uri uri = Uri.parse(url);
        Intent intent = new Intent(Intent.ACTION_VIEW, uri); // 액션이 VIEW로 되어있고 인텐트타입이 uri
        startActivity(intent);
    }
}

videoAdapter

package com.leopard4.youtubeapiapp.adapter;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
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.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;

import com.bumptech.glide.Glide;
import com.leopard4.youtubeapiapp.MainActivity;
import com.leopard4.youtubeapiapp.PhotoActivity;
import com.leopard4.youtubeapiapp.R;
import com.leopard4.youtubeapiapp.model.Video;

import java.util.ArrayList;

public class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.ViewHolder>{
    Context context;
    ArrayList<Video> videoList;

    public VideoAdapter(Context context, ArrayList<Video> videoList) {
        this.context = context;
        this.videoList = videoList;
    }

    @NonNull
    @Override
    public VideoAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.video_row, parent, false);
        return new VideoAdapter.ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull VideoAdapter.ViewHolder holder, int position) {
        Video video = videoList.get(position);

        holder.txtTitle.setText(video.title);
        holder.txtDescription.setText(video.description);

        Glide.with(context).load(video.mediumUrl)
                .placeholder(R.drawable.ic_baseline_ondemand_video_24)
                .into(holder.imgThumb);

    }

    @Override
    public int getItemCount() {
        return videoList.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        CardView cardView;
        TextView txtTitle, txtDescription;
        ImageView imgThumb;

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

            cardView = itemView.findViewById(R.id.cardView);
            txtTitle = itemView.findViewById(R.id.txtTitle);
            txtDescription = itemView.findViewById(R.id.txtDescription);
            imgThumb = itemView.findViewById(R.id.imgThumb);

            imgThumb.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    int index = getAdapterPosition();

                    Intent intent = new Intent(context, PhotoActivity.class);
                    intent.putExtra("highUrl", videoList.get(index).highUrl);

                    context.startActivity(intent);
                }
            });
            cardView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {

                    int index = getAdapterPosition();
                    Video video = videoList.get(index);

                    // https://www.youtube.com/watch?v="videoId"
                    String url = "https://www.youtube.com/watch?v=" + video.videoId;

                    ((MainActivity) context).openWebPage(url);

                }
            });
        }

    }
}

PhotoActivity

package com.leopard4.youtubeapiapp;

import androidx.appcompat.app.AppCompatActivity;

import android.net.Uri;
import android.os.Bundle;
import android.widget.ImageView;

import com.bumptech.glide.Glide;

public class PhotoActivity extends AppCompatActivity {

    ImageView imgPhoto;

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

        imgPhoto = findViewById(R.id.imgPhoto);

        String url = getIntent().getStringExtra("highUrl");

        Glide.with(PhotoActivity.this)
                .load(url)
                .placeholder(R.drawable.ic_baseline_wallpaper_24)
                .into(imgPhoto);
    }
}