de.tap.easy_xkcd.fragments.comics.ComicBrowserFragment.java Source code

Java tutorial

Introduction

Here is the source code for de.tap.easy_xkcd.fragments.comics.ComicBrowserFragment.java

Source

/**
 * *******************************************************************************
 * Copyright 2016 Tom Praschan
 * <p/>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ******************************************************************************
 */

package de.tap.easy_xkcd.fragments.comics;

import android.Manifest;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.graphics.Palette;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.GlideDrawableImageViewTarget;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.target.Target;
import com.kogitune.activity_transition.ActivityTransition;
import com.tap.xkcd_reader.R;

import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;

import de.tap.easy_xkcd.Activities.MainActivity;
import de.tap.easy_xkcd.database.DatabaseManager;
import de.tap.easy_xkcd.database.RealmComic;
import de.tap.easy_xkcd.utils.Comic;
import de.tap.easy_xkcd.utils.JsonParser;
import io.realm.RealmResults;
import uk.co.senab.photoview.PhotoView;

public class ComicBrowserFragment extends ComicFragment {

    private static boolean loadingImages;
    public static boolean newestUpdated = false;

    private ComicBrowserPagerAdapter adapter;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflateLayout(R.layout.pager_layout, inflater, container, savedInstanceState);

        loadingImages = true;

        if (savedInstanceState == null && !newestUpdated) {
            newestUpdated = true;
            new updateNewest(true).execute();
        } else {
            newestComicNumber = prefHelper.getNewest();
            new updateNewest(false).execute();
            scrollViewPager();
            adapter = new ComicBrowserPagerAdapter(getActivity(), newestComicNumber);
            pager.setAdapter(adapter);
        }

        pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {
                pageSelected(position);
                if (!prefHelper.isOnline(getActivity())) //Don't update if the device is not online
                    Toast.makeText(getActivity(), R.string.no_connection, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });

        return v;
    }

    @Override
    public void updatePager() {
        new updateNewest(false).execute();
    }

    private class updateNewest extends AsyncTask<Void, Void, Boolean> {
        private ProgressDialog progress;
        private boolean showProgress;
        private boolean updatePager;

        public updateNewest(boolean showProgress) {
            super();
            this.showProgress = showProgress;
        }

        @Override
        protected void onPreExecute() {
            if (showProgress) {
                progress = new ProgressDialog(getActivity());
                progress.setTitle(getResources().getString(R.string.loading_comics));
                progress.setCancelable(false);
                progress.show();
            }
        }

        @Override
        protected Boolean doInBackground(Void... params) {
            try {
                JSONObject json = JsonParser.getJSONFromUrl("http://xkcd.com/info.0.json");
                newestComicNumber = Integer.parseInt(json.getString("num"));
                if (lastComicNumber == 0)
                    lastComicNumber = newestComicNumber;
            } catch (Exception e) {
                e.printStackTrace();
            }
            boolean showSnackbar = newestComicNumber > prefHelper.getNewest()
                    && lastComicNumber != newestComicNumber && (prefHelper.getNotificationInterval() == 0);
            updatePager = showProgress || newestComicNumber > prefHelper.getNewest();

            prefHelper.setNewestComic(newestComicNumber);
            prefHelper.setLastComic(lastComicNumber);
            return showSnackbar;
        }

        @Override
        protected void onPostExecute(Boolean showSnackbar) {
            if (updatePager) {
                scrollViewPager();
                adapter = new ComicBrowserPagerAdapter(getActivity(), newestComicNumber);
                pager.setAdapter(adapter);
            }
            if (showSnackbar) {
                View.OnClickListener oc = new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        getLatestComic();
                    }
                };
                FloatingActionButton fab = (FloatingActionButton) getActivity().findViewById(R.id.fab);
                //noinspection ResourceType
                Snackbar.make(fab, getActivity().getResources().getString(R.string.new_comic), 4000)
                        .setAction(getActivity().getResources().getString(R.string.new_comic_view), oc).show();
            }
            if (showProgress)
                progress.dismiss();
        }
    }

    private class ComicBrowserPagerAdapter extends ComicAdapter {

        private RealmResults<RealmComic> comics;

        public ComicBrowserPagerAdapter(Context context, int count) {
            super(context, count);
        }

        @Override
        public int getCount() {
            return count;
        }

        @Override
        public Object instantiateItem(final ViewGroup container, final int position) {
            View itemView = setupPager(container, position);
            final PhotoView pvComic = (PhotoView) itemView.findViewById(R.id.ivComic);
            final TextView tvAlt = (TextView) itemView.findViewById(R.id.tvAlt);
            final TextView tvTitle = (TextView) itemView.findViewById(R.id.tvTitle);

            if (Arrays.binarySearch(mContext.getResources().getIntArray(R.array.large_comics), position + 1) >= 0)
                pvComic.setMaximumScale(15.0f);

            class loadComic extends AsyncTask<Void, Void, Void> {
                private Comic comic;
                private boolean largeComic;
                private boolean interactiveComic;
                private boolean loadedFromDatabase = false;

                private void displayComic(String url, String title) {
                    if (fromSearch && position == lastComicNumber - 1) {
                        fromSearch = false;
                        transition = ActivityTransition.with(getActivity().getIntent()).duration(300).to(pvComic)
                                .start(null);
                    }
                    if (getGifId(position) != 0) {
                        Glide.with(getActivity()).load(getGifId(position))
                                .listener(new RequestListener<Integer, GlideDrawable>() {
                                    @Override
                                    public boolean onException(Exception e, Integer model,
                                            Target<GlideDrawable> target, boolean isFirstResource) {
                                        return false;
                                    }

                                    @Override
                                    public boolean onResourceReady(GlideDrawable resource, Integer model,
                                            Target<GlideDrawable> target, boolean isFromMemoryCache,
                                            boolean isFirstResource) {
                                        if (position == lastComicNumber - 1) {
                                            if (((MainActivity) getActivity()).getProgressDialog() != null)
                                                ((MainActivity) getActivity()).getProgressDialog().dismiss();
                                            animateToolbar();
                                        }
                                        return false;
                                    }
                                }).into(new GlideDrawableImageViewTarget(pvComic));
                    } else
                        Glide.with(getActivity()).load(url).asBitmap().diskCacheStrategy(DiskCacheStrategy.SOURCE)
                                .into(new SimpleTarget<Bitmap>() {
                                    @Override
                                    public void onResourceReady(Bitmap resource,
                                            GlideAnimation<? super Bitmap> glideAnimation) {
                                        if (themePrefs.invertColors(false)
                                                && themePrefs.bitmapContainsColor(resource))
                                            pvComic.clearColorFilter();

                                        pvComic.setAlpha(0f);
                                        pvComic.setImageBitmap(resource);
                                        pvComic.animate().alpha(1f).setDuration(200);

                                        if (position == lastComicNumber - 1) {
                                            if (((MainActivity) getActivity()).getProgressDialog() != null)
                                                ((MainActivity) getActivity()).getProgressDialog().dismiss();
                                            animateToolbar();
                                        }
                                    }
                                });
                    tvTitle.setText(title);
                }

                @Override
                protected void onPreExecute() {
                    largeComic = PreferenceManager.getDefaultSharedPreferences(getActivity())
                            .getBoolean("pref_large", true)
                            && Arrays.binarySearch(getResources().getIntArray(R.array.large_comics),
                                    position + 1) >= 0;
                    interactiveComic = Arrays.binarySearch(getResources().getIntArray(R.array.interactive_comics),
                            position + 1) >= 0;
                    if (!largeComic && !interactiveComic && databaseManager.databaseLoaded()) {
                        if (comics == null)
                            comics = databaseManager.realm.where(RealmComic.class).findAll();
                        RealmComic realmComic = comics.where().equalTo("comicNumber", position + 1).findFirst();
                        loadedFromDatabase = realmComic != null;
                        if (loadedFromDatabase)
                            displayComic(realmComic.getUrl(), realmComic.getTitle());
                    }
                    if (largeComic)
                        animateToolbar();

                }

                @Override
                protected Void doInBackground(Void... dummy) {
                    comic = comicMap.get(position + 1);
                    if (comic == null) {
                        try {
                            comic = new Comic(position + 1, getActivity());
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        comicMap.put(position + 1, comic);
                    }
                    return null;
                }

                @Override
                protected void onPostExecute(Void dummy) {
                    if (comic != null && getActivity() != null) {
                        if (!loadedFromDatabase || largeComic || interactiveComic)
                            displayComic(comic.getComicData()[2], comic.getComicData()[0]);
                        tvAlt.setText(comic.getComicData()[1]);

                        if (position == lastComicNumber + 1
                                || (position == lastComicNumber - 1 && lastComicNumber == newestComicNumber)
                                || (position == lastComicNumber && lastComicNumber == newestComicNumber - 1)) {
                            loadingImages = false;
                        }
                    }
                }
            }
            new loadComic().execute();

            container.addView(itemView);
            return itemView;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((RelativeLayout) object);
            Glide.clear(((RelativeLayout) object).findViewById(R.id.ivComic));
        }

    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.action_favorite:
            return ModifyFavorites(item);
        case R.id.action_share:
            return shareComic();
        case R.id.action_latest:
            return getLatestComic();
        case R.id.action_random:
            return getRandomComic();
        case R.id.action_thread:
            return DatabaseManager.showThread(comicMap.get(lastComicNumber).getComicData()[0], getActivity(),
                    false);
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected boolean getLatestComic() {
        if (prefHelper.isOnline(getActivity())) {
            if (newestComicNumber - lastComicNumber > 4)
                ((MainActivity) getActivity())
                        .setProgressDialog(this.getResources().getString(R.string.loading_latest), false);
            return super.getLatestComic();
        }
        return true;
    }

    /*************************
     * Favorite Modification
     ************************/

    protected boolean ModifyFavorites(MenuItem item) {
        if (!prefHelper.isOnline(getActivity())) {
            Toast.makeText(getActivity(), R.string.no_connection, Toast.LENGTH_SHORT).show();
            return true;
        }
        if (databaseManager.checkFavorite(lastComicNumber)) {
            new DeleteComicImageTask().execute(true);
            item.setIcon(R.drawable.ic_favorite_outline);
        } else {
            if (!(ContextCompat.checkSelfPermission(getActivity(),
                    Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)) {
                ActivityCompat.requestPermissions(getActivity(),
                        new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, 2);
                return true;
            }
            new SaveComicImageTask().execute(true);
            item.setIcon(R.drawable.ic_action_favorite);
        }
        return true;
    }

    /*********************************
     * Random Comics
     ***********************************/

    @Override
    public boolean getRandomComic() {
        if (prefHelper.isOnline(getActivity()) && newestComicNumber != 0) {
            ((MainActivity) getActivity())
                    .setProgressDialog(getActivity().getResources().getString(R.string.loading_random), false);
            return super.getRandomComic();
        }
        Toast.makeText(getActivity(), R.string.no_connection, Toast.LENGTH_SHORT).show();
        return true;
    }

    @Override
    public void getPreviousRandom() {
        if (prefHelper.isOnline(getActivity()) && newestComicNumber != 0)
            super.getPreviousRandom();
        else
            Toast.makeText(getActivity(), R.string.no_connection, Toast.LENGTH_SHORT).show();
    }

    /*******************
     * Sharing
     **************************/

    protected boolean shareComic() {
        if (prefHelper.shareImage()) {
            shareComicImage();
            return true;
        }
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setItems(R.array.share_dialog, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                switch (which) {
                case 0:
                    shareComicImage();
                    break;
                case 1:
                    shareComicUrl(comicMap.get(lastComicNumber));
                    break;
                }
            }
        });
        AlertDialog alert = builder.create();
        alert.show();
        return true;
    }

    public void shareComicImage() {
        if (!(ContextCompat.checkSelfPermission(getActivity(),
                Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)) {
            ActivityCompat.requestPermissions(getActivity(),
                    new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, 1);
            return;
        }
        new ShareImageTask().execute(comicMap.get(lastComicNumber).getComicData()[2]);
    }

    private class ShareImageTask extends AsyncTask<String, Void, Bitmap> {
        @Override
        protected Bitmap doInBackground(String... params) {
            String url = params[0];
            try {
                return Glide.with(getActivity()).load(url).asBitmap().diskCacheStrategy(DiskCacheStrategy.SOURCE)
                        .into(-1, -1).get();
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }

        @SuppressWarnings("ResultOfMethodCallIgnored")
        @Override
        protected void onPostExecute(Bitmap result) {
            if (result == null) {
                return;
            }
            try {
                String cachePath = Environment.getExternalStorageDirectory() + "/easy xkcd";
                File dir = new File(cachePath);
                dir.mkdirs();
                File file = new File(dir, String.valueOf(lastComicNumber) + ".png");
                FileOutputStream stream = new FileOutputStream(file);
                result.compress(Bitmap.CompressFormat.PNG, 100, stream);
                stream.close();
                Uri uri = Uri.fromFile(file);
                ComicBrowserFragment.super.shareComicImage(uri, comicMap.get(lastComicNumber));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public boolean zoomReset() {
        return loadingImages || super.zoomReset();
    }
}