com.amaze.filemanager.asynchronous.services.ExtractService.java Source code

Java tutorial

Introduction

Here is the source code for com.amaze.filemanager.asynchronous.services.ExtractService.java

Source

/*
 * ExtractService.java
 *
 * Copyright (C) 2014-2018 Arpit Khurana <arpitkh96@gmail.com>, Vishal Nehra <vishalmeham2@gmail.com>,
 * Emmanuel Messulam <emmanuelbendavid@gmail.com>, Raymond Lai <airwave209gt@gmail.com> and Contributors.
 *
 * 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.filemanager.asynchronous.services;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.RemoteViews;

import com.amaze.filemanager.R;
import com.amaze.filemanager.activities.MainActivity;
import com.amaze.filemanager.filesystem.compressed.CompressedHelper;
import com.amaze.filemanager.filesystem.compressed.extractcontents.Extractor;
import com.amaze.filemanager.ui.notifications.NotificationConstants;
import com.amaze.filemanager.utils.DatapointParcelable;
import com.amaze.filemanager.utils.ObtainableServiceBinder;
import com.amaze.filemanager.utils.ProgressHandler;
import com.amaze.filemanager.utils.ServiceWatcherUtil;
import com.amaze.filemanager.utils.application.AppConfig;

import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;

public class ExtractService extends AbstractProgressiveService {

    Context context;

    private final IBinder mBinder = new ObtainableServiceBinder<>(this);

    // list of data packages,// to initiate chart in process viewer fragment
    private ArrayList<DatapointParcelable> dataPackages = new ArrayList<>();

    private NotificationManager mNotifyManager;
    private NotificationCompat.Builder mBuilder;
    private ProgressHandler progressHandler = new ProgressHandler();
    private volatile float progressPercent = 0f;
    private ProgressListener progressListener;
    private int accentColor;
    private SharedPreferences sharedPreferences;
    private RemoteViews customSmallContentViews, customBigContentViews;

    public static final String KEY_PATH_ZIP = "zip";
    public static final String KEY_ENTRIES_ZIP = "entries";
    public static final String TAG_BROADCAST_EXTRACT_CANCEL = "excancel";
    public static final String KEY_PATH_EXTRACT = "extractpath";

    @Override
    public void onCreate() {
        registerReceiver(receiver1, new IntentFilter(TAG_BROADCAST_EXTRACT_CANCEL));
        context = getApplicationContext();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, final int startId) {
        String file = intent.getStringExtra(KEY_PATH_ZIP);
        String extractPath = intent.getStringExtra(KEY_PATH_EXTRACT);
        String[] entries = intent.getStringArrayExtra(KEY_ENTRIES_ZIP);

        mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
        accentColor = ((AppConfig) getApplication()).getUtilsProvider().getColorPreference()
                .getCurrentUserColorPreferences(this, sharedPreferences).accent;

        Intent notificationIntent = new Intent(this, MainActivity.class);
        notificationIntent.setAction(Intent.ACTION_MAIN);
        notificationIntent.putExtra(MainActivity.KEY_INTENT_PROCESS_VIEWER, true);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

        customSmallContentViews = new RemoteViews(getPackageName(), R.layout.notification_service_small);
        customBigContentViews = new RemoteViews(getPackageName(), R.layout.notification_service_big);

        Intent stopIntent = new Intent(TAG_BROADCAST_EXTRACT_CANCEL);
        PendingIntent stopPendingIntent = PendingIntent.getBroadcast(context, 1234, stopIntent,
                PendingIntent.FLAG_UPDATE_CURRENT);
        NotificationCompat.Action action = new NotificationCompat.Action(R.drawable.ic_zip_box_grey600_36dp,
                getString(R.string.stop_ftp), stopPendingIntent);

        mBuilder = new NotificationCompat.Builder(context, NotificationConstants.CHANNEL_NORMAL_ID);
        mBuilder.setContentIntent(pendingIntent).setSmallIcon(R.drawable.ic_zip_box_grey600_36dp)
                .setContentIntent(pendingIntent).setCustomContentView(customSmallContentViews)
                .setCustomBigContentView(customBigContentViews).setCustomHeadsUpContentView(customSmallContentViews)
                .setStyle(new NotificationCompat.DecoratedCustomViewStyle()).addAction(action).setOngoing(true)
                .setColor(accentColor);

        NotificationConstants.setMetadata(getApplicationContext(), mBuilder, NotificationConstants.TYPE_NORMAL);
        startForeground(NotificationConstants.EXTRACT_ID, mBuilder.build());
        initNotificationViews();

        long totalSize = getTotalSize(file);

        progressHandler.setSourceSize(1);
        progressHandler.setTotalSize(totalSize);
        progressHandler.setProgressListener((speed) -> publishResults(speed, false, false));

        super.onStartCommand(intent, flags, startId);
        super.progressHalted();
        new DoWork(this, progressHandler, file, extractPath, entries).execute();

        return START_STICKY;
    }

    @Override
    protected NotificationManager getNotificationManager() {
        return mNotifyManager;
    }

    @Override
    protected NotificationCompat.Builder getNotificationBuilder() {
        return mBuilder;
    }

    @Override
    protected int getNotificationId() {
        return NotificationConstants.EXTRACT_ID;
    }

    @Override
    protected float getPercentProgress() {
        return progressPercent;
    }

    @Override
    protected void setPercentProgress(float progress) {
        progressPercent = progress;
    }

    @Override
    protected RemoteViews getNotificationCustomViewSmall() {
        return customSmallContentViews;
    }

    @Override
    protected RemoteViews getNotificationCustomViewBig() {
        return customBigContentViews;
    }

    public ProgressListener getProgressListener() {
        return progressListener;
    }

    @Override
    public void setProgressListener(ProgressListener progressListener) {
        this.progressListener = progressListener;
    }

    @Override
    protected ArrayList<DatapointParcelable> getDataPackages() {
        return dataPackages;
    }

    @Override
    protected ProgressHandler getProgressHandler() {
        return progressHandler;
    }

    @Override
    public void onDestroy() {
        unregisterReceiver(receiver1);
    }

    /**
     * Method calculates zip file size to initiate progress
     * Supporting local file extraction progress for now
     */
    private long getTotalSize(String filePath) {
        return new File(filePath).length();
    }

    public class DoWork extends AsyncTask<Void, Void, Boolean> {
        private WeakReference<ExtractService> extractService;
        private String[] entriesToExtract;
        private String extractionPath, compressedPath;
        private ProgressHandler progressHandler;
        private ServiceWatcherUtil watcherUtil;

        private DoWork(ExtractService extractService, ProgressHandler progressHandler, String cpath, String epath,
                String[] entries) {
            this.extractService = new WeakReference<>(extractService);
            this.progressHandler = progressHandler;
            compressedPath = cpath;
            extractionPath = epath;
            entriesToExtract = entries;
        }

        @Override
        protected Boolean doInBackground(Void... p) {
            final ExtractService extractService = this.extractService.get();
            if (extractService == null)
                return null;

            File f = new File(compressedPath);
            String extractDirName = CompressedHelper.getFileName(f.getName());

            if (compressedPath.equals(extractionPath)) {
                // custom extraction path not set, extract at default path
                extractionPath = f.getParent() + "/" + extractDirName;
            } else {
                if (extractionPath.endsWith("/")) {
                    extractionPath = extractionPath + extractDirName;
                } else {
                    extractionPath = extractionPath + "/" + extractDirName;
                }
            }

            try {
                if (entriesToExtract.length == 0)
                    entriesToExtract = null;

                final Extractor extractor = CompressedHelper.getExtractorInstance(
                        extractService.getApplicationContext(), f, extractionPath, new Extractor.OnUpdate() {
                            private int sourceFilesProcessed = 0;

                            @Override
                            public void onStart(long totalBytes, String firstEntryName) {
                                // setting total bytes calculated from zip entries
                                progressHandler.setTotalSize(totalBytes);

                                extractService.addFirstDatapoint(firstEntryName, 1, totalBytes, false);

                                watcherUtil = new ServiceWatcherUtil(progressHandler);
                                watcherUtil.watch(ExtractService.this);
                            }

                            @Override
                            public void onUpdate(String entryPath) {
                                progressHandler.setFileName(entryPath);
                                if (entriesToExtract != null) {
                                    progressHandler.setSourceFilesProcessed(sourceFilesProcessed++);
                                }
                            }

                            @Override
                            public void onFinish() {
                                if (entriesToExtract == null) {
                                    progressHandler.setSourceFilesProcessed(1);
                                }
                            }

                            @Override
                            public boolean isCancelled() {
                                return progressHandler.getCancelled();
                            }
                        });

                if (entriesToExtract != null) {
                    extractor.extractFiles(entriesToExtract);
                } else {
                    extractor.extractEverything();
                }
                return (extractor.getInvalidArchiveEntries().size() == 0);
            } catch (IOException e) {
                Log.e("amaze", "Error while extracting file " + compressedPath, e);
                AppConfig.toast(extractService, extractService.getString(R.string.error));
                return false;
            }
        }

        @Override
        public void onPostExecute(Boolean hasInvalidEntries) {
            final ExtractService extractService = this.extractService.get();
            if (extractService == null)
                return;

            // check whether watcherutil was initialized. It was not initialized when we got exception
            // in extracting the file
            if (watcherUtil != null)
                watcherUtil.stopWatch();
            Intent intent = new Intent(MainActivity.KEY_INTENT_LOAD_LIST);
            intent.putExtra(MainActivity.KEY_INTENT_LOAD_LIST_FILE, extractionPath);
            extractService.sendBroadcast(intent);
            extractService.stopSelf();

            if (!hasInvalidEntries)
                AppConfig.toast(extractService, getString(R.string.multiple_invalid_archive_entries));
        }
    }

    /**
     * Class used for the client Binder.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with IPC.
     */
    private BroadcastReceiver receiver1 = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            progressHandler.setCancelled(true);
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

}