me.xingrz.finder.ZipFinderActivity.java Source code

Java tutorial

Introduction

Here is the source code for me.xingrz.finder.ZipFinderActivity.java

Source

/*
 * Copyright 2015 XiNGRZ <chenxingyu92@gmail.com>
 *
 * 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 me.xingrz.finder;

import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.util.Log;
import android.widget.EditText;
import android.widget.Toast;

import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.progress.ProgressMonitor;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;

import java.io.File;
import java.io.IOException;
import java.util.List;

public class ZipFinderActivity extends EntriesActivity implements Runnable {

    public static final String EXTRA_PREFIX = "prefix";

    private static final String TAG = "ZipFinderActivity";

    private static final int REQUEST_OPEN_FILE = 1;

    private static final long PROGRESS_INTERVAL = 40;

    private final Handler handler = new Handler(Looper.getMainLooper());

    private File current;
    private ZipFile zipFile;

    private ProgressMonitor progressMonitor;

    private Intent pendingIntent;

    private FileHeader extracting;

    private AlertDialog passwordPrompt;

    private ProgressDialog progressDialog;

    @Override
    protected void onCreateInternal(Bundle savedInstanceState) {
        super.onCreateInternal(savedInstanceState);

        current = new File(getIntent().getData().getPath());

        try {
            zipFile = new ZipFile(current);
            zipFile.setRunInThread(true);
        } catch (ZipException e) {
            Log.d(TAG, "failed to open zip file " + current.getAbsolutePath(), e);
        }

        if (getIntent().hasExtra(EXTRA_PREFIX)) {
            toolbar.setTitle(FilenameUtils.getName(getIntent().getStringExtra(EXTRA_PREFIX)));
            toolbar.setSubtitle(current.getName());
        }

        passwordPrompt = new AlertDialog.Builder(this).setView(R.layout.dialog_password)
                .setPositiveButton("", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        confirmFilePassword();
                    }
                }).create();

        progressMonitor = zipFile.getProgressMonitor();

        progressDialog = new ProgressDialog(this);
        progressDialog.setMax(100);
        progressDialog.setCancelable(false);
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    }

    @Override
    protected void onDestroyInternal() {
        super.onDestroyInternal();
        handler.removeCallbacksAndMessages(null);
    }

    @Override
    protected int provideContentView() {
        return R.layout.activity_finder;
    }

    @Override
    protected String getCurrentDisplayName() {
        return current.getName();
    }

    @Override
    protected RecyclerView.Adapter getAdapter() {
        List<FileHeader> headers;

        try {
            //noinspection unchecked
            headers = zipFile.getFileHeaders();
        } catch (ZipException e) {
            return null;
        }

        return new ZipAdapter(this, headers, getIntent().getStringExtra(EXTRA_PREFIX)) {
            @Override
            protected void openFolder(final AbstractFile folder) {
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        Intent intent = new Intent();
                        intent.setData(getIntent().getData());
                        intent.putExtra(EXTRA_PREFIX, folder.path);
                        startFinder(intent, ZipFinderActivity.class);
                    }
                }, START_ACTIVITY_DELAY);
            }

            @Override
            protected void openFile(AbstractFile file) {
                if (file.isDirectory || file.header == null) {
                    Log.e(TAG, "not a valid file to extract");
                    return;
                }

                extracting = file.header;
                openFileInZip();
            }
        };
    }

    private void openFileInZip() {
        if (getExternalCacheDir() == null) {
            Log.e(TAG, "no external cache dir to extract");
            return;
        }

        File target = new File(getExternalCacheDir(), extracting.getFileName());
        Intent intent = intentToView(Uri.fromFile(target), mimeOfFile(target));

        if (intent.resolveActivityInfo(getPackageManager(), 0) == null) {
            Log.e(TAG, "no activity to handle file " + extracting.getFileName());
            Toast.makeText(this, "", Toast.LENGTH_SHORT).show();
            return;
        }

        if (extracting.isEncrypted()
                && (extracting.getPassword() == null || extracting.getPassword().length == 0)) {
            passwordPrompt.show();
            return;
        }

        try {
            zipFile.extractFile(extracting, getExternalCacheDir().getAbsolutePath());
        } catch (ZipException ignored) {
        }

        pendingIntent = intent;

        progressDialog.setProgress(0);
        progressDialog.show();

        handler.post(this);
    }

    private void confirmFilePassword() {
        Editable password = ((EditText) passwordPrompt.findViewById(R.id.password)).getText();

        char[] chars = new char[password.length()];
        password.getChars(0, password.length(), chars, 0);

        extracting.setPassword(chars);
        openFileInZip();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
        case REQUEST_OPEN_FILE:
            deleteTempFile();
            break;
        default:
            super.onActivityResult(requestCode, resultCode, data);
            break;
        }
    }

    private void deleteTempFile() {
        if (getExternalCacheDir() == null) {
            Log.d(TAG, "nothing to clean");
        }

        try {
            // FIXME: sub dir in the future
            FileUtils.cleanDirectory(getExternalCacheDir());
            Log.d(TAG, "cleaned cache dir");
        } catch (IOException e) {
            Log.e(TAG, "failed to clean cache dir", e);
        }
    }

    @Override
    public void run() {
        if (progressMonitor.getState() == ProgressMonitor.STATE_BUSY) {
            progressDialog.setProgress(progressMonitor.getPercentDone());
            handler.postDelayed(this, PROGRESS_INTERVAL);
        } else if (progressMonitor.getResult() == ProgressMonitor.RESULT_SUCCESS) {
            progressDialog.dismiss();
            startActivityForResult(pendingIntent, REQUEST_OPEN_FILE);
            overridePendingTransitionForBuiltInViewer(pendingIntent);
            extracting = null;
        } else if (progressMonitor.getResult() == ProgressMonitor.RESULT_ERROR) {
            progressDialog.dismiss();
            Log.e(TAG, "failed to extract file " + extracting.getFileName(), progressMonitor.getException());
            Toast.makeText(this, "?", Toast.LENGTH_SHORT).show();
            extracting.setPassword(null);
            extracting = null;
        }
    }

}