com.amaze.carbonfilemanager.fragments.ProcessViewer.java Source code

Java tutorial

Introduction

Here is the source code for com.amaze.carbonfilemanager.fragments.ProcessViewer.java

Source

/*
 * Copyright (C) 2014 Arpit Khurana <arpitkh96@gmail.com>, Vishal Nehra <vishalmeham2@gmail.com>
 *
 * This file is part of Amaze File Manager.
 *
 * Amaze File Manager is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.amaze.carbonfilemanager.fragments;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v7.widget.CardView;
import android.text.Html;
import android.text.Spanned;
import android.text.format.Formatter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.amaze.carbonfilemanager.R;
import com.amaze.carbonfilemanager.activities.MainActivity;
import com.amaze.carbonfilemanager.services.CopyService;
import com.amaze.carbonfilemanager.services.EncryptService;
import com.amaze.carbonfilemanager.services.ExtractService;
import com.amaze.carbonfilemanager.services.ZipTask;
import com.amaze.carbonfilemanager.ui.icons.IconUtils;
import com.amaze.carbonfilemanager.utils.DataPackage;
import com.amaze.carbonfilemanager.utils.files.Futils;
import com.amaze.carbonfilemanager.utils.Utils;
import com.amaze.carbonfilemanager.utils.color.ColorUsage;
import com.amaze.carbonfilemanager.utils.theme.AppTheme;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

public class ProcessViewer extends Fragment {

    boolean isInitialized = false;
    SharedPreferences sharedPrefs;
    IconUtils icons;
    MainActivity mainActivity;
    int accentColor, primaryColor;
    ImageButton mCancelButton;
    ImageView mProgressImage;

    private View rootView;
    private CardView mCardView;
    private LineChart mLineChart;
    private LineData mLineData = new LineData();
    private long time = 0L;
    private TextView mProgressTypeText, mProgressFileNameText, mProgressBytesText, mProgressFileText,
            mProgressSpeedText, mProgressTimer;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.processparent, container, false);
        setRetainInstance(false);

        mainActivity = (MainActivity) getActivity();

        accentColor = mainActivity.getColorPreference().getColor(ColorUsage.ACCENT);
        primaryColor = mainActivity.getColorPreference().getColor(ColorUsage.getPrimary(MainActivity.currentTab));
        if (mainActivity.getAppTheme().equals(AppTheme.DARK))
            rootView.setBackgroundResource((R.color.cardView_background));
        mainActivity.updateViews(new ColorDrawable(primaryColor));
        mainActivity.setActionBarTitle(getResources().getString(R.string.process_viewer));
        mainActivity.floatingActionButton.hideMenuButton(true);
        sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
        icons = new IconUtils(sharedPrefs, getActivity());
        mainActivity.supportInvalidateOptionsMenu();

        mCardView = (CardView) rootView.findViewById(R.id.card_view);

        mLineChart = (LineChart) rootView.findViewById(R.id.progress_chart);
        mProgressImage = (ImageView) rootView.findViewById(R.id.progress_image);
        mCancelButton = (ImageButton) rootView.findViewById(R.id.delete_button);
        mProgressTypeText = (TextView) rootView.findViewById(R.id.text_view_progress_type);
        mProgressFileNameText = (TextView) rootView.findViewById(R.id.text_view_progress_file_name);
        mProgressBytesText = (TextView) rootView.findViewById(R.id.text_view_progress_bytes);
        mProgressFileText = (TextView) rootView.findViewById(R.id.text_view_progress_file);
        mProgressSpeedText = (TextView) rootView.findViewById(R.id.text_view_progress_speed);
        mProgressTimer = (TextView) rootView.findViewById(R.id.text_view_progress_timer);

        if (mainActivity.getAppTheme().equals(AppTheme.DARK)) {

            mCancelButton.setImageResource(R.drawable.ic_action_cancel);
            mCardView.setCardBackgroundColor(Utils.getColor(getContext(), R.color.cardView_foreground));
            mCardView.setCardElevation(0f);
        }

        return rootView;
    }

    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            // We've bound to LocalService, cast the IBinder and get LocalService instance

            CopyService.LocalBinder localBinder = (CopyService.LocalBinder) service;
            CopyService copyService = localBinder.getService();

            for (int i = 0; i < copyService.getDataPackageSize(); i++) {

                processResults(copyService.getDataPackage(i), ServiceType.COPY);
            }

            // animate the chart a little after initial values have been applied
            mLineChart.animateXY(500, 500);

            copyService.setProgressListener(new CopyService.ProgressListener() {
                @Override
                public void onUpdate(final DataPackage dataPackage) {
                    if (getActivity() == null || getActivity().getSupportFragmentManager()
                            .findFragmentByTag(MainActivity.KEY_INTENT_PROCESS_VIEWER) == null) {
                        // callback called when we're not inside the app
                        return;
                    }
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {

                            processResults(dataPackage, ServiceType.COPY);
                        }
                    });
                }

                @Override
                public void refresh() {

                }
            });
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
        }
    };

    private ServiceConnection mExtractConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            // We've bound to LocalService, cast the IBinder and get LocalService instance
            ExtractService.LocalBinder localBinder = (ExtractService.LocalBinder) service;
            ExtractService extractService = localBinder.getService();

            for (int i = 0; i < extractService.getDataPackageSize(); i++) {

                processResults(extractService.getDataPackage(i), ServiceType.EXTRACT);
            }

            // animate the chart a little after initial values have been applied
            mLineChart.animateXY(500, 500);

            extractService.setProgressListener(new ExtractService.ProgressListener() {
                @Override
                public void onUpdate(final DataPackage dataPackage) {
                    if (getActivity() == null) {
                        // callback called when we're not inside the app
                        return;
                    }
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {

                            processResults(dataPackage, ServiceType.EXTRACT);
                        }
                    });
                }

                @Override
                public void refresh() {

                }
            });
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
        }
    };

    private ServiceConnection mCompressConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            // We've bound to LocalService, cast the IBinder and get LocalService instance
            ZipTask.LocalBinder localBinder = (ZipTask.LocalBinder) service;
            ZipTask zipTask = localBinder.getService();

            for (int i = 0; i < zipTask.getDataPackageSize(); i++) {

                processResults(zipTask.getDataPackage(i), ServiceType.COMPRESS);
            }

            // animate the chart a little after initial values have been applied
            mLineChart.animateXY(500, 500);

            zipTask.setProgressListener(new ZipTask.ProgressListener() {
                @Override
                public void onUpdate(final DataPackage dataPackage) {
                    if (getActivity() == null) {
                        // callback called when we're not inside the app
                        return;
                    }
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            processResults(dataPackage, ServiceType.COMPRESS);
                        }
                    });
                }

                @Override
                public void refresh() {

                }
            });
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {

        }
    };

    private ServiceConnection mCryptConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            EncryptService.LocalBinder binder = (EncryptService.LocalBinder) service;
            EncryptService encryptService = binder.getService();

            for (int i = 0; i < encryptService.getDataPackageSize(); i++) {
                DataPackage dataPackage = encryptService.getDataPackage(i);
                processResults(dataPackage, dataPackage.isMove() ? ServiceType.DECRYPT : ServiceType.ENCRYPT);
            }

            // animate the chart a little after initial values have been applied
            mLineChart.animateXY(500, 500);

            encryptService.setProgressListener(new EncryptService.ProgressListener() {
                @Override
                public void onUpdate(final DataPackage dataPackage) {
                    if (getActivity() == null) {
                        // callback called when we're not inside the app
                        return;
                    }
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {

                            processResults(dataPackage,
                                    dataPackage.isMove() ? ServiceType.DECRYPT : ServiceType.ENCRYPT);
                        }
                    });
                }

                @Override
                public void refresh() {

                }
            });
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

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

        Intent intent = new Intent(getActivity(), CopyService.class);
        getActivity().bindService(intent, mConnection, 0);

        Intent intent1 = new Intent(getActivity(), ExtractService.class);
        getActivity().bindService(intent1, mExtractConnection, 0);

        Intent intent2 = new Intent(getActivity(), ZipTask.class);
        getActivity().bindService(intent2, mCompressConnection, 0);

        Intent intent3 = new Intent(getActivity(), EncryptService.class);
        getActivity().bindService(intent3, mCryptConnection, 0);
    }

    @Override
    public void onPause() {
        super.onPause();
        getActivity().unbindService(mConnection);
        getActivity().unbindService(mExtractConnection);
        getActivity().unbindService(mCompressConnection);
        getActivity().unbindService(mCryptConnection);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    /**
     * Enum helps defining the result type for {@link #processResults(DataPackage, ServiceType)}
     * to process
     */
    enum ServiceType {

        COPY, EXTRACT, COMPRESS, ENCRYPT, DECRYPT
    }

    public void processResults(final DataPackage dataPackage, ServiceType serviceType) {
        if (dataPackage != null) {
            String name = dataPackage.getName();
            long total = dataPackage.getTotal();
            long doneBytes = dataPackage.getByteProgress();
            boolean move = dataPackage.isMove();

            if (!isInitialized) {

                // initializing views for the first time
                chartInit(total);

                // setting progress image
                setupDrawables(serviceType, move);
                isInitialized = true;
            }

            addEntry(Futils.readableFileSizeFloat(doneBytes),
                    Futils.readableFileSizeFloat(dataPackage.getSpeedRaw()));

            mProgressFileNameText.setText(name);

            Spanned bytesText = Html.fromHtml(getResources().getString(R.string.written) + " <font color='"
                    + accentColor + "'><i>" + Formatter.formatFileSize(getContext(), doneBytes) + " </font></i>"
                    + getResources().getString(R.string.out_of) + " <i>"
                    + Formatter.formatFileSize(getContext(), total) + "</i>");
            mProgressBytesText.setText(bytesText);

            Spanned fileProcessedSpan = Html.fromHtml(getResources().getString(R.string.processing_file)
                    + " <font color='" + accentColor + "'><i>" + (dataPackage.getSourceProgress()) + " </font></i>"
                    + getResources().getString(R.string.of) + " <i>" + dataPackage.getSourceFiles() + "</i>");
            mProgressFileText.setText(fileProcessedSpan);

            Spanned speedSpan = Html.fromHtml(
                    getResources().getString(R.string.current_speed) + ": <font color='" + accentColor + "'><i>"
                            + Formatter.formatFileSize(getContext(), dataPackage.getSpeedRaw()) + "/s</font></i>");
            mProgressSpeedText.setText(speedSpan);

            Spanned timerSpan = Html.fromHtml(getResources().getString(R.string.service_timer) + ": <font color='"
                    + accentColor + "'><i>" + formatTimer(++time) + "</font></i>");

            mProgressTimer.setText(timerSpan);
        }
    }

    /**
     * Formats input to plain mm:ss format
     * @param timer
     * @return
     */
    private String formatTimer(long timer) {
        final long min = TimeUnit.SECONDS.toMinutes(timer);
        final long sec = TimeUnit.SECONDS.toSeconds(timer - TimeUnit.MINUTES.toMillis(min));
        return String.format("%02d:%02d", min, sec);
    }

    /**
     * Setup drawables and click listeners based on the {@link ServiceType}
     * @param serviceType
     */
    private void setupDrawables(ServiceType serviceType, boolean isMove) {
        switch (serviceType) {
        case COPY:
            if (mainActivity.getAppTheme().equals(AppTheme.DARK)) {

                mProgressImage.setImageDrawable(getResources().getDrawable(R.drawable.ic_content_copy_white_36dp));
            } else {
                mProgressImage
                        .setImageDrawable(getResources().getDrawable(R.drawable.ic_content_copy_grey600_36dp));
            }
            mProgressTypeText.setText(isMove ? getResources().getString(R.string.moving)
                    : getResources().getString(R.string.copying));
            cancelBroadcast(new Intent(CopyService.TAG_BROADCAST_COPY_CANCEL));
            break;
        case EXTRACT:
            if (mainActivity.getAppTheme().equals(AppTheme.DARK)) {

                mProgressImage.setImageDrawable(getResources().getDrawable(R.drawable.ic_zip_box_white_36dp));
            } else {
                mProgressImage.setImageDrawable(getResources().getDrawable(R.drawable.ic_zip_box_grey600_36dp));
            }
            mProgressTypeText.setText(getResources().getString(R.string.extracting));
            cancelBroadcast(new Intent(ExtractService.TAG_BROADCAST_EXTRACT_CANCEL));
            break;
        case COMPRESS:
            if (mainActivity.getAppTheme().equals(AppTheme.DARK)) {

                mProgressImage.setImageDrawable(getResources().getDrawable(R.drawable.ic_zip_box_white_36dp));
            } else {
                mProgressImage.setImageDrawable(getResources().getDrawable(R.drawable.ic_zip_box_grey600_36dp));
            }
            mProgressTypeText.setText(getResources().getString(R.string.compressing));
            cancelBroadcast(new Intent(ZipTask.KEY_COMPRESS_BROADCAST_CANCEL));
            break;
        case ENCRYPT:
            if (mainActivity.getAppTheme().equals(AppTheme.DARK)) {

                mProgressImage.setImageDrawable(getResources().getDrawable(R.drawable.ic_folder_lock_white_36dp));
            } else {
                mProgressImage.setImageDrawable(getResources().getDrawable(R.drawable.ic_folder_lock_grey600_36dp));
            }
            mProgressTypeText.setText(getResources().getString(R.string.crypt_encrypting));
            cancelBroadcast(new Intent(EncryptService.TAG_BROADCAST_CRYPT_CANCEL));
            break;
        case DECRYPT:
            if (mainActivity.getAppTheme().equals(AppTheme.DARK)) {

                mProgressImage
                        .setImageDrawable(getResources().getDrawable(R.drawable.ic_folder_lock_open_white_36dp));
            } else {
                mProgressImage
                        .setImageDrawable(getResources().getDrawable(R.drawable.ic_folder_lock_open_grey600_36dp));
            }
            mProgressTypeText.setText(getResources().getString(R.string.crypt_decrypting));
            cancelBroadcast(new Intent(EncryptService.TAG_BROADCAST_CRYPT_CANCEL));
            break;
        }
    }

    /**
     * Setup click listener to cancel button click for various intent types
     * @param intent
     */
    private void cancelBroadcast(final Intent intent) {

        mCancelButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getActivity(), getResources().getString(R.string.stopping), Toast.LENGTH_LONG)
                        .show();
                getActivity().sendBroadcast(intent);
                mProgressTypeText.setText(getResources().getString(R.string.cancelled));
                mProgressSpeedText.setText("");
                mProgressFileText.setText("");
                mProgressBytesText.setText("");
                mProgressFileNameText.setText("");

                mProgressTypeText.setTextColor(Utils.getColor(getContext(), android.R.color.holo_red_light));
            }
        });
    }

    /**
     * Add a new entry dynamically to the chart, initializes a {@link LineDataSet} if not done so
     * @param xValue the x-axis value, the number of bytes processed till now
     * @param yValue the y-axis value, bytes processed per sec
     */
    private void addEntry(float xValue, float yValue) {

        ILineDataSet dataSet = mLineData.getDataSetByIndex(0);
        if (dataSet == null) {
            // adding set for first time
            dataSet = createDataSet();
            mLineData.addDataSet(dataSet);
        }

        int randomDataSetIndex = (int) (Math.random() * mLineData.getDataSetCount());
        mLineData.addEntry(new Entry(xValue, yValue), randomDataSetIndex);
        mLineData.notifyDataChanged();

        // let the chart know it's data has changed
        mLineChart.notifyDataSetChanged();
        mLineChart.invalidate();
    }

    /**
     * Creates an instance for {@link LineDataSet} which will store the entries
     * @return
     */
    private LineDataSet createDataSet() {
        LineDataSet lineDataset = new LineDataSet(new ArrayList<Entry>(), null);

        lineDataset.setLineWidth(1.75f);
        lineDataset.setCircleRadius(5f);
        lineDataset.setCircleHoleRadius(2.5f);
        lineDataset.setColor(Color.WHITE);
        lineDataset.setCircleColor(Color.WHITE);
        lineDataset.setHighLightColor(Color.WHITE);
        lineDataset.setDrawValues(false);
        lineDataset.setCircleColorHole(accentColor);

        return lineDataset;
    }

    /**
     * Initialize chart for the first time
     * @param totalBytes maximum value for x-axis
     */
    private void chartInit(long totalBytes) {
        mLineChart.setBackgroundColor(accentColor);
        mLineChart.getLegend().setEnabled(false);

        // no description text
        mLineChart.getDescription().setEnabled(false);

        XAxis xAxis = mLineChart.getXAxis();
        YAxis yAxisLeft = mLineChart.getAxisLeft();
        mLineChart.getAxisRight().setEnabled(false);
        yAxisLeft.setTextColor(Color.WHITE);
        yAxisLeft.setAxisLineColor(Color.TRANSPARENT);
        yAxisLeft.setTypeface(Typeface.DEFAULT_BOLD);
        yAxisLeft.setGridColor(Utils.getColor(getContext(), R.color.white_translucent));

        xAxis.setAxisMaximum(Futils.readableFileSizeFloat(totalBytes));
        xAxis.setAxisMinimum(0.0f);
        xAxis.setAxisLineColor(Color.TRANSPARENT);
        xAxis.setGridColor(Color.TRANSPARENT);
        xAxis.setTextColor(Color.WHITE);
        xAxis.setTypeface(Typeface.DEFAULT_BOLD);
        mLineChart.setData(mLineData);
        mLineChart.invalidate();
    }
}