{"id":3702,"date":"2025-04-17T06:36:07","date_gmt":"2025-04-17T06:36:07","guid":{"rendered":"https:\/\/alsaeeddev.com\/?p=3702"},"modified":"2025-05-23T17:44:33","modified_gmt":"2025-05-23T17:44:33","slug":"news-api-integration-in-android-app-java","status":"publish","type":"post","link":"https:\/\/alsaeeddev.com\/shop\/news-api-integration-in-android-app-java\/","title":{"rendered":"News API Integration In Android App Java"},"content":{"rendered":"<p>In today\u2019s mobile-first world, delivering real-time content quickly and smoothly is crucial for user engagement. In this tutorial on <strong>News API Integration In Android App Java<\/strong>, you\u2019ll learn how to <strong>fetch and display news articles<\/strong> in an Android app using <strong>Retrofit<\/strong>, <strong>RecyclerView<\/strong>, and <strong>ProgressBar<\/strong>, while implementing an <strong>infinite scroll<\/strong> feature \u2014 all written in <strong>Java<\/strong>.<\/p>\n<p>By the end of this guide, you will have a working news app that fetches the latest articles based on a search query and loads more content as the user scrolls down.<\/p>\n<hr \/>\n<h3>\ud83d\ude80 Key Components We&#8217;ll Use<\/h3>\n<ul>\n<li><strong>RecyclerView<\/strong> \u2014 To display news articles in a scrollable list.<\/li>\n<li><strong>ProgressBar<\/strong> \u2014 To show loading status while fetching data.<\/li>\n<li><strong>Retrofit<\/strong> \u2014 For efficient and safe API calls.<\/li>\n<li><strong>Infinite Scrolling<\/strong> \u2014 Load more news automatically when the user reaches the end.<\/li>\n<li><strong>Handler<\/strong> \u2014 To simulate slight loading delays during pagination.<\/li>\n<\/ul>\n<hr \/>\n<h3>\ud83d\udd27 Step-by-Step Implementation<\/h3>\n<h4>1. Setting Up RecyclerView<\/h4>\n<p>First, we initialize our <code>RecyclerView<\/code> and set up a custom <code>NewsAdapter<\/code> to bind news articles dynamically.<\/p>\n<pre><code class=\"language-java\">\r\nprivate void setupRecyclerView() {\r\n    recyclerView.setLayoutManager(new LinearLayoutManager(this));\r\n    adapter = new NewsAdapter(this, listArticles, article -&gt; {\r\n        NewsDialogFragment dialogFragment = NewsDialogFragment.newInstance(article);\r\n        dialogFragment.show(getSupportFragmentManager(), \"NewsDialogFragment\");\r\n    });\r\n    recyclerView.setAdapter(adapter);\r\n}\r\n<\/code><\/pre>\n<p>Here, each news item is clickable and opens a <code>DialogFragment<\/code> to show article details.<\/p>\n<hr \/>\n<h4>2. Fetching News Using Retrofit<\/h4>\n<p>We use <strong>Retrofit<\/strong> to fetch news data asynchronously from an API. Here&#8217;s the main method:<\/p>\n<div style=\"padding: 10px; background-color: #fff3cd; border-left: 5px solid #ffeeba; margin-bottom: 20px;\"><strong>\ud83d\udd14 Note:<\/strong> Make sure to replace <code>API_KEY<\/code> with your actual News API key to successfully fetch the news data.<br \/>\nYou can get your API key from <a href=\"https:\/\/newsapi.org\/\" target=\"_blank\" rel=\"noopener\">NewsAPI.org<\/a>.<\/div>\n<pre><code class=\"language-java\">\r\nprivate void fetchNews(String query, int limit, int offset) {\r\n    NewsApiService apiService = ApiClient.getRetrofitInstance().create(NewsApiService.class);\r\n\r\n    Call&lt;ArticlesResponse&gt; call = apiService.getArticles(query, limit, offset, API_KEY);\r\n    call.enqueue(new Callback&lt;ArticlesResponse&gt;() {\r\n        @Override\r\n        public void onResponse(@NonNull Call&lt;ArticlesResponse&gt; call, @NonNull Response&lt;ArticlesResponse&gt; response) {\r\n            isLoading = false;\r\n            adapter.removeLoadingFooter();\r\n            if (response.isSuccessful() &amp;&amp; response.body() != null) {\r\n                List&lt;ArticlesResponse.Article&gt; newArticles = response.body().getArticles();\r\n                if (newArticles != null &amp;&amp; !newArticles.isEmpty()) {\r\n                    int oldSize = listArticles.size();\r\n                    listArticles.addAll(newArticles);\r\n                    adapter.notifyItemRangeInserted(oldSize, newArticles.size());\r\n                }\r\n            }\r\n            webProgress.setVisibility(View.GONE);\r\n        }\r\n\r\n        @Override\r\n        public void onFailure(@NonNull Call&lt;ArticlesResponse&gt; call, @NonNull Throwable t) {\r\n            webProgress.setVisibility(View.GONE);\r\n            Toast.makeText(MainActivity.this, \"Error: \" + t.getMessage(), Toast.LENGTH_SHORT).show();\r\n        }\r\n    });\r\n}\r\n<\/code><\/pre>\n<hr \/>\n<h4>3. Adding Infinite Scroll (Load More News)<\/h4>\n<p>To enable infinite scrolling, we attach a scroll listener to the <code>RecyclerView<\/code>. When the user scrolls near the bottom, we load more news automatically.<\/p>\n<pre><code class=\"language-java\">\r\nrecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {\r\n    @Override\r\n    public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {\r\n        super.onScrolled(recyclerView, dx, dy);\r\n\r\n        LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();\r\n        int totalItemCount = Objects.requireNonNull(layoutManager).getItemCount();\r\n        int lastVisibleItem = layoutManager.findLastVisibleItemPosition();\r\n\r\n        if (!isLoading &amp;&amp; lastVisibleItem == totalItemCount - 10) {\r\n            isLoading = true;\r\n            adapter.addLoadingFooter();\r\n\r\n            new Handler().postDelayed(() -&gt; {\r\n                currentOffset += PAGE_SIZE;\r\n                fetchNews(QUERY, PAGE_SIZE, currentOffset);\r\n            }, 1000); \/\/ simulate network delay\r\n        }\r\n    }\r\n});\r\n<\/code><\/pre>\n<p>\u2705 This ensures a seamless user experience without manual refresh!<\/p>\n<hr \/>\n<h3>\ud83d\udcf1 Full MainActivity Java Code<\/h3>\n<p>For your reference, here\u2019s the <strong>complete<\/strong> <code>MainActivity.java<\/code>:<\/p>\n<pre><code class=\"language-java\">\r\npublic class MainActivity extends AppCompatActivity {\r\n    private ProgressBar webProgress;\r\n    private RecyclerView recyclerView;\r\n    private NewsAdapter adapter;\r\n    private List listArticles = new ArrayList&lt;&gt;();\r\n    private boolean isLoading = false;\r\n    private int currentOffset = 0;\r\n    private final int PAGE_SIZE = 20;\r\n    private final String QUERY = \"bitcoin\"; \/\/ or anything you use\r\n\r\n    private static final String API_KEY = \"API_KEY\";\r\n\r\n    @Override\r\n    protected void onCreate(Bundle savedInstanceState) {\r\n        super.onCreate(savedInstanceState);\r\n        setContentView(R.layout.activity_main);\r\n        webProgress = findViewById(R.id.web_progress);\r\n        webProgress.setVisibility(VISIBLE);\r\n\r\n        recyclerView = findViewById(R.id.recycler_view);\r\n        setupRecyclerView();\r\n\r\n        fetchNews(QUERY, PAGE_SIZE, currentOffset);\r\n    }\r\n\r\n\r\n    private void fetchNews(String query, int limit, int offset) {\r\n        NewsApiService apiService = ApiClient.getRetrofitInstance().create(NewsApiService.class);\r\n\r\n        Call call = apiService.getArticles(query, limit, offset, API_KEY);\r\n        call.enqueue(new Callback() {\r\n            @Override\r\n            public void onResponse(@NonNull Call call, @NonNull Response response) {\r\n\r\n                isLoading = false;\r\n                adapter.removeLoadingFooter();\r\n\r\n                if (response.isSuccessful() &amp;&amp; response.body() != null) {\r\n                    List newArticles = response.body().getArticles();\r\n\r\n                    if (newArticles != null &amp;&amp; !newArticles.isEmpty()) {\r\n                        int oldSize = listArticles.size();\r\n                        listArticles.addAll(newArticles);\r\n\r\n                        adapter.notifyItemRangeInserted(oldSize, newArticles.size());\r\n                    }\r\n\r\n                    NewsLog.INSTANCE.d(\"onResponse\", \"News Loaded\");\r\n\r\n                }else {\r\n\r\n                    NewsLog.INSTANCE.d(\"onResponse\", \"Failed to load news\");\r\n\r\n                }\r\n\r\n                webProgress.setVisibility(View.GONE);\r\n\r\n            }\r\n\r\n            @Override\r\n            public void onFailure(@NonNull Call call, @NonNull Throwable t) {\r\n                webProgress.setVisibility(View.GONE);\r\n                Toast.makeText(MainActivity.this, \"Error: \" + t.getMessage(), Toast.LENGTH_SHORT).show();\r\n                NewsLog.INSTANCE.d(\"onFailure\", t.getMessage());\r\n            }\r\n        });\r\n    }\r\n\r\n\r\n    private void setupRecyclerView(){\r\n\r\n        recyclerView.setLayoutManager(new LinearLayoutManager(this));\r\n        adapter = new NewsAdapter(this, listArticles, article -&gt; {\r\n            \/\/ listen news click here, to open the news\r\n            NewsDialogFragment dialogFragment = NewsDialogFragment.newInstance(article);\r\n            dialogFragment.show(getSupportFragmentManager(), \"NewsDialogFragment\");\r\n\r\n        });\r\n        recyclerView.setAdapter(adapter);\r\n\r\n        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {\r\n            @Override\r\n            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {\r\n                super.onScrolled(recyclerView, dx, dy);\r\n\r\n                LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();\r\n                int totalItemCount = Objects.requireNonNull(layoutManager).getItemCount();\r\n                int lastVisibleItem = layoutManager.findLastVisibleItemPosition();\r\n\r\n                if (!isLoading &amp;&amp; lastVisibleItem == totalItemCount - 10) {\r\n                    isLoading = true;\r\n                    adapter.addLoadingFooter();\r\n\r\n                    new Handler().postDelayed(() -&gt; {\r\n                        currentOffset += PAGE_SIZE;\r\n                        fetchNews(QUERY, PAGE_SIZE, currentOffset);\r\n                    }, 1000); \/\/ simulate delay\r\n\r\n                }\r\n            }\r\n        });\r\n\r\n    }\r\n\r\n}\r\n<\/code><\/pre>\n<h3>\ud83d\udcf1 Full NewsAdapter Java Code<\/h3>\n<p>For your reference, here\u2019s the <strong>complete<\/strong> <code>NewsAdapter.java<\/code>:<\/p>\n<pre><code class=\"language-java\">\r\npublic class NewsAdapter extends RecyclerView.Adapter {\r\n\r\n    private static final int VIEW_TYPE_ITEM = 0;\r\n    private static final int VIEW_TYPE_LOADING = 1;\r\n    private List articles;\r\n    private Context context;\r\n    private boolean isLoadingAdded = false;\r\n    private onNewsClickListener listener;\r\n\r\n    public NewsAdapter(Context context, List articles, onNewsClickListener listener) {\r\n        this.context = context;\r\n        this.articles = articles;\r\n        this.listener = listener;\r\n    }\r\n\r\n    @Override\r\n    public int getItemViewType(int position) {\r\n        return (position == articles.size() &amp;&amp; isLoadingAdded) ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM;\r\n    }\r\n\r\n    @Override\r\n    public int getItemCount() {\r\n        return articles.size() + (isLoadingAdded ? 1 : 0);\r\n    }\r\n\r\n    @NonNull\r\n    @Override\r\n    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {\r\n        if (viewType == VIEW_TYPE_ITEM) {\r\n            View view = LayoutInflater.from(context).inflate(R.layout.item_article, parent, false);\r\n            return new ArticleViewHolder(view);\r\n        } else {\r\n            View view = LayoutInflater.from(context).inflate(R.layout.item_loading, parent, false);\r\n            return new LoadingViewHolder(view);\r\n        }\r\n    }\r\n\r\n    @Override\r\n    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {\r\n        if (getItemViewType(position) == VIEW_TYPE_ITEM) {\r\n            ArticleViewHolder viewHolder = (ArticleViewHolder) holder;\r\n            ArticlesResponse.Article article = articles.get(position);\r\n            viewHolder.title.setText(article.getTitle());\r\n            viewHolder.description.setText(article.getDescription());\r\n            \/\/ Add image loading if needed\r\n\r\n            Glide.with(context)\r\n                    .load(article.getFeedImage())  \/\/ Image URL or resource\r\n                    .apply(new RequestOptions().placeholder(R.drawable.place_holder)\r\n                          \/\/  .error(R.drawable.error_image)\r\n                    )\r\n                    .into(((ArticleViewHolder) holder).imageView);  \/\/ The ImageView where the image will be loaded\r\n\r\n            holder.itemView.setOnClickListener(v -&gt; {\r\n                int position1 = holder.getAdapterPosition();\r\n                if(listener != null &amp;&amp; position1 != RecyclerView.NO_POSITION){\r\n                    listener.onClick(article);\r\n                }\r\n            });\r\n\r\n        }\r\n    }\r\n\r\n    public void addLoadingFooter() {\r\n        isLoadingAdded = true;\r\n        notifyItemInserted(articles.size());\r\n    }\r\n\r\n    public void removeLoadingFooter() {\r\n        if (isLoadingAdded) {\r\n            isLoadingAdded = false;\r\n            notifyItemRemoved(articles.size());\r\n        }\r\n    }\r\n\r\n    static class ArticleViewHolder extends RecyclerView.ViewHolder {\r\n        TextView title, description;\r\n        ImageView imageView;\r\n\r\n        public ArticleViewHolder(View itemView) {\r\n            super(itemView);\r\n            title = itemView.findViewById(R.id.article_title);\r\n            description = itemView.findViewById(R.id.article_description);\r\n            imageView = itemView.findViewById(R.id.iv_news);\r\n        }\r\n    }\r\n\r\n    static class LoadingViewHolder extends RecyclerView.ViewHolder {\r\n        public LoadingViewHolder(View itemView) {\r\n            super(itemView);\r\n        }\r\n    }\r\n}\r\n\r\n<\/code><\/pre>\n<hr \/>\n<p><iframe loading=\"lazy\" title=\"News API Integration App in Android Using Retrofit &amp; RecyclerView | Free Source Code #shorts #api\" width=\"640\" height=\"360\" src=\"https:\/\/www.youtube.com\/embed\/irak7RCxeIw?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/p>\n<hr \/>\n<p><a href=\"https:\/\/github.com\/alsaeeddev\/NewsApiIntegration\/archive\/refs\/heads\/main.zip\">Download Source Code<\/a><\/p>\n<h3>\ud83c\udfaf Final Thoughts<\/h3>\n<p>By combining <strong>Retrofit<\/strong>, <strong>RecyclerView<\/strong>, and <strong>ProgressBar<\/strong>, we\u2019ve built a highly efficient, real-time news app that supports <strong>infinite scrolling<\/strong> in Android using <strong>Java<\/strong>.<\/p>\n<p>This pattern is extremely useful for creating <strong>news apps<\/strong>, <strong>social media feeds<\/strong>, <strong>blogs<\/strong>, and any app that requires real-time content loading.<\/p>\n<p><strong>Pro Tip:<\/strong> Always handle error cases smartly (like no internet, API limit errors) to enhance user experience even further.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In today\u2019s mobile-first world, delivering real-time content quickly and smoothly is crucial for user engagement. In this tutorial on News API Integration In Android App Java, you\u2019ll learn how to fetch and display news articles in an Android app using Retrofit, RecyclerView, and ProgressBar, while implementing an infinite scroll feature \u2014 all written in Java. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3705,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,117,164],"tags":[73,69,72,70,67,68,66,71],"class_list":["post-3702","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-android","category-java","category-source-codes","tag-android-app-development-tutorial","tag-android-java-news-app-example","tag-android-recyclerview-load-more-example","tag-display-news-articles-android","tag-fetching-news-in-android-with-retrofit","tag-infinite-scroll-in-recyclerview-android","tag-news-api-integration-in-android-app-java","tag-retrofit-api-call-android-java"],"_links":{"self":[{"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/posts\/3702","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/comments?post=3702"}],"version-history":[{"count":12,"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/posts\/3702\/revisions"}],"predecessor-version":[{"id":4039,"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/posts\/3702\/revisions\/4039"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/media\/3705"}],"wp:attachment":[{"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/media?parent=3702"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/categories?post=3702"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alsaeeddev.com\/shop\/wp-json\/wp\/v2\/tags?post=3702"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}