Reddit Android App Development | Lets Build that App

Reddit Android App Development with Source Code.

In this tutorial of Build that App. We will teach you how you can create your Reddit App in Android Studio using Java Programming Language.

However this app won’t be like the original Reddit App available in the play store. Rather it will have a swipe layout just like popular dating app Tinder. Which means you will be able to swipe your feeds in any direction.

For this we will be using yuyakaido library CardStackViewto achieve the desired layout.

Reddit Android App Development

Getting Started

Create a new Android Studio Project with Empty Activity. Go to build.gradle (app) and add following dependencies:

//TinderCards Library
    implementation "com.yuyakaido.android:card-stack-view:2.2.1"

    //Picasso
    implementation 'com.squareup.picasso:picasso:2.71828'

    //OKHTTP
    implementation 'com.squareup.okhttp3:okhttp:3.12.1'

    //Glide
    implementation 'com.github.bumptech.glide:glide:4.8.0'

    //GSON
    implementation 'com.google.code.gson:gson:2.8.2'

Making Layouts

Once the build Sync is finished, go to activity_main.xml in the res folder (See on the left side in the Project Panel). And add the following lines of code to it inside the ConstraintLayout Widget:

 <com.yuyakaido.android.cardstackview.CardStackView
    android:id="@+id/card_stack_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

We’ve now added the CardStackView, this is where the cards will be displayed. Now let’s make the layout for our cards.

Here is the rough draft of how our card will look like:

reddit android app development
reddit android app development

The finalized UI of the card layout looks like the following:

The XML code to be added in a new layout file named item_spot.xml to achieve such a layout as shown above is as follows:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    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="match_parent"
    android:background="?attr/selectableItemBackground"
    android:foreground="?attr/selectableItemBackground"
    app:cardUseCompatPadding="true"
    app:cardPreventCornerOverlap="false"
    app:cardCornerRadius="10dp"
    android:elevation="10dp"
    app:layout_constraintCircleRadius="5dp"
    app:cardBackgroundColor="@android:color/white">


    <ImageView
        android:src="@drawable/board"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"/>

    <ImageView
        android:id="@+id/item_thumb_image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="center"/>

    <ImageView
        android:id="@+id/item_chota_image"
        android:layout_marginTop="50dp"
        android:layout_marginBottom="120dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitCenter"
        android:adjustViewBounds="true"/>

    <com.google.android.exoplayer2.ui.PlayerView
        android:layout_marginBottom="50dp"
        android:visibility="gone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/video_player"/>

    <LinearLayout
        android:layout_margin="10dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">



            <TextView
                android:textColor="@color/white"
                android:shadowDy="2"
                android:shadowColor="#000"
                android:shadowRadius="10"
                android:id="@+id/item_subreddit_name"
                android:textSize="12sp"
                android:layout_weight="1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="r/subreddit_name"/>



    <LinearLayout
        android:layout_width="match_parent"
        android:orientation="vertical"
        android:layout_height="wrap_content"
        android:layout_weight="1">

        <TextView
            android:textColor="@color/white"
            android:shadowDy="2"
            android:shadowRadius="10"
            android:shadowColor="#000"
            android:textSize="10sp"
            android:id="@+id/item_pubDate"
            android:textAlignment="viewEnd"
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Author Name"/>


        <TextView
            android:id="@+id/item_auth_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:shadowColor="#000"
            android:shadowDy="2"
            android:shadowRadius="10"
            android:text="By Author Name"
            android:textAlignment="viewEnd"
            android:textColor="@color/white"
            android:textSize="12sp" />


    </LinearLayout>

    </LinearLayout>

    <LinearLayout
        android:layout_marginTop="50dp"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:weightSum="1"
        android:layout_gravity="bottom"
        android:padding="10dp"
        android:background="@drawable/layout_bg">

        <ScrollView
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">


                <TextView
                    android:text="Learn Text"
                    android:id="@+id/item_title"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textStyle="bold"
                    android:textColor="@android:color/white"
                    android:textSize="17sp"/>

                <TextView
                    android:text="Know Text"
                    android:id="@+id/item_subTitle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:autoLink="all"
                    android:clickable="true"
                    android:focusable="true"
                    android:textStyle="bold"
                    android:textColor="@android:color/white"
                    android:textSize="12sp"/>

            </LinearLayout>

        </ScrollView>


        <LinearLayout
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center">

            <android.support.design.widget.FloatingActionButton
                android:layout_margin="10dp"
                android:layout_weight="1"
                app:fabCustomSize="35dp"
                android:id="@+id/fab_comments"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:hapticFeedbackEnabled="true"
                android:src="@drawable/chat"
                app:backgroundTint="@android:color/white"
                app:fabSize="auto"
                app:rippleColor="#22bf00ff"/>


            <android.support.design.widget.FloatingActionButton
                android:layout_margin="10dp"
                android:layout_weight="1"
                app:fabCustomSize="35dp"
                android:id="@+id/fab_share"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:hapticFeedbackEnabled="true"
                android:src="@drawable/share"
                app:backgroundTint="@android:color/white"
                app:fabSize="auto"
                app:rippleColor="#22ff0004"/>

            <android.support.design.widget.FloatingActionButton
                android:layout_margin="10dp"
                android:layout_weight="1"
                app:fabCustomSize="35dp"
                android:id="@+id/fab_down"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:hapticFeedbackEnabled="true"
                android:src="@drawable/download"
                app:backgroundTint="@android:color/white"
                app:fabSize="auto"
                app:rippleColor="#2200ff97"/>

            <android.support.design.widget.FloatingActionButton
                android:layout_margin="10dp"
                android:layout_weight="1"
                android:id="@+id/fab_video"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:fabCustomSize="35dp"
                android:hapticFeedbackEnabled="true"
                android:src="@drawable/video"
                app:backgroundTint="@android:color/white"
                app:fabSize="auto"
                app:rippleColor="#2200ff97"/>

            <android.support.design.widget.FloatingActionButton
                android:layout_margin="10dp"
                android:layout_weight="1"
                android:id="@+id/fab_copy"
                android:layout_width="wrap_content"
                app:fabCustomSize="35dp"
                android:layout_height="wrap_content"
                android:hapticFeedbackEnabled="true"
                android:src="@drawable/copy"
                app:backgroundTint="@android:color/white"
                app:fabSize="auto"
                app:rippleColor="#2200ff97"/>

            <android.support.design.widget.FloatingActionButton
                android:layout_margin="10dp"
                android:layout_weight="1"
                android:id="@+id/fab_maximise"
                app:fabCustomSize="35dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:hapticFeedbackEnabled="true"
                android:src="@drawable/maximize"
                app:backgroundTint="@android:color/white"
                app:fabSize="auto"
                app:rippleColor="#2200ff97"/>

            <android.support.design.widget.FloatingActionButton
                android:layout_margin="10dp"
                android:layout_weight="1"
                android:id="@+id/fab_link"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:fabCustomSize="35dp"
                android:hapticFeedbackEnabled="true"
                android:src="@drawable/link"
                app:backgroundTint="@android:color/white"
                app:fabSize="auto"
                app:rippleColor="#2200ff97"/>

            <android.support.design.widget.FloatingActionButton
                android:layout_margin="10dp"
                android:layout_weight="1"
                android:id="@+id/fab_wallpaper"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:fabCustomSize="35dp"
                android:tint="@color/colorAccent"
                android:hapticFeedbackEnabled="true"
                android:src="@drawable/ic_wallpaper"
                app:backgroundTint="@android:color/white"
                app:fabSize="auto"
                app:rippleColor="#2200ff97"/>


        </LinearLayout>


    </LinearLayout>

   

</android.support.v7.widget.CardView>

Coding the Reddit Android App Development

Now go to MainActivity.java and Let’s first create an AsyncTask to get the data from Reddit.

Before calling an Asynctask, we much know from which URL we are going to fetch data. As per Reddit API we can easily fetch a public data, subject to a limit of maximum 100 feeds at a time. By simply adding /.json&after=after_tag&limit=100 as a suffix to any of its URL.

.json is used to get data in JSON format (you can get in XML)

after and before tag parameters are used in case of pagination. It is useful,if the user wants to view more than 100 feeds.

Limit: The number can be any upto 100. We’re using 50 in our example to make it easier for our app to handle data.

@SuppressLint("StaticFieldLeak")
    public class getFeed extends AsyncTask<String,Void,String> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            progressDialog = new ProgressDialog(MainActivity.this);
            progressDialog.setMessage("Getting Feed...");
            progressDialog.show();
        }


        @Override
        protected String doInBackground(String... strings) {
            OkHttpClient client = new OkHttpClient();
            if(strings.length != 0) {
                Request request = new Request.Builder()
                       // .url("https://www.reddit.com/" + strings[0] + ".json?raw_json=1&after=" + after + "&limit=50")
                        .url("https://www.reddit.com/r/earthporn/.json?raw_json=1&after=" + after + "&limit=50")
                        .build();
                try (Response response = client.newCall(request).execute()) {
                    assert response.body() != null;
                    return response.body().string();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                Request request = new Request.Builder()
                        // .url("https://www.reddit.com/" + strings[0] + ".json?raw_json=1&after=" + after + "&limit=50")
                        .url("https://www.reddit.com/r/earthporn/.json?raw_json=1&after=" + after + "&limit=50")
                        .build();
                try (Response response = client.newCall(request).execute()) {
                    assert response.body() != null;
                    return response.body().string();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }


        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            postArrayList.clear();
            try {
                if(s != null) {
                    JSONObject jsonObject = new JSONObject(s);
                    if(jsonObject.has("data")) {
                        JSONObject dataJSON = jsonObject.getJSONObject("data");
                        modhash = dataJSON.getString("modhash");
                        JSONArray childrenArray = dataJSON.getJSONArray("children");
                        dist = dataJSON.getLong("dist");
                        after = dataJSON.getString("after");
                        before = dataJSON.getString("before");

                        for (int i = 0; i < childrenArray.length(); i++) {
                            JSONObject item = childrenArray.getJSONObject(i);
                            JSONObject items = item.getJSONObject("data");
                            String subreddit = items.getString("subreddit");
                            String title = items.getString("title");
                            String selftext = items.getString("selftext");
                            String thumbnail = items.getString("thumbnail");
                            String author_flair_css_class = items.getString("author_flair_css_class");
                            String over_18 = items.getString("over_18");
                            String author = items.getString("author");
                            String url = items.getString("url");
                            String is_video = items.getString("is_video");
                            String permalink = "";
                            if (!items.getString("permalink").isEmpty()) {
                                permalink = items.getString("permalink");
                            }
                            Long ups = items.getLong("ups");
                            Long created = items.getLong("created");
                            Long num_comments = items.getLong("num_comments");
                            Long num_crossposts = items.getLong("num_crossposts");

                            String type = "hi";
                            String post_hint = "hi";
                            String is_gif = "false";

                            if (items.has("post_hint")) {
                                post_hint = items.getString("post_hint");
                            }


                            // NOT CrossPost
//                        if(!items.has("crosspost_parent_list")){
                            if (items.has("preview") && post_hint.equals("image")) {
                                JSONObject preview = items.getJSONObject("preview");
                                JSONArray images = preview.getJSONArray("images");
                                JSONObject zero = images.getJSONObject(0);
                                JSONObject source = zero.getJSONObject("source");
                                long width = source.getLong("width");
                                if (width > 1079) {
                                    type = "BCGR";
                                    JSONArray resolutions = zero.getJSONArray("resolutions");
                                    int size = resolutions.length() - 1;
                                    JSONObject thumbstar = resolutions.getJSONObject(size);
                                    thumbnail = thumbstar.getString("url");

                                } else {
                                    type = "MEME";
                                }
                            } else if (/*!items.has("preview") &&*/ url.contains("reddit.com") && is_video.equals("false")) {
                                type = "TEXT";
                            } else if (post_hint.equals("link") || post_hint.equals("rich:video") || post_hint.equals("hi") && !url.contains("reddit.com")) {
                                type = "LINK";
                                if (items.has("preview")) {
                                    JSONObject preview = items.getJSONObject("preview");
                                    JSONArray images = preview.getJSONArray("images");
                                    JSONObject zero = images.getJSONObject(0);
                                    JSONObject source = zero.getJSONObject("source");
                                    thumbnail = source.getString("url");
                                    if (preview.has("reddit_video_preview")) {
                                        JSONObject reddit_video_preview = preview.getJSONObject("reddit_video_preview");
                                        is_gif = reddit_video_preview.getString("is_gif");

                                        if (is_video.equals("false") && is_gif.equals("true")) {
                                            type = "VIDS";
                                            url = reddit_video_preview.getString("dash_url");
                                        }

                                    }

                                }

                            } else if (is_video.equals("true")) {
                                type = "VIDS";
                                if (items.has("media")) {
                                    JSONObject media = items.getJSONObject("media");
                                    JSONObject reddit_video = media.getJSONObject("reddit_video");
                                    url = reddit_video.getString("dash_url");
                                }
                            }

                            postArrayList.add(new Model_Data(subreddit, title, selftext, thumbnail, author_flair_css_class, post_hint, over_18, author, url, is_video, permalink, ups, created, num_comments, num_crossposts, type, is_gif));

                        }

                        if(cardStackView.getAdapter() == null){
                            adapter = new CardStackAdapter(postArrayList);
                            cardStackView.setAdapter(adapter);
                        }

                        adapter.notifyDataSetChanged();
                        cardStackView.setAdapter(adapter);
                        progressDialog.dismiss();



                    } else {
                        showToast("SubReddit Invalid");
                        progressDialog.dismiss();
                    }

                } else {

                    new AlertDialog.Builder(MainActivity.this)
                            .setTitle("Unable to Fetch Data")
                            .setMessage("Please Refresh or check your Internet Connection")

                            // Specifying a listener allows you to take an action before dismissing the dialog.
                            // The dialog is automatically dismissed when a dialog button is clicked.
                            .setPositiveButton("Refresh Data", (dialog, which) -> {
                                // Continue with delete operation
                                new getFeed().execute();
                            })

                            // A null listener allows the button to dismiss the dialog and take no further action.
                            .setNegativeButton("Exit App", (dialog, which) -> finish())
                            .setIcon(android.R.drawable.ic_dialog_alert)
                            .show();

                }

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


        }
    }

In onPostExecute() method of the Asynctask, you will notice that there are various variables we have used. They are important to know the type of feed and also to display data in card view.

Here is the code for the Adapter to show card:

 public class CardStackAdapter extends CardStackView.Adapter<RecyclerView.ViewHolder>{

        private List<Model_Data> postArrayList;

        CardStackAdapter(List<Model_Data> postArrayList) {
            this.postArrayList = postArrayList;
        }

        @NonNull
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {

            switch(i){
                case 10:
                    View view= LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.rec_ads,viewGroup,false);
                    return new AdViewHolder(view);
                default:
                    View cardview= LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_spot,viewGroup,false);
                    return new CardViewHolder(cardview);
            }

        }

        @Override
        public int getItemViewType(int position) {
            return position % 20;
        }

        @SuppressLint("RestrictedApi")
        @Override
        public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder viewHolder, int i) {

            switch (viewHolder.getItemViewType()){
                case 10:
                    AdViewHolder adViewHolder = (AdViewHolder) viewHolder;
                    loadNativeAd(adViewHolder.itemView.getContext());
                    adViewHolder.shareApp.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            // TODO: SHARE APP
                        }
                    });

                    break;

                default:
                    CardViewHolder cardViewHolder = (CardViewHolder) viewHolder;
                    Model_Data post = postArrayList.get(i);
                    String AuthorName = "by " + post.getAuthor();
                    cardViewHolder.authName.setText(AuthorName);
                    cardViewHolder.title.setText(post.getTitle());
                    cardViewHolder.subTitle.setText(post.getSelftext());
                    String timeAgo = GetTimeAgo.getTimeAgo(post.getCreated(),cardViewHolder.itemView.getContext());
                    cardViewHolder.pubDate.setText(timeAgo);
                    cardViewHolder.thumbImage.setImageDrawable(null);
                    cardViewHolder.playerView.setVisibility(View.GONE);
                    String getSub = "r/" + post.getSubreddit();
                    cardViewHolder.subredditName.setText(getSub);
//            cardViewHolder.thumbImage.setBackground(getResources().getDrawable(R.drawable.mona));

                    cardViewHolder.fMsg.setOnClickListener(v -> {
                        //TODO: MESSAGES / COMMENTS
                    });

//            cardViewHolder.itemView.setOnTouchListener(new View.OnTouchListener() {
//                @Override
//                public boolean onTouch(View v, MotionEvent event) {
//                   if(MotionEvent.ACTION_UP == event.getActionMasked()){
//                       showToast("Swiped Up");
//                       return true;
//                   }
//                    return false;
//                }
//            });

                    cardViewHolder.fDown.setVisibility(View.GONE);
                    cardViewHolder.fVideo.setVisibility(View.GONE);
                    cardViewHolder.fCopy.setVisibility(View.GONE);
                    cardViewHolder.fResize.setVisibility(View.GONE);
                    cardViewHolder.fWallpaper.setVisibility(View.GONE);
                    cardViewHolder.fLink.setVisibility(View.GONE);
                    cardViewHolder.thumbImage.setVisibility(View.INVISIBLE);
                    cardViewHolder.chotaImage.setVisibility(View.VISIBLE);

                    switch (post.getType()) {
                        case "BCGR":
                            cardViewHolder.fDown.setVisibility(View.VISIBLE);
                            cardViewHolder.fResize.setVisibility(View.VISIBLE);
                            cardViewHolder.fWallpaper.setVisibility(View.VISIBLE);
                            cardViewHolder.thumbImage.setScaleType(ImageView.ScaleType.CENTER_CROP);

                            //COMMENT SYSTEM
                            cardViewHolder.fMsg.setOnClickListener(v -> mBottomSheetDialog.show());
                            mBottomSheetDialog.setOnShowListener(dialog -> new CommentsShow().execute(post.getPermalink()));

                            Glide.with(getApplicationContext()).load(post.getThumbnail()).into(cardViewHolder.thumbImage);
                            Glide.with(getApplicationContext()).load(post.getThumbnail()).into(cardViewHolder.chotaImage);

                            cardViewHolder.fShare.setOnClickListener(v -> shareItem(post.getUrl(), post.getTitle(), post.getType()));

                            cardViewHolder.fWallpaper.setOnClickListener(v -> {

                                if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED &&
                                        ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                                    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 123);
                                    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 123);
                                    showToast("Need Permission to access storage for Downloading Image");
                                } else {

                                    new AlertDialog.Builder(MainActivity.this)
                                            .setTitle("Change Background Wallpaper?")
                                            .setMessage("Are you sure you want to change your wallpaper to currently selected Image?")

                                            // Specifying a listener allows you to take an action before dismissing the dialog.
                                            // The dialog is automatically dismissed when a dialog button is clicked.
                                            .setPositiveButton(android.R.string.yes, (dialog, which) -> {
                                                // Continue with delete operation
                                                new SetWallpaper().execute(post.getUrl());
                                            })

                                            // A null listener allows the button to dismiss the dialog and take no further action.
                                            .setNegativeButton(android.R.string.no, null)
                                            .setIcon(android.R.drawable.ic_dialog_alert)
                                            .show();

                                }
                            });

//                RESIZE SCALE
                            cardViewHolder.fResize.setOnClickListener(v -> {
                                if (cardViewHolder.chotaImage.getVisibility() == View.INVISIBLE) {
                                    cardViewHolder.chotaImage.setVisibility(View.VISIBLE);
                                    cardViewHolder.thumbImage.setVisibility(View.INVISIBLE);
                                } else {
                                    cardViewHolder.chotaImage.setVisibility(View.INVISIBLE);
                                    cardViewHolder.thumbImage.setVisibility(View.VISIBLE);
                                }
                            });

                            //DOWNLOAD IMAGE
                            cardViewHolder.fDown.setOnClickListener(v -> DownloadImage(post.getUrl()));


                            break;
                        case "MEME":

                            //COMMENT SYSTEM
                            mBottomSheetDialog.setOnShowListener(dialog -> new CommentsShow().execute(post.getPermalink()));
                            cardViewHolder.fMsg.setOnClickListener(v -> mBottomSheetDialog.show());

                            cardViewHolder.fDown.setVisibility(View.VISIBLE);
                            cardViewHolder.fResize.setVisibility(View.VISIBLE);
                            cardViewHolder.thumbImage.setScaleType(ImageView.ScaleType.FIT_START);
                            Glide.with(getApplicationContext()).load(post.getUrl()).into(cardViewHolder.thumbImage);
                            Glide.with(getApplicationContext()).load(post.getUrl()).into(cardViewHolder.chotaImage);

                            cardViewHolder.fShare.setOnClickListener(v -> shareItem(post.getUrl(), post.getTitle(), post.getType()));


                            //RESIZE SCALE
                            cardViewHolder.fResize.setOnClickListener(v -> {
                                if (cardViewHolder.chotaImage.getVisibility() == View.INVISIBLE) {
                                    cardViewHolder.chotaImage.setVisibility(View.VISIBLE);
                                    cardViewHolder.thumbImage.setVisibility(View.INVISIBLE);
                                } else {
                                    cardViewHolder.chotaImage.setVisibility(View.INVISIBLE);
                                    cardViewHolder.thumbImage.setVisibility(View.VISIBLE);
                                }
                            });

                            //DOWNLOAD IMAGE
                            cardViewHolder.fDown.setOnClickListener(v -> DownloadImage(post.getUrl()));
                            break;
                        case "VIDS":
                            cardViewHolder.fDown.setVisibility(View.VISIBLE);
                            cardViewHolder.fVideo.setVisibility(View.VISIBLE);

                            //COMMENT SYSTEM
                            mBottomSheetDialog.setOnShowListener(dialog -> new CommentsShow().execute(post.getPermalink()));
                            cardViewHolder.fMsg.setOnClickListener(v -> mBottomSheetDialog.show());

                            if (post.getPost_hint().equals("hosted:video") || post.getPost_hint().equals("link")) {
                                cardViewHolder.playerView.setVisibility(View.VISIBLE);

                                DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(cardViewHolder.itemView.getContext(),
                                        com.google.android.exoplayer2.util.Util.getUserAgent(cardViewHolder.itemView.getContext(), "ExoPlayer"));
                                Uri uri = Uri.parse(post.getUrl());
                                DashMediaSource dashMediaSource = new DashMediaSource(uri, dataSourceFactory,
                                        new DefaultDashChunkSource.Factory(dataSourceFactory), null, null);

                                BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
                                TrackSelector trackSelector = new DefaultTrackSelector(new AdaptiveTrackSelection.Factory(bandwidthMeter));

                                simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(cardViewHolder.itemView.getContext(), trackSelector);

                                // VIDEO PLAY
                                cardViewHolder.fVideo.setOnClickListener(v -> {
                                    simpleExoPlayer.prepare(dashMediaSource);
                                    simpleExoPlayer.setPlayWhenReady(true);
                                    simpleExoPlayer.setVolume(0);
                                    simpleExoPlayer.setRepeatMode(Player.REPEAT_MODE_ONE);
                                    cardViewHolder.playerView.setPlayer(simpleExoPlayer);
                                });


                                if (cardViewHolder.playerView.getPlayer() != null) {
                                    //TODO: ERROR
                                    if (cardViewHolder.playerView.getVisibility() == View.INVISIBLE) {
                                        cardViewHolder.playerView.getPlayer().setPlayWhenReady(false);
                                        cardViewHolder.playerView.getPlayer().seekTo(0);
                                        cardViewHolder.playerView.getPlayer().stop();
                                        swiped = false;
                                    }
                                }

                                cardViewHolder.fShare.setOnClickListener(v -> shareItem(post.getUrl(), post.getTitle(), post.getType()));

                                cardViewHolder.fDown.setOnClickListener(v -> {
                                    //DownloadImage(post.getUrl());
                                    //TODO: Download Video
                                    new ProgressBack().execute(post.getUrl());
                                });


                            } else if (post.getPost_hint().equals("rich:video")) {
//                    showToast("Rich Video");
                                //TODO:RIchVIDEO
                   /* Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(post.getUrl()));
                    startActivity(browserIntent);
                    Toast.makeText(cardViewHolder.itemView.getContext(),"Opening Video in Browser",Toast.LENGTH_SHORT).show();*/
                                cardViewHolder.fShare.setOnClickListener(v -> shareItem(post.getUrl(), post.getTitle(), post.getType()));


                                cardViewHolder.fDown.setOnClickListener(v -> {
                                    //DownloadImage(post.getUrl());
                                    //TODO: Download Video
                                    new ProgressBack().execute(post.getUrl());
                                });


                            }

                            break;
                        case "TEXT":
                            cardViewHolder.fCopy.setVisibility(View.VISIBLE);
                            cardViewHolder.fLink.setVisibility(View.VISIBLE);

                            //COMMENT SYSTEM
                            mBottomSheetDialog.setOnShowListener(dialog -> new CommentsShow().execute(post.getPermalink()));
                            cardViewHolder.fMsg.setOnClickListener(v -> mBottomSheetDialog.show());

                            //Copy
                            cardViewHolder.fCopy.setOnClickListener(v -> {
                                ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
                                String text = post.getTitle() + "\n\n" + post.getSelftext();
                                ClipData clip = ClipData.newPlainText("popcorn", text);
                                clipboard.setPrimaryClip(clip);
                                showToast("Story copied to Clipboard");
                            });

                            cardViewHolder.fLink.setOnClickListener(v -> {
                                Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(post.getUrl()));
                                startActivity(browserIntent);
                                Toast.makeText(cardViewHolder.itemView.getContext(), "Opening Story in Browser", Toast.LENGTH_SHORT).show();
                            });

                            cardViewHolder.fShare.setOnClickListener(v -> {
                                String shareBody = post.getTitle() + " Send using Popcorn for Reddit!";
                                Intent sharingIntent = new Intent(Intent.ACTION_SEND);
                                sharingIntent.setType("text/plain");
                                sharingIntent.putExtra(Intent.EXTRA_SUBJECT, "Popcorn for Reddit");
                                sharingIntent.putExtra(Intent.EXTRA_TEXT, shareBody);
                                startActivity(Intent.createChooser(sharingIntent, "Share Text Using..."));
                            });


                            break;
                        case "LINK":
                            cardViewHolder.fLink.setVisibility(View.VISIBLE);
                            cardViewHolder.fCopy.setVisibility(View.VISIBLE);
                            cardViewHolder.thumbImage.setScaleType(ImageView.ScaleType.FIT_START);
                            Glide.with(getApplicationContext()).load(post.getThumbnail()).into(cardViewHolder.thumbImage);

                            //COMMENT SYSTEM
                            mBottomSheetDialog.setOnShowListener(dialog -> new CommentsShow().execute(post.getPermalink()));
                            cardViewHolder.fMsg.setOnClickListener(v -> mBottomSheetDialog.show());

                            //Copy
                            cardViewHolder.fCopy.setOnClickListener(v -> {
                                ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
                                String text = post.getTitle() + " Read more here: " + post.getUrl() + "\n\n Send using Popcorn for Reddit";
                                ClipData clip = ClipData.newPlainText("popcorn", text);
                                clipboard.setPrimaryClip(clip);
                                Toast.makeText(cardViewHolder.itemView.getContext(), "Link copied to Clipboard", Toast.LENGTH_SHORT).show();
                            });

                            //OPEN LINK
                            cardViewHolder.fLink.setOnClickListener(v -> {
                                Intent intent = new Intent(Intent.ACTION_VIEW);
                                intent.setData(Uri.parse(post.getUrl()));
                                startActivity(intent);
                                showToast("Opening Link in Browser!");
                            });

                            //SHARE LINK
                            cardViewHolder.fShare.setOnClickListener(v -> {
                                String shareBody = post.getTitle() + " \n\n" + post.getUrl() + " \n\nSent using 'Popcorn for Reddit'";
                                Intent sharingIntent = new Intent(Intent.ACTION_SEND);
                                sharingIntent.setType("text/plain");
                                sharingIntent.putExtra(Intent.EXTRA_SUBJECT, post.getTitle());
                                sharingIntent.putExtra(Intent.EXTRA_TEXT, shareBody);
                                startActivity(Intent.createChooser(sharingIntent, "Share Link Using..."));
                            });

                            break;
                        case "ILNK":

                            //SHARE, COPY, DOWNLOAD

                            break;
                    }

                    //Customised

                    if(post.getSubreddit().equals("news")){
                        cardViewHolder.thumbImage.setBackground(getResources().getDrawable(R.drawable.newspaper));

                        //SHARE LINK
                        cardViewHolder.fShare.setOnClickListener(v -> {
                            String shareBody = post.getUrl();
                            Intent sharingIntent = new Intent(Intent.ACTION_SEND);
                            sharingIntent.setType("text/plain");
                            sharingIntent.putExtra(Intent.EXTRA_SUBJECT, post.getTitle());
                            sharingIntent.putExtra(Intent.EXTRA_TEXT, shareBody);
                            startActivity(Intent.createChooser(sharingIntent, "Share NEWS Using..."));
                        });

                        //COMMENT SYSTEM
                        mBottomSheetDialog.setOnShowListener(dialog -> new CommentsShow().execute(post.getPermalink()));
                        cardViewHolder.fMsg.setOnClickListener(v -> mBottomSheetDialog.show());

                    }



                    if(i == postArrayList.size()-1){
                        new getFeed().execute();
                    }

                    //cardViewHolder.fMsg.setVisibility(View.GONE);
//                    mBottomSheetDialog.setOnShowListener(dialog -> new CommentsShow().execute(post.getPermalink()));
//
//                    cardViewHolder.fMsg.setOnClickListener(v -> mBottomSheetDialog.show());

                    String myLinkText = cardViewHolder.subTitle.getText().toString();
                    Spannable spannable = new SpannableString( Html.fromHtml(myLinkText) );
                    Linkify.addLinks(spannable, Linkify.WEB_URLS);

                    cardViewHolder.subTitle.setMovementMethod(EnhancedLinkMovementMethod.getInstance());
                    cardViewHolder.subTitle.setText(spannable, TextView.BufferType.SPANNABLE);

                    URLSpan[] spans = spannable.getSpans(0, spannable.length(), URLSpan.class);
                    for (URLSpan urlSpan : spans) {
                        LinkSpan linkSpan = new LinkSpan(urlSpan.getURL());
                        int spanStart = spannable.getSpanStart(urlSpan);
                        int spanEnd = spannable.getSpanEnd(urlSpan);
                        spannable.setSpan(linkSpan, spanStart, spanEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        spannable.removeSpan(urlSpan);
                    }

                    cardViewHolder.subTitle.setOnClickListener(v -> showToast("Double click to open a link!"));
                    break;
            }


        }

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

        class CardViewHolder extends RecyclerView.ViewHolder {

            ImageView thumbImage, chotaImage;
            TextView authName, pubDate, title, subTitle, subredditName;
            PlayerView playerView;
            FloatingActionButton fMsg, fShare, fDown, fVideo, fCopy, fResize,fLink, fWallpaper;

            CardViewHolder(@NonNull View itemView) {
                super(itemView);
                chotaImage = itemView.findViewById(R.id.item_chota_image);
                thumbImage = itemView.findViewById(R.id.item_thumb_image);
                authName = itemView.findViewById(R.id.item_auth_name);
                pubDate = itemView.findViewById(R.id.item_pubDate);
                title = itemView.findViewById(R.id.item_title);
                subTitle = itemView.findViewById(R.id.item_subTitle);
                playerView = itemView.findViewById(R.id.video_player);
                subredditName = itemView.findViewById(R.id.item_subreddit_name);
                fMsg = itemView.findViewById(R.id.fab_comments);
                fShare = itemView.findViewById(R.id.fab_share);
                fDown = itemView.findViewById(R.id.fab_down);
                fVideo = itemView.findViewById(R.id.fab_video);
                fCopy = itemView.findViewById(R.id.fab_copy);
                fResize = itemView.findViewById(R.id.fab_maximise);
                fLink = itemView.findViewById(R.id.fab_link);
                fWallpaper = itemView.findViewById(R.id.fab_wallpaper);



            }
        }

     
    }

In the Adapter above we have also, as shown above, using an Ad layout if in case you want to show ads as well. Here are some extra line of codes for some functions used in the adapter above.

  private class LinkSpan extends URLSpan {
        private LinkSpan(String url) {
            super(url);
        }

        @Override
        public void onClick(View view) {
            String url = getURL();
            Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
            startActivity(browserIntent);
        }
    }

    void DownloadImage(String ImageUrl) {

        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 123);
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 123);
            showToast("Need Permission to access storage for Downloading Image");
        } else {
            showToast("Downloading Image...");
            new DownloadsImage().execute(ImageUrl);
        }
    }

    @SuppressLint("StaticFieldLeak")
    class CommentsShow extends AsyncTask<String,Void, String>{

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            modelComments.clear();
            showToast("Loading Comments");
            mCommentsProgress.setVisibility(View.VISIBLE);
        }


        @Override
        protected String doInBackground(String... strings) {
            OkHttpClient client = new OkHttpClient();

            Request request = new Request.Builder()
                    .url("https://www.reddit.com" + strings[0] + ".json")
                    .build();
            Response response;
            try {
                response = client.newCall(request).execute();
                assert response.body() != null;
                return response.body().string();
            } catch (IOException e) {
                e.printStackTrace();
                return "error";
            }

        }


        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            mCommentsProgress.setVisibility(View.GONE);

            try {
                JSONArray jsonArray = new JSONArray(s);
                JSONObject jsonObject = jsonArray.getJSONObject(1);
                JSONObject dataObject = jsonObject.getJSONObject("data");
                JSONArray childrenArray = dataObject.getJSONArray("children");

                for( int i = 0; i < childrenArray.length(); i++){
                    JSONObject childObject = childrenArray.getJSONObject(i);
                    JSONObject dataChildObject = childObject.getJSONObject("data");
                    String author, body;
                    long timestamp, ups, downs;
                    if(dataChildObject.optString("author").isEmpty()){
                        author = "none";
                    } else {
                        author = dataChildObject.getString("author");
                    }
                    if(dataChildObject.optString("body").isEmpty()){
                        body = "none";
                    } else {
                        body = dataChildObject.getString("body");
                    }

                    if(dataChildObject.optLong("created") == 0){
                        timestamp = System.currentTimeMillis();
                    } else {
                        timestamp = dataChildObject.optLong("created");
                    }
                    if(dataChildObject.optLong("ups") == 0){
                        ups = 0;
                    } else {
                        ups = dataChildObject.optLong("ups");
                    }
                    if(dataChildObject.optLong("downs") == 0){
                        downs = 0;
                    } else {
                        downs = dataChildObject.optLong("downs");
                    }

                   // timestamp = dataChildObject.getLong("created");
//                    ups = dataChildObject.getLong("ups");
//                    downs = dataChildObject.getLong("downs");
                    Model_Comment model_comment = new Model_Comment(author,body,timestamp,ups,downs);
                    modelComments.add(model_comment);
                    //TODO: HERE

                }

                commentsAdapter = new CommentsAdapter(sheetView.getContext(),modelComments);
                commentsRecycler.setAdapter(commentsAdapter);
                commentsAdapter.notifyDataSetChanged();

            } catch (JSONException e) {
                showToast(e.getMessage());
            }

        }
    }

    public class CommentsAdapter extends RecyclerView.Adapter<CommentsAdapter.CommentsViewHolder>{

        private Context context;
        private List<Model_Comment> mRecyclerViewItems;

        CommentsAdapter(Context context, List<Model_Comment> mRecyclerViewItems) {
            this.context = context;
            this.mRecyclerViewItems = mRecyclerViewItems;
        }

        @NonNull
        @Override
        public CommentsViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
            LayoutInflater inflater = LayoutInflater.from(context);
            View view = inflater.inflate(R.layout.rec_comments,viewGroup,false);
            return new CommentsViewHolder(view);
        }

        @Override
        public void onBindViewHolder(@NonNull CommentsViewHolder commentsViewHolder, int i) {

            Model_Comment comment = mRecyclerViewItems.get(i);
            commentsViewHolder.body.setText(comment.getBody());
            commentsViewHolder.author.setText(comment.getAuthor());
            String time = GetTimeAgo.getTimeAgo(comment.getCreated(),commentsViewHolder.itemView.getContext());
            commentsViewHolder.createdOn.setText(time);
            commentsViewHolder.ups.setText(String.valueOf(comment.getUps()));
            commentsViewHolder.downs.setText(String.valueOf(comment.getDowns()));

        }

        @Override
        public int getItemCount() {
            if(mRecyclerViewItems.size() < 1){
                noImage.setVisibility(View.VISIBLE);
            } else {
                noImage.setVisibility(View.GONE);
            }
            return mRecyclerViewItems.size();
        }

        class CommentsViewHolder extends RecyclerView.ViewHolder{
            TextView body, author, createdOn, ups, downs;
            CommentsViewHolder(@NonNull View itemView) {
                super(itemView);
                body = itemView.findViewById(R.id.item_comment);
                author = itemView.findViewById(R.id.item_author);
                createdOn = itemView.findViewById(R.id.item_timeago);
                ups = itemView.findViewById(R.id.item_up);
                downs = itemView.findViewById(R.id.item_down);
            }
        }
    }

    @SuppressLint("StaticFieldLeak")
    class SetWallpaper extends AsyncTask<String, Void, Void>{

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            showToast("Getting Image...");
            showToast("Large images may take sometime!");
        }

        @Override
        protected Void doInBackground(String... strings) {
            Bitmap result;
            try {
                result = Picasso.get()
                        .load(strings[0]).get();
                WallpaperManager wallpaperManager = WallpaperManager.getInstance(MainActivity.this);
                try {
                    wallpaperManager.setBitmap(result);
                } catch (IOException ex) {
                    showToast(ex.getMessage());
                }
            } catch (IOException e) {
                showToast(e.getMessage());
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            showToast("Wallpaper Set Successfully!");
        }
    }

    @SuppressLint("StaticFieldLeak")
    class DownloadsImage extends AsyncTask<String, Void,Void>{

        @Override
        protected Void doInBackground(String... strings) {
            URL url = null;
            try {
                url = new URL(strings[0]);
            } catch (MalformedURLException e) {
//                e.printStackTrace();
                showToast(e.getMessage());
            }
            Bitmap bm = null;
            try {
                bm = BitmapFactory.decodeStream(Objects.requireNonNull(url).openConnection().getInputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }

            //Create Path to save Image
            File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES+ "/Popcorn"); //Creates app specific folder

            if(!path.exists()) {
                path.mkdirs();
            }

            File imageFile = new File(path, String.valueOf(System.currentTimeMillis())+".png"); // Imagename.png
            FileOutputStream out = null;
            try {
                out = new FileOutputStream(imageFile);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            try{
                Objects.requireNonNull(bm).compress(Bitmap.CompressFormat.PNG, 100, out); // Compress Image
                assert out != null;
                out.flush();
                out.close();
                // Tell the media scanner about the new file so that it is
                // immediately available to the user.
                MediaScannerConnection.scanFile(MainActivity.this,new String[] { imageFile.getAbsolutePath() }, null, (path1, uri) -> {
                    // Log.i("ExternalStorage", "Scanned " + path + ":");
                    //    Log.i("ExternalStorage", "-> uri=" + uri);
                });
            } catch(Exception ignored) {
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            showToast("Image Saved!");
        }
    }

    public void shareItem(String url, String Title, String Type){


        if(!Type.equals("VIDS")) {
            showToast("Please Wait, we're getting Image to share...");
            final String shareBody = Title;
            //I'm using Popcorn for Reddit, Are you? Get App from here:
            Picasso.get().load(url).into(new Target() {
                @Override
                public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                    Intent i = new Intent(Intent.ACTION_SEND);
                    i.setType("image/*");
                    i.putExtra(Intent.EXTRA_TEXT, shareBody);
                    i.putExtra(Intent.EXTRA_STREAM, getLocalBitmapUri(bitmap));
                    i.setType("image/jpeg");
                    i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    startActivity(Intent.createChooser(i, "Share Image with..."));
                }

                @Override
                public void onBitmapFailed(Exception e, Drawable errorDrawable) {

                }

                @Override
                public void onPrepareLoad(Drawable placeHolderDrawable) {
                }
            });

        } else {
            showToast("Share Video Link");
            String shareBody = Title + " \n\n" + url + " \n\n" + "Send via Popcorn for Reddit";
            Intent i = new Intent(Intent.ACTION_SEND);
            i.setType("text/plain");
            i.putExtra(Intent.EXTRA_TEXT, shareBody);
            i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            startActivity(Intent.createChooser(i, "Share Image with..."));
        }

    }

    public Uri getLocalBitmapUri(Bitmap bmp) {
        Uri bmpUri = null;
        try {
            File file =  new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "share_image_" + System.currentTimeMillis() + ".png");
            FileOutputStream out = new FileOutputStream(file);
            bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
            out.close();
            bmpUri = Uri.fromFile(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bmpUri;
    }

    @SuppressLint("StaticFieldLeak")
    private class ProgressBack extends AsyncTask<String,String,String> {
        //ProgressDialog PD;
        @Override
        protected void onPreExecute() {
           showToast("Downloading Video...");
        }

        @Override
        protected String doInBackground(String... arg0) {
            downloadVideo(arg0[0],"video_" + String.valueOf(System.currentTimeMillis()) + ".mpd");
            return null;
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            showToast("Download Complete");
        }
    }

    private void downloadVideo(String fileURL, String fileName) {
        try {
            String rootDir = Environment.getExternalStorageDirectory()
                    + File.separator + "Video" + File.separator + "Popcorn";
            File rootFile = new File(rootDir);
            rootFile.mkdir();
            URL url = new URL(fileURL);
            HttpURLConnection c = (HttpURLConnection) url.openConnection();
            c.setRequestMethod("GET");
            c.setDoOutput(true);
            c.connect();
            FileOutputStream f = new FileOutputStream(new File(rootFile,
                    fileName));
            InputStream in = c.getInputStream();
            byte[] buffer = new byte[1024];
            int len1;
            while ((len1 = in.read(buffer)) > 0) {
                f.write(buffer, 0, len1);
            }
            f.close();
        } catch (IOException e) {
            //showToast(e.getMessage());
            Log.e("ERROR IN VIDEO",e.getMessage());
        }

        //showToast("Feature currently unavailable, Download using Browser!");

    }

To know more about Android App development Subscribe to our weekly newsletter below.

Learn more about creating fancy button in Android Studio here.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.