com.miz.mizuu.fragments.ShowEpisodeDetailsFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.miz.mizuu.fragments.ShowEpisodeDetailsFragment.java

Source

/*
 * Copyright (C) 2014 Michell Bak
 *
 * 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
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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 com.miz.mizuu.fragments;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Locale;

import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbFile;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v4.content.LocalBroadcastManager;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.miz.db.DbAdapter;
import com.miz.db.DbAdapterTvShow;
import com.miz.db.DbAdapterTvShowEpisode;
import com.miz.functions.MizLib;
import com.miz.mizuu.IdentifyTvShow;
import com.miz.mizuu.MizuuApplication;
import com.miz.mizuu.TvShowEpisode;
import com.miz.mizuu.R;
import com.miz.service.DeleteFile;
import com.miz.service.MakeAvailableOffline;
import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;
import com.test.smbstreamer.variant1.Streamer;

public class ShowEpisodeDetailsFragment extends Fragment {

    private DbAdapterTvShowEpisode dbHelper;
    private ImageView cover, playbutton;
    private TextView title, plot, airdate, rating, director, writer, gueststars, file;
    private String rowId;
    private TvShowEpisode thisEpisode = null;
    private boolean useWildcard, prefsDisableEthernetWiFiCheck, ignoreDeletedFiles;
    private Typeface tf;
    private long videoPlaybackStarted, videoPlaybackEnded;
    private Picasso mPicasso;

    public static ShowEpisodeDetailsFragment newInstance(String rowId) {
        ShowEpisodeDetailsFragment frag = new ShowEpisodeDetailsFragment();
        Bundle b = new Bundle();
        b.putString("rowId", rowId);
        frag.setArguments(b);
        return frag;
    }

    public ShowEpisodeDetailsFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setHasOptionsMenu(true);

        useWildcard = PreferenceManager.getDefaultSharedPreferences(getActivity()).getBoolean("prefsIgnoreFileType",
                false);
        prefsDisableEthernetWiFiCheck = PreferenceManager.getDefaultSharedPreferences(getActivity())
                .getBoolean("prefsDisableEthernetWiFiCheck", false);
        ignoreDeletedFiles = PreferenceManager.getDefaultSharedPreferences(getActivity())
                .getBoolean("prefsIgnoredFilesEnabled", false);

        tf = MizuuApplication.getOrCreateTypeface(getActivity(), "Roboto-Thin.ttf");

        rowId = getArguments().getString("rowId");

        if (!rowId.isEmpty()) {
            dbHelper = MizuuApplication.getTvEpisodeDbAdapter();
            Cursor cursor = dbHelper.getEpisode(rowId);
            while (cursor.moveToNext()) {
                thisEpisode = new TvShowEpisode(getActivity(),
                        cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisode.KEY_ROWID)),
                        cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisode.KEY_SHOW_ID)),
                        cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisode.KEY_FILEPATH)),
                        cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisode.KEY_EPISODE_TITLE)),
                        cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisode.KEY_EPISODE_PLOT)),
                        cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisode.KEY_SEASON)),
                        cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisode.KEY_EPISODE)),
                        cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisode.KEY_EPISODE_AIRDATE)),
                        cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisode.KEY_EPISODE_DIRECTOR)),
                        cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisode.KEY_EPISODE_WRITER)),
                        cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisode.KEY_EPISODE_GUESTSTARS)),
                        cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisode.KEY_EPISODE_RATING)),
                        cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisode.KEY_HAS_WATCHED)),
                        cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisode.KEY_EXTRA_1)));
            }
            cursor.close();
        }

        mPicasso = MizuuApplication.getPicasso(getActivity());
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        if (thisEpisode == null)
            return inflater.inflate(R.layout.empty_layout, null, false);
        return inflater.inflate(R.layout.episode_details, null, false);
    }

    public void onViewCreated(View v, Bundle savedInstanceState) {
        super.onViewCreated(v, savedInstanceState);

        if (thisEpisode != null) {
            cover = (ImageView) v.findViewById(R.id.traktIcon);
            playbutton = (ImageView) v.findViewById(R.id.imageView2);
            title = (TextView) v.findViewById(R.id.overviewMessage);
            plot = (TextView) v.findViewById(R.id.textView2);
            airdate = (TextView) v.findViewById(R.id.textView9);
            rating = (TextView) v.findViewById(R.id.textView11);
            director = (TextView) v.findViewById(R.id.textView7);
            writer = (TextView) v.findViewById(R.id.textView3);
            gueststars = (TextView) v.findViewById(R.id.TextView04);
            file = (TextView) v.findViewById(R.id.TextView07);

            // Set the episode details
            title.setText(thisEpisode.getTitle());
            title.setTypeface(tf);
            if (MizLib.isGoogleTV(getActivity()))
                title.setTextSize(28f);
            title.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

            if (!thisEpisode.getDescription().equals(getString(R.string.stringNA))
                    && !MizLib.isEmpty(thisEpisode.getDescription()))
                plot.setText(thisEpisode.getDescription());
            else
                plot.setText(getString(R.string.stringNoPlot));

            if (MizLib.isEmpty(thisEpisode.getReleasedate())
                    || thisEpisode.getReleasedate().equals(getString(R.string.stringNA))) {
                v.findViewById(R.id.tableRow1).setVisibility(View.GONE);
            } else {
                // Set the genre first aired date
                try {
                    String[] date = thisEpisode.getReleasedate().split("-");
                    Calendar cal = Calendar.getInstance();
                    cal.set(Integer.parseInt(date[0]), Integer.parseInt(date[1]) - 1, Integer.parseInt(date[2]));

                    airdate.setText(DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault())
                            .format(cal.getTime()));
                } catch (Exception e) { // Fall back if something goes wrong
                    airdate.setText(thisEpisode.getReleasedate());
                }
            }

            if (!thisEpisode.getRating().equals("0/10"))
                rating.setText(thisEpisode.getRating());
            else
                v.findViewById(R.id.tableRow2).setVisibility(View.GONE);

            if (MizLib.isEmpty(thisEpisode.getDirector())
                    || thisEpisode.getDirector().equals(getString(R.string.stringNA))) {
                v.findViewById(R.id.tableRow3).setVisibility(View.GONE);
            } else {
                director.setText(thisEpisode.getDirector());
            }

            if (MizLib.isEmpty(thisEpisode.getWriter())
                    || thisEpisode.getWriter().equals(getString(R.string.stringNA))) {
                v.findViewById(R.id.tableRow4).setVisibility(View.GONE);
            } else {
                writer.setText(thisEpisode.getWriter());
            }

            if (MizLib.isEmpty(thisEpisode.getGuestStars())
                    || thisEpisode.getGuestStars().equals(getString(R.string.stringNA))) {
                v.findViewById(R.id.tableRow5).setVisibility(View.GONE);
            } else {
                gueststars.setText(thisEpisode.getGuestStars());
            }

            file.setText(thisEpisode.getFilepath());

            playbutton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    play();
                }
            });

            mPicasso.load(thisEpisode.getEpisodePhoto()).skipMemoryCache().placeholder(R.drawable.bg).into(cover,
                    new Callback() {
                        @Override
                        public void onError() {
                            if (isAdded())
                                mPicasso.load(MizLib.getTvShowThumbFolder(getActivity()) + "/"
                                        + thisEpisode.getShowId() + ".jpg").skipMemoryCache()
                                        .placeholder(R.drawable.bg).error(R.drawable.nobackdrop).into(cover);
                        }

                        @Override
                        public void onSuccess() {
                        }
                    });
        }
    }

    private void play() {
        if (thisEpisode.hasOfflineCopy()) {
            playEpisode(thisEpisode.getOfflineCopyUri(), false);
        } else {
            playEpisode(thisEpisode.getFilepath(), thisEpisode.isNetworkFile());
        }
    }

    private void playEpisode(String filepath, boolean isNetworkFile) {
        videoPlaybackStarted = System.currentTimeMillis();
        if (isNetworkFile) {
            playNetworkFile();
        } else {
            try { // Attempt to launch intent based on the MIME type
                getActivity().startActivity(MizLib.getVideoIntent(filepath, useWildcard, thisEpisode));
                checkIn();
            } catch (Exception e) {
                try { // Attempt to launch intent based on wildcard MIME type
                    getActivity().startActivity(MizLib.getVideoIntent(filepath, "video/*", thisEpisode));
                    checkIn();
                } catch (Exception e2) {
                    Toast.makeText(getActivity(), getString(R.string.noVideoPlayerFound), Toast.LENGTH_LONG).show();
                }
            }
        }
    }

    public void onResume() {
        super.onResume();

        videoPlaybackEnded = System.currentTimeMillis();

        if (videoPlaybackStarted > 0 && videoPlaybackEnded - videoPlaybackStarted > (1000 * 60 * 5)) {
            if (!thisEpisode.hasWatched())
                watched(false); // Mark it as watched
        }
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        if (!(!MizLib.isPortrait(getActivity()) && MizLib.isTablet(getActivity())) && isVisible())
            inflater.inflate(R.menu.episode_details, menu);

        try {
            if (thisEpisode.hasWatched()) {
                menu.findItem(R.id.watched).setTitle(R.string.stringMarkAsUnwatched);
            } else {
                menu.findItem(R.id.watched).setTitle(R.string.stringMarkAsWatched);
            }

            if (thisEpisode.isNetworkFile()) {
                menu.findItem(R.id.watchOffline).setVisible(true);

                if (thisEpisode.hasOfflineCopy())
                    menu.findItem(R.id.watchOffline).setTitle(R.string.removeOfflineCopy);
                else
                    menu.findItem(R.id.watchOffline).setTitle(R.string.watchOffline);
            }
        } catch (Exception e) {
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.menuDeleteEpisode:
            deleteEpisode();
            break;
        case R.id.watched:
            watched(true);
            break;
        case R.id.identify:
            identifyEpisode();
            break;
        case R.id.watchOffline:
            watchOffline(item);
            break;
        }
        return false;
    }

    public void watchOffline(MenuItem m) {
        if (thisEpisode.hasOfflineCopy()) {
            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
            builder.setMessage(getString(R.string.areYouSure)).setTitle(getString(R.string.removeOfflineCopy))
                    .setCancelable(false)
                    .setPositiveButton(getString(android.R.string.yes), new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            boolean success = thisEpisode.getOfflineCopyFile().delete();
                            if (!success)
                                thisEpisode.getOfflineCopyFile().delete();
                            getActivity().invalidateOptionsMenu();
                            return;
                        }
                    }).setNegativeButton(getString(android.R.string.no), new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                        }
                    }).create().show();
        } else {
            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
            builder.setMessage(getString(R.string.downloadOfflineCopy)).setTitle(getString(R.string.watchOffline))
                    .setCancelable(false)
                    .setPositiveButton(getString(android.R.string.yes), new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            if (MizLib.isLocalCopyBeingDownloaded(getActivity()))
                                Toast.makeText(getActivity(), R.string.addedToDownloadQueue, Toast.LENGTH_SHORT)
                                        .show();

                            Intent i = new Intent(getActivity(), MakeAvailableOffline.class);
                            i.putExtra(MakeAvailableOffline.FILEPATH, thisEpisode.getFilepath());
                            i.putExtra(MakeAvailableOffline.TYPE, MizLib.TYPE_SHOWS);
                            i.putExtra("thumb", thisEpisode.getThumbnail());
                            i.putExtra("backdrop", thisEpisode.getEpisodePhoto());
                            getActivity().startService(i);
                            return;
                        }
                    }).setNegativeButton(getString(android.R.string.no), new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                        }
                    }).create().show();
        }
    }

    private void identifyEpisode() {
        Intent i = new Intent();
        i.setClass(getActivity(), IdentifyTvShow.class);
        i.putExtra("rowId", thisEpisode.getRowId());
        i.putExtra("files", new String[] { thisEpisode.getFullFilepath() });
        i.putExtra("isShow", false);
        startActivity(i);
    }

    private void deleteEpisode() {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

        View dialogLayout = getActivity().getLayoutInflater().inflate(R.layout.delete_file_dialog_layout, null);
        final CheckBox cb = (CheckBox) dialogLayout.findViewById(R.id.deleteFile);
        cb.setChecked(PreferenceManager.getDefaultSharedPreferences(getActivity())
                .getBoolean("prefsAlwaysDeleteFile", true));

        builder.setTitle(
                getString(R.string.removeEpisode) + " S" + thisEpisode.getSeason() + "E" + thisEpisode.getEpisode())
                .setView(dialogLayout).setCancelable(false)
                .setPositiveButton(getString(android.R.string.yes), new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        // Create and open database
                        dbHelper = MizuuApplication.getTvEpisodeDbAdapter();
                        boolean deleted = false;
                        if (ignoreDeletedFiles)
                            deleted = dbHelper.ignoreEpisode(thisEpisode.getRowId());
                        else
                            deleted = dbHelper.deleteEpisode(thisEpisode.getRowId());

                        if (deleted) {
                            try {
                                // Delete episode images
                                File episodePhoto = new File(MizLib.getTvShowEpisodeFolder(getActivity()),
                                        thisEpisode.getShowId() + "_S" + thisEpisode.getSeason() + "E"
                                                + thisEpisode.getEpisode() + ".jpg");
                                if (episodePhoto.exists()) {
                                    MizLib.deleteFile(episodePhoto);
                                }
                            } catch (NullPointerException e) {
                            } // No file to delete

                            if (dbHelper.getEpisodeCount(thisEpisode.getShowId()) == 0) { // No more episodes for this show
                                DbAdapterTvShow dbShow = MizuuApplication.getTvDbAdapter();
                                boolean deletedShow = dbShow.deleteShow(thisEpisode.getShowId());

                                if (deletedShow) {
                                    MizLib.deleteFile(new File(MizLib.getTvShowThumbFolder(getActivity()),
                                            thisEpisode.getShowId() + ".jpg"));
                                    MizLib.deleteFile(new File(MizLib.getTvShowBackdropFolder(getActivity()),
                                            thisEpisode.getShowId() + "_tvbg.jpg"));
                                }
                            }

                            if (cb.isChecked()) {
                                Intent deleteIntent = new Intent(getActivity(), DeleteFile.class);
                                deleteIntent.putExtra("filepath", thisEpisode.getFilepath());
                                getActivity().startService(deleteIntent);
                            }

                            notifyDatasetChanges();
                            getActivity().finish();
                            return;
                        } else {
                            Toast.makeText(getActivity(), getString(R.string.failedToRemoveEpisode),
                                    Toast.LENGTH_SHORT).show();
                        }
                    }
                }).setNegativeButton(getString(android.R.string.no), new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.cancel();
                    }
                }).show();
    }

    private void watched(boolean showToast) {
        // Create and open database
        dbHelper = MizuuApplication.getTvEpisodeDbAdapter();

        thisEpisode.setHasWatched(!thisEpisode.hasWatched()); // Reverse the hasWatched boolean

        if (dbHelper.updateSingleItem(Long.valueOf(thisEpisode.getRowId()), DbAdapter.KEY_HAS_WATCHED,
                thisEpisode.getHasWatched())) {
            getActivity().invalidateOptionsMenu();

            if (showToast)
                if (thisEpisode.hasWatched()) {
                    Toast.makeText(getActivity(), getString(R.string.markedAsWatched), Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(getActivity(), getString(R.string.markedAsUnwatched), Toast.LENGTH_SHORT).show();
                }

            LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(new Intent("tvshow-episode-changed"));

        } else {
            if (showToast)
                Toast.makeText(getActivity(), getString(R.string.errorOccured), Toast.LENGTH_SHORT).show();
        }

        new Thread() {
            @Override
            public void run() {
                ArrayList<TvShowEpisode> episode = new ArrayList<TvShowEpisode>();
                episode.add(thisEpisode);
                MizLib.markEpisodeAsWatched(episode, getActivity(), false);
            }
        }.start();
    }

    private void notifyDatasetChanges() {
        LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(new Intent("mizuu-shows-update"));
    }

    private void checkIn() {
        new Thread() {
            @Override
            public void run() {
                MizLib.checkInEpisodeTrakt(thisEpisode, getActivity());
            }
        }.start();
    }

    private void playNetworkFile() {
        if (!MizLib.isWifiConnected(getActivity(), prefsDisableEthernetWiFiCheck)) {
            Toast.makeText(getActivity(), getString(R.string.noConnection), Toast.LENGTH_LONG).show();
            return;
        }

        int bufferSize;
        String buff = PreferenceManager.getDefaultSharedPreferences(getActivity()).getString("prefsBufferSize",
                getString(R.string._16kb));
        if (buff.equals(getString(R.string._16kb)))
            bufferSize = 8192 * 2; // This appears to be the limit for most video players
        else
            bufferSize = 8192;

        final Streamer s = Streamer.getInstance();
        if (s != null)
            s.setBufferSize(bufferSize);
        else {
            Toast.makeText(getActivity(), getString(R.string.errorOccured), Toast.LENGTH_SHORT).show();
            return;
        }

        final NtlmPasswordAuthentication auth = MizLib.getAuthFromFilepath(MizLib.TYPE_SHOWS,
                thisEpisode.getFilepath());

        new Thread() {
            public void run() {
                try {
                    final SmbFile file = new SmbFile(MizLib.createSmbLoginString(
                            URLEncoder.encode(auth.getDomain(), "utf-8"),
                            URLEncoder.encode(auth.getUsername(), "utf-8"),
                            URLEncoder.encode(auth.getPassword(), "utf-8"), thisEpisode.getFilepath(), false));

                    s.setStreamSrc(file, MizLib.getSubtitleFiles(thisEpisode.getFilepath(), auth)); //the second argument can be a list of subtitle files
                    getActivity().runOnUiThread(new Runnable() {
                        public void run() {
                            try {
                                Uri uri = Uri.parse(Streamer.URL
                                        + Uri.fromFile(new File(Uri.parse(thisEpisode.getFilepath()).getPath()))
                                                .getEncodedPath());
                                startActivity(MizLib.getVideoIntent(uri, useWildcard, thisEpisode));
                                checkIn();
                            } catch (Exception e) {
                                try { // Attempt to launch intent based on wildcard MIME type
                                    Uri uri = Uri.parse(Streamer.URL
                                            + Uri.fromFile(new File(Uri.parse(thisEpisode.getFilepath()).getPath()))
                                                    .getEncodedPath());
                                    startActivity(MizLib.getVideoIntent(uri, "video/*", thisEpisode));
                                    checkIn();
                                } catch (Exception e2) {
                                    Toast.makeText(getActivity(), getString(R.string.noVideoPlayerFound),
                                            Toast.LENGTH_LONG).show();
                                }
                            }
                        }
                    });
                } catch (MalformedURLException e) {
                } catch (UnsupportedEncodingException e1) {
                }
            }
        }.start();
    }
}