no.digipost.android.gui.content.UploadActivity.java Source code

Java tutorial

Introduction

Here is the source code for no.digipost.android.gui.content.UploadActivity.java

Source

/**
 * Copyright (C) Posten Norge AS
 *
 * 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 no.digipost.android.gui.content;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.*;
import android.widget.*;
import com.google.android.gms.analytics.GoogleAnalytics;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.assist.ImageSize;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import no.digipost.android.DigipostApplication;
import no.digipost.android.R;
import no.digipost.android.api.ContentOperations;
import no.digipost.android.api.exception.DigipostApiException;
import no.digipost.android.api.exception.DigipostAuthenticationException;
import no.digipost.android.api.exception.DigipostClientException;
import no.digipost.android.constants.ApiConstants;
import no.digipost.android.constants.ApplicationConstants;
import no.digipost.android.model.Mailbox;
import no.digipost.android.utilities.*;
import org.apache.commons.io.FilenameUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import static java.lang.String.format;

public class UploadActivity extends AppCompatActivity {
    private final static File DEFAULT_INITIAL_DIRECTORY = Environment.getExternalStorageDirectory();
    private final String[] blockedFileContentTypes = { ApiConstants.TEXT_HTML };
    private final String KEY_DIRECTORY = "directory";

    private File mDirectory;
    private ArrayList<File> mFiles;
    private boolean mShowHiddenFiles = false;
    private UploadListAdapter listAdapter;

    private TextView absolutePath;
    private TextProgressBar availableSpace;
    private TextView listEmpty;
    private int content = 0;
    private final long TOO_LARGE_FILE = 104858027;
    private ActionMode uploadActionMode;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ((DigipostApplication) getApplication()).getTracker(DigipostApplication.TrackerName.APP_TRACKER);
        setContentView(R.layout.activity_upload);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setTitle(R.string.upload);
        getSupportActionBar().setHomeButtonEnabled(true);

        absolutePath = (TextView) findViewById(R.id.upload_file_path);
        availableSpace = (TextProgressBar) findViewById(R.id.upload_available_space);
        listEmpty = (TextView) findViewById(R.id.upload_list_empty);

        mDirectory = DEFAULT_INITIAL_DIRECTORY;
        mFiles = new ArrayList<File>();

        ListView listView = (ListView) findViewById(R.id.upload_file_list);
        listView.setEmptyView(listEmpty);
        listView.setOnItemClickListener(new ListOnItemClickListener());
        listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
        listView.setFastScrollEnabled(true);
        listView.setMultiChoiceModeListener(new UploadMultiChoiceModeListener());
        listAdapter = new UploadListAdapter(this, mFiles);
        listView.setAdapter(listAdapter);
        content = getIntent().getIntExtra(ApiConstants.UPLOAD, ApplicationConstants.MAILBOX);
        Permissions.requestWritePermissionsIfMissing(getApplicationContext(), UploadActivity.this);
        executeSetAccountInfoTask();
    }

    @Override
    protected void onStart() {
        super.onStart();
        GoogleAnalytics.getInstance(this).reportActivityStart(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        GoogleAnalytics.getInstance(this).reportActivityStop(this);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString(KEY_DIRECTORY, mDirectory.getAbsolutePath());
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        mDirectory = new File(savedInstanceState.getString(KEY_DIRECTORY));
    }

    @Override
    protected void onResume() {
        refreshFilesList();
        super.onResume();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (isFinishing()) {
            ImageLoader imageLoader = ImageLoader.getInstance();
            imageLoader.clearDiscCache();
            imageLoader.clearMemoryCache();
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            finish();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private void refreshFilesList() {
        absolutePath.setText(mDirectory.getAbsolutePath());

        mFiles.clear();

        File[] files = mDirectory.listFiles();

        if (files != null && files.length > 0) {
            for (File f : files) {
                if ((f.isHidden() && !mShowHiddenFiles) || !isAcceptedFileExtension(f)) {
                    continue;
                }

                mFiles.add(f);
            }

            Collections.sort(mFiles, new FileComparator());
        }
        listAdapter.notifyDataSetChanged();
    }

    private void setAvailableSpace(Mailbox mailbox) {
        long bytesUsed = Long.parseLong(mailbox.getUsedStorage());
        long bytesAvailable = Long.parseLong(mailbox.getTotalAvailableStorage());

        int percentUsed = (int) ((bytesUsed * 100) / bytesAvailable);

        availableSpace.setProgress(percentUsed);
        availableSpace.setText(percentUsed + getString(R.string.upload_space_used));
    }

    private boolean isAcceptedFileExtension(File file) {
        if (blockedFileContentTypes != null && blockedFileContentTypes.length > 0) {
            String contentType = FileUtilities.getMimeType(file);

            if (contentType != null) {
                for (String blockedFileContentType : blockedFileContentTypes) {
                    if (contentType.equals(blockedFileContentType)) {
                        return false;
                    }
                }
            }

            return true;
        }

        return true;
    }

    private void promtUpload(final File file) {
        final AlertDialog dialog = DialogUtitities
                .getAlertDialogBuilderWithMessageAndTitle(this,
                        getString(R.string.upload_dialog) + file.getName() + "?", getString(R.string.upload))
                .setPositiveButton(R.string.upload, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        executeUploadTask(file);
                        dialogInterface.dismiss();
                    }
                }).setNegativeButton(R.string.abort, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        dialogInterface.dismiss();
                    }
                }).create();

        dialog.setOnShowListener(new DialogInterface.OnShowListener() {

            @Override
            public void onShow(DialogInterface dialogInterface) {

                Button b = dialog.getButton(AlertDialog.BUTTON_NEUTRAL);
                b.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        previewFile(file);
                    }
                });
            }
        });

        dialog.show();
    }

    private void promtUpload(final ArrayList<File> files) {
        AlertDialog.Builder builder = DialogUtitities.getAlertDialogBuilderWithMessageAndTitle(this,
                getUploadFileDialogMessage(listAdapter.getCheckedCount()), getString(R.string.upload));
        builder.setPositiveButton(R.string.upload, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                uploadActionMode.finish();
                executeUploadTask(files);
                dialogInterface.dismiss();
            }
        });
        builder.setNegativeButton(R.string.abort, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                dialogInterface.dismiss();
            }
        });
        builder.create().show();
    }

    private String getUploadFileDialogMessage(int count) {
        if (count > 1) {
            return format(getString(R.string.upload_confirm_multiple), count);
        }

        return getString(R.string.upload_confirm_single);
    }

    private void previewFile(File file) {
        if (FilenameUtils.getExtension(file.getName()).toLowerCase().equals(ApiConstants.FILETYPE_PDF)) {
            Intent intent = new Intent(UploadActivity.this, MuPDFActivity.class);
            intent.putExtra(MuPDFActivity.ACTION_OPEN_FILEPATH, file.getAbsolutePath());
            startActivity(intent);
        } else {
            try {
                FileUtilities.openFileWithIntent(this, file);
            } catch (ActivityNotFoundException e) {
                DialogUtitities.showToast(this, getString(R.string.error_no_activity_to_open_file));
            }
        }
    }

    private void executeUploadTask(File file) {
        ArrayList<File> files = new ArrayList<File>();
        files.add(file);
        UploadTask uploadTask = new UploadTask(files, content);
        uploadTask.execute();
    }

    private void executeUploadTask(ArrayList<File> files) {
        UploadTask uploadTask = new UploadTask(files, content);
        uploadTask.execute();
    }

    private void setAccountInfo(Mailbox mailbox) {
        setAvailableSpace(mailbox);
        availableSpace.setVisibility(View.VISIBLE);
    }

    private void executeSetAccountInfoTask() {
        SetAccountInfoTask setAccountInfoTask = new SetAccountInfoTask();
        setAccountInfoTask.execute();
    }

    private class SetAccountInfoTask extends AsyncTask<Void, Void, Mailbox> {

        @Override
        protected Mailbox doInBackground(Void... voids) {
            try {
                return ContentOperations.getCurrentMailbox(UploadActivity.this);
            } catch (DigipostApiException e) {
                return null;
            } catch (DigipostClientException e) {
                return null;
            } catch (DigipostAuthenticationException e) {
                return null;
            }
        }

        @Override
        protected void onPostExecute(Mailbox mailbox) {
            super.onPostExecute(mailbox);

            if (mailbox != null) {
                setAccountInfo(mailbox);
            }
        }
    }

    @Override
    public void onBackPressed() {
        if (!mDirectory.equals(DEFAULT_INITIAL_DIRECTORY)) {
            mDirectory = mDirectory.getParentFile();
            refreshFilesList();
            return;
        }

        super.onBackPressed();
    }

    private class ListOnItemClickListener implements AdapterView.OnItemClickListener {

        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
            File newFile = listAdapter.getItem(position);
            if (newFile.length() > TOO_LARGE_FILE) {
                showTooLargeFileDialog();
            } else if (newFile.isFile()) {
                promtUpload(newFile);
            } else {
                mDirectory = newFile;
                refreshFilesList();
            }
        }
    }

    private void showTooLargeFileDialog() {
        String message = getString(R.string.upload_too_large_file);
        Dialog tooLargeFileDialog = DialogUtitities.getAlertDialogBuilderWithMessage(this, message).create();
        tooLargeFileDialog.show();
    }

    private class UploadListAdapter extends ArrayAdapter<File> {

        private ArrayList<File> objects;
        private boolean[] checked;
        private boolean checkboxVisible;

        private Context context;

        public UploadListAdapter(Context context, ArrayList<File> objects) {
            super(context, R.layout.upload_list_item, android.R.id.text1, objects);
            this.objects = objects;
            this.checked = new boolean[objects.size()];
            this.checkboxVisible = false;
            this.context = context;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            LayoutInflater inflater = (LayoutInflater) getContext()
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View row = inflater.inflate(R.layout.upload_list_item, parent, false);

            File object = objects.get(position);

            TextView name = (TextView) row.findViewById(R.id.upload_file_name);
            TextView size = (TextView) row.findViewById(R.id.upload_file_size);
            TextView extension = (TextView) row.findViewById(R.id.upload_file_extension);

            name.setText(FilenameUtils.getBaseName(object.getName()));

            final ImageView thumbnail = (ImageView) row.findViewById(R.id.upload_thumbnail);

            if (object.isFile()) {
                if (isImage(object)) {
                    ImageSize targetSize = new ImageSize(40, 40);
                    ImageLoader.getInstance().loadImage("file://" + object.getAbsolutePath(), targetSize,
                            getImageLoaderOptions(), new SimpleImageLoadingListener() {
                                @Override
                                public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
                                    super.onLoadingComplete(imageUri, view, loadedImage);
                                    thumbnail.setImageBitmap(loadedImage);
                                }

                                @Override
                                public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
                                    super.onLoadingFailed(imageUri, view, failReason);
                                    thumbnail.setImageDrawable(
                                            context.getResources().getDrawable(R.drawable.ic_grey_file));
                                }
                            });
                } else {
                    thumbnail.setImageDrawable(context.getResources().getDrawable(R.drawable.ic_grey_file));
                }

                size.setText(FormatUtilities.getFormattedFileSize(object.length()));
                extension.setText("." + FilenameUtils.getExtension(object.getName()));
            } else {
                thumbnail.setImageDrawable(context.getResources().getDrawable(R.drawable.ic_grey_folder));
            }

            CheckBox checkBox = (CheckBox) row.findViewById(R.id.upload_checkbox);
            checkBox.setFocusable(false);
            checkBox.setClickable(false);
            if (checkboxVisible) {
                if (checked[position]) {
                    checkBox.setChecked(true);
                }

                if (object.isFile()) {
                    checkBox.setVisibility(View.VISIBLE);
                }
            } else {
                checkBox.setVisibility(View.GONE);
            }

            return row;
        }

        private void initializeChecked() {
            checked = new boolean[objects.size()];
        }

        public void setCheckboxVisible(boolean state) {
            checkboxVisible = state;
            initializeChecked();
            notifyDataSetChanged();
        }

        public void clearChecked() {
            initializeChecked();
            notifyDataSetChanged();
        }

        public void setChecked(int position) throws UnsupportedOperationException {
            File file = objects.get(position);
            if (file.length() > TOO_LARGE_FILE) {
                showTooLargeFileDialog();
            } else if (file.isFile()) {
                checked[position] = !checked[position];
            } else {
                throw new UnsupportedOperationException(getString(R.string.upload_folder_exception));
            }
        }

        public int getCheckedCount() {
            int count = 0;

            for (boolean state : checked) {
                if (state) {
                    count++;
                }
            }

            return count;
        }

        public ArrayList<File> getCheckedItems() {
            ArrayList<File> checkedItems = new ArrayList<File>();

            for (int i = 0; i < checked.length; i++) {
                if (checked[i]) {
                    checkedItems.add(objects.get(i));
                }
            }

            return checkedItems;
        }

        private DisplayImageOptions getImageLoaderOptions() {
            return new DisplayImageOptions.Builder().cacheInMemory(true).cacheOnDisk(true).build();
        }

        private boolean isImage(File f) {
            for (String extension : ApiConstants.FILETYPES_IMAGE) {
                if (FilenameUtils.getExtension(f.getName()).equals(extension)) {
                    return true;
                }
            }

            return false;
        }
    }

    private class FileComparator implements Comparator<File> {
        @Override
        public int compare(File f1, File f2) {
            if (f1 == f2) {
                return 0;
            }
            if (f1.isDirectory() && f2.isFile()) {
                return -1;
            }
            if (f1.isFile() && f2.isDirectory()) {
                return 1;
            }

            return f1.getName().compareToIgnoreCase(f2.getName());
        }
    }

    private class UploadTask extends AsyncTask<Void, File, String> {
        private ArrayList<File> files;
        private boolean invalidToken;
        private int progress;
        private int content;

        private ProgressDialog progressDialog;

        public UploadTask(ArrayList<File> files, int content) {
            this.files = files;
            this.progress = 0;
            this.content = content;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            progressDialog = DialogUtitities.getProgressDialogWithMessage(UploadActivity.this, "");
            progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.abort),
                    new DialogInterface.OnClickListener() {
                        public void onClick(final DialogInterface dialog, final int which) {
                            dialog.dismiss();
                            UploadTask.this.cancel(true);
                        }
                    });

            progressDialog.show();
        }

        @Override
        protected String doInBackground(Void... voids) {
            try {
                for (File file : files) {
                    if (!isCancelled()) {
                        publishProgress(file);
                        progress++;
                        ContentOperations.uploadFile(UploadActivity.this, file, content);
                    }
                }

                return null;
            } catch (DigipostAuthenticationException e) {
                e.printStackTrace();
                invalidToken = true;
                return e.getMessage();
            } catch (DigipostApiException e) {
                e.printStackTrace();
                return e.getMessage();
            } catch (DigipostClientException e) {
                e.printStackTrace();
                return e.getMessage();
            }
        }

        @Override
        protected void onProgressUpdate(File... values) {
            super.onProgressUpdate(values);
            progressDialog
                    .setMessage(format(getString(R.string.uploading), values[0].getName(), progress, files.size()));
        }

        @Override
        protected void onCancelled() {
            super.onCancelled();
            progressDialog.dismiss();
            DialogUtitities.showToast(UploadActivity.this,
                    format(getString(R.string.upload_files_uploaded), progress, files.size()));
            finishActivityWithAction(ApiConstants.REFRESH_ARCHIVE);
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            progressDialog.dismiss();

            if (result != null) {
                if (invalidToken) {
                    finishActivityWithAction(ApiConstants.LOGOUT);
                }

                DialogUtitities.showToast(UploadActivity.this, result);
            } else {
                DialogUtitities.showToast(UploadActivity.this, getString(R.string.upload_complete));
                finishActivityWithAction(ApiConstants.UPLOAD);
            }
        }
    }

    private void finishActivityWithAction(String action) {
        Intent intent = new Intent();
        intent.putExtra(ApiConstants.FRAGMENT_ACTIVITY_RESULT_ACTION, action);
        setResult(RESULT_OK, intent);
        finish();
    }

    protected class UploadMultiChoiceModeListener implements AbsListView.MultiChoiceModeListener {

        @Override
        public void onItemCheckedStateChanged(ActionMode actionMode, int position, long id, boolean state) {

            try {
                listAdapter.setChecked(position);
                actionMode.setTitle(Integer.toString(listAdapter.getCheckedCount()));
                listAdapter.notifyDataSetChanged();
            } catch (UnsupportedOperationException e) {
                DialogUtitities.showToast(UploadActivity.this, e.getMessage());
                actionMode.finish();
            }
        }

        @Override
        public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
            uploadActionMode = actionMode;
            MenuInflater inflater = actionMode.getMenuInflater();
            inflater.inflate(R.menu.activity_upload_context, menu);
            listAdapter.setCheckboxVisible(true);

            return true;
        }

        @Override
        public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
            return false;
        }

        @Override
        public boolean onActionItemClicked(ActionMode actionMode, android.view.MenuItem menuItem) {
            switch (menuItem.getItemId()) {
            case R.id.upload_uploadButton:
                promtUpload(listAdapter.getCheckedItems());
                return true;
            default:
                return true;
            }
        }

        @Override
        public void onDestroyActionMode(ActionMode actionMode) {
            listAdapter.setCheckboxVisible(false);
            listAdapter.clearChecked();
            uploadActionMode = null;
        }
    }
}