com.peppe130.fireinstaller.core.CustomFileChooser.java Source code

Java tutorial

Introduction

Here is the source code for com.peppe130.fireinstaller.core.CustomFileChooser.java

Source

/*
    
Copyright  2016, Giuseppe Montuoro and Aidan Follestad.
    
This program 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.peppe130.fireinstaller.core;

import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.Manifest;
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.webkit.MimeTypeMap;
import java.io.File;
import java.io.FileFilter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import com.peppe130.fireinstaller.R;
import com.peppe130.fireinstaller.ControlCenter;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;

public class CustomFileChooser extends DialogFragment implements MaterialDialog.ListCallback {

    private final static String DEFAULT_TAG = "[MD_FILE_SELECTOR]";

    MaterialDialog mDialog;
    private File parentFolder;
    private File[] parentContents;
    private boolean canGoUp = true;
    private FileCallback mCallback;

    public interface FileCallback {

        void onFileSelection(@NonNull CustomFileChooser dialog, @NonNull File file);

    }

    public CustomFileChooser() {

    }

    String[] getContentsArray() {

        if (parentContents == null) {

            return new String[] { "..." };

        }

        if (getLockExplorer() && parentFolder.getAbsolutePath().equals(getPathToBeLocked())) {

            canGoUp = false;

            String[] results = new String[parentContents.length];

            for (int i = 0; i < parentContents.length; i++)

                results[i] = parentContents[i].getName();

            return results;

        } else {

            String[] results = new String[parentContents.length + (canGoUp ? 1 : 0)];

            results[0] = "...";

            for (int i = 0; i < parentContents.length; i++)

                results[canGoUp ? i + 1 : i] = parentContents[i].getName();

            return results;

        }

    }

    File[] listFiles(String mimeType) {

        File[] contents = parentFolder.listFiles(new FileFilter() {
            @Override
            public boolean accept(File file) {

                return getShowHiddenFiles() || !file.isHidden();

            }
        });

        List<File> results = new ArrayList<>();

        if (contents != null) {

            MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();

            for (File fi : contents) {

                if (fi.isDirectory()) {

                    results.add(fi);

                } else {

                    if (fileIsMimeType(fi, mimeType, mimeTypeMap)) {

                        results.add(fi);

                    }

                }

            }

            Collections.sort(results, new FileSorter());

            return results.toArray(new File[results.size()]);

        }

        return null;

    }

    boolean fileIsMimeType(File file, String mimeType, MimeTypeMap mimeTypeMap) {

        if (mimeType == null || mimeType.equals("*/*")) {

            return true;

        } else {

            String filename = file.toURI().toString();

            int dotPos = filename.lastIndexOf('.');

            if (dotPos == -1) {

                return false;

            }

            String fileExtension = filename.substring(dotPos + 1);

            String fileType = mimeTypeMap.getMimeTypeFromExtension(fileExtension);

            if (fileType == null) {

                return false;

            }

            if (fileType.equals(mimeType)) {

                return true;

            }

            int mimeTypeDelimiter = mimeType.lastIndexOf('/');

            if (mimeTypeDelimiter == -1) {

                return false;

            }

            String mimeTypeMainType = mimeType.substring(0, mimeTypeDelimiter);

            String mimeTypeSubtype = mimeType.substring(mimeTypeDelimiter + 1);

            if (!mimeTypeSubtype.equals("*")) {

                return false;

            }

            int fileTypeDelimiter = fileType.lastIndexOf('/');

            if (fileTypeDelimiter == -1) {

                return false;

            }

            String fileTypeMainType = fileType.substring(0, fileTypeDelimiter);

            if (fileTypeMainType.equals(mimeTypeMainType)) {

                return true;

            }

        }

        return false;

    }

    @NonNull
    @Override
    @SuppressWarnings("ConstantConditions")
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        if (ControlCenter.TRIAL_MODE && !getLockExplorer()) {

            getFragmentManager().beginTransaction().add(new ChooseSampleFile(), "choose_sample_file")
                    .commitAllowingStateLoss();

        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && ActivityCompat.checkSelfPermission(getActivity(),
                Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {

            return new MaterialDialog.Builder(getActivity()).title(R.string.md_error_label)
                    .content(R.string.md_storage_perm_error).positiveText(android.R.string.ok).build();

        }

        if (getArguments() == null || !getArguments().containsKey("builder")) {

            throw new IllegalStateException("You must create a FileChooserDialog using the Builder.");

        } else if (!getArguments().containsKey("current_path")) {

            getArguments().putString("current_path", getInitialPath());

        }

        parentFolder = new File(getArguments().getString("current_path"));

        parentContents = listFiles(getBuilder().mMimeType);

        mDialog = new MaterialDialog.Builder(getActivity()).title(parentFolder.getAbsolutePath())
                .items(getContentsArray()).itemsCallback(this)
                .positiveText(getLockExplorer() ? getString(R.string.clear_downloads_button)
                        : getString(R.string.rom_download_button))
                .onPositive(new MaterialDialog.SingleButtonCallback() {
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {

                        if (getLockExplorer()) {

                            dialog.dismiss();

                            Utils.DeleteFolderRecursively(getPathToBeLocked());

                            Utils.ToastShort(getActivity(), getString(R.string.cleared));

                        } else {

                            if (Utils.isConnected()) {

                                if (Utils.isWifiAvailable()) {

                                    new MaterialDialog.Builder(getActivity())
                                            .content(getString(
                                                    R.string.download_rom_from_file_chooser_dialog_content))
                                            .positiveText(getString(R.string.positive_button))
                                            .negativeText(getString(R.string.negative_button))
                                            .onPositive(new MaterialDialog.SingleButtonCallback() {
                                                @Override
                                                public void onClick(@NonNull MaterialDialog dialog,
                                                        @NonNull DialogAction which) {

                                                    mDialog.dismiss();

                                                    new Handler().postDelayed(new Runnable() {
                                                        @Override
                                                        public void run() {

                                                            ControlCenter.DownloadROM();

                                                        }
                                                    }, 300);

                                                }
                                            }).show();

                                } else {

                                    new MaterialDialog.Builder(getActivity())
                                            .title(getString(R.string.no_wifi_network_dialog_title))
                                            .content(getString(R.string.no_wifi_network_dialog_message))
                                            .positiveText(getString(R.string.positive_button))
                                            .onPositive(new MaterialDialog.SingleButtonCallback() {
                                                @Override
                                                public void onClick(@NonNull MaterialDialog dialog,
                                                        @NonNull DialogAction which) {

                                                    mDialog.dismiss();

                                                    new Handler().postDelayed(new Runnable() {
                                                        @Override
                                                        public void run() {

                                                            ControlCenter.DownloadROM();

                                                        }
                                                    }, 300);

                                                }
                                            }).negativeText(getString(R.string.negative_button)).show();

                                }

                            } else {

                                new MaterialDialog.Builder(getActivity())
                                        .title(getString(R.string.no_network_connection_dialog_title))
                                        .content(getString(R.string.no_network_connection_dialog_message))
                                        .positiveText(getString(R.string.ok_button)).show();

                            }

                        }

                    }
                }).autoDismiss(false).canceledOnTouchOutside(getCanceledOnTouchOutside()).build();

        return mDialog;

    }

    @Override
    public void onSelection(MaterialDialog materialDialog, View view, int i, CharSequence s) {

        if (canGoUp && i == 0) {

            parentFolder = parentFolder.getParentFile();

            if (parentFolder.getAbsolutePath().equals("/storage/emulated")) {

                parentFolder = parentFolder.getParentFile();

            }

            if (!getLockExplorer()) {

                canGoUp = parentFolder.getParent() != null;

            } else if (getLockExplorer() && parentFolder.getAbsolutePath().equals(getPathToBeLocked())) {

                canGoUp = false;

            }

        } else {

            if (getLockExplorer() && parentFolder.getAbsolutePath().equals(getPathToBeLocked())) {

                parentFolder = parentContents[i];

            } else {

                parentFolder = parentContents[canGoUp ? i - 1 : i];

            }

            canGoUp = true;

            if (parentFolder.getAbsolutePath().equals("/storage/emulated")) {

                parentFolder = Environment.getExternalStorageDirectory();

            }

        }

        if (parentFolder.isFile()) {

            if (getLockExplorer()) {

                String mContent = (String.format(getString(R.string.clear_single_download_dialog_message),
                        parentFolder.getName()));

                new MaterialDialog.Builder(getActivity()).content(mContent)
                        .positiveText(getString(R.string.positive_button))
                        .negativeText(getString(R.string.negative_button))
                        .onPositive(new MaterialDialog.SingleButtonCallback() {
                            @Override
                            @SuppressWarnings("ResultOfMethodCallIgnored")
                            public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {

                                File mFile = parentFolder.getAbsoluteFile();

                                mFile.delete();

                            }
                        }).dismissListener(new DialogInterface.OnDismissListener() {
                            @Override
                            public void onDismiss(DialogInterface dialogInterface) {

                                parentFolder = parentFolder.getAbsoluteFile().getParentFile();

                                parentContents = listFiles(getBuilder().mMimeType);

                                MaterialDialog dialog2 = (MaterialDialog) getDialog();

                                dialog2.setTitle(parentFolder.toString());

                                getArguments().putString("current_path", parentFolder.toString());

                                dialog2.setItems(getContentsArray());

                            }
                        }).show();

            } else if (parentFolder.getAbsolutePath().contains(".zip")) {

                mCallback.onFileSelection(this, parentFolder);

                dismiss();

            } else {

                Utils.ToastShort(getActivity(), getString(R.string.not_valid_zip_file));

            }

        } else {

            parentContents = listFiles(getBuilder().mMimeType);

            MaterialDialog dialog = (MaterialDialog) getDialog();

            dialog.setTitle(parentFolder.getAbsolutePath());

            getArguments().putString("current_path", parentFolder.getAbsolutePath());

            dialog.setItems(getContentsArray());

        }

    }

    @Override
    @SuppressWarnings("deprecation")
    public void onAttach(Activity activity) {

        super.onAttach(activity);

        mCallback = (FileCallback) activity;

    }

    public void show(FragmentActivity context) {

        final String tag = getBuilder().mTag;

        Fragment frag = context.getSupportFragmentManager().findFragmentByTag(tag);

        if (frag != null) {

            ((DialogFragment) frag).dismiss();

            context.getSupportFragmentManager().beginTransaction().remove(frag).commit();
        }

        show(context.getSupportFragmentManager(), tag);

    }

    @SuppressWarnings("unused")
    public static class Builder implements Serializable {

        @NonNull
        protected final transient AppCompatActivity mContext;
        protected String mInitialPath;
        protected String mMimeType;
        protected String mTag;
        protected String mPathToBeLocked;
        protected Boolean mLockExplorer = false;
        protected Boolean mCanceledOnTouchOutside = true;
        protected Boolean mShowHiddenFiles = false;

        public <ActivityType extends AppCompatActivity & FileCallback> Builder(@NonNull AppCompatActivity context) {
            mContext = context;
            mInitialPath = Environment.getExternalStorageDirectory().getAbsolutePath();
            mMimeType = null;
            mLockExplorer = false;
            mCanceledOnTouchOutside = true;
            mShowHiddenFiles = false;
        }

        @NonNull
        public Builder initialPath(@Nullable String initialPath) {

            if (initialPath == null) {

                initialPath = File.separator;

            }

            mInitialPath = initialPath;

            return this;

        }

        @NonNull
        public Builder mimeType(@Nullable String type) {

            mMimeType = type;

            return this;

        }

        @NonNull
        public Builder lockFolder(@Nullable String pathToBeLocked, Boolean isLocked, Boolean equalsToInitialPath) {

            if (equalsToInitialPath) {

                mPathToBeLocked = mInitialPath;

            } else {

                mPathToBeLocked = pathToBeLocked;

            }

            mLockExplorer = isLocked;

            return this;

        }

        @NonNull
        public Builder canceledOnTouchOutside(boolean canceledOnTouchOutside) {

            this.mCanceledOnTouchOutside = canceledOnTouchOutside;

            return this;

        }

        @NonNull
        public Builder showHiddenFiles(boolean showHiddenFiles) {

            this.mShowHiddenFiles = showHiddenFiles;

            return this;

        }

        @NonNull
        public Builder tag(@Nullable String tag) {

            if (tag == null) {

                tag = DEFAULT_TAG;

            }

            mTag = tag;

            return this;

        }

        @NonNull
        public CustomFileChooser build() {

            CustomFileChooser dialog = new CustomFileChooser();

            Bundle args = new Bundle();

            args.putSerializable("builder", this);

            dialog.setArguments(args);

            return dialog;

        }

        @NonNull
        public CustomFileChooser show() {

            CustomFileChooser dialog = build();

            dialog.show(mContext);

            return dialog;

        }

    }

    @NonNull
    public String getInitialPath() {

        return getBuilder().mInitialPath;

    }

    @NonNull
    public String getPathToBeLocked() {

        return getBuilder().mPathToBeLocked;

    }

    @NonNull
    public Boolean getLockExplorer() {

        return getBuilder().mLockExplorer;

    }

    @NonNull
    public Boolean getCanceledOnTouchOutside() {

        return getBuilder().mCanceledOnTouchOutside;

    }

    @NonNull
    public Boolean getShowHiddenFiles() {

        return getBuilder().mShowHiddenFiles;

    }

    @NonNull
    @SuppressWarnings("ConstantConditions")
    private Builder getBuilder() {

        return (Builder) getArguments().getSerializable("builder");

    }

    private static class FileSorter implements Comparator<File> {
        @Override
        public int compare(File lhs, File rhs) {

            if (lhs.isDirectory() && !rhs.isDirectory()) {

                return -1;

            } else if (!lhs.isDirectory() && rhs.isDirectory()) {

                return 1;

            } else {

                return lhs.getName().compareTo(rhs.getName());

            }

        }

    }

    public static class ChooseSampleFile extends DialogFragment {

        public ChooseSampleFile() {

        }

        @NonNull
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {

            setCancelable(false);

            String mContent = (String.format(Utils.ACTIVITY.getString(R.string.choose_sample_file),
                    Utils.ROM_DOWNLOAD_FOLDER + "."));

            return new MaterialDialog.Builder(getActivity()).content(mContent)
                    .positiveText(getString(R.string.ok_button)).canceledOnTouchOutside(false).show();

        }

    }

}