com.doplgangr.secrecy.views.FileViewer.java Source code

Java tutorial

Introduction

Here is the source code for com.doplgangr.secrecy.views.FileViewer.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with context work for additional information
 * regarding copyright ownership.  The ASF licenses context file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use context 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 com.doplgangr.secrecy.views;

import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.MimeTypeMap;
import android.widget.Toast;

import com.doplgangr.secrecy.Config;
import com.doplgangr.secrecy.CustomApp;
import com.doplgangr.secrecy.filesystem.CryptStateListener;
import com.doplgangr.secrecy.filesystem.encryption.Vault;
import com.doplgangr.secrecy.filesystem.files.EncryptedFile;
import com.doplgangr.secrecy.filesystem.files.SecrecyFile;
import com.doplgangr.secrecy.filesystem.OurFileProvider;
import com.doplgangr.secrecy.filesystem.Storage;
import com.doplgangr.secrecy.jobs.AddFileJob;
import com.doplgangr.secrecy.R;
import com.doplgangr.secrecy.Util;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public abstract class FileViewer extends Fragment {

    ActionBarActivity context;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.activity_file_viewer, container, false);
    }

    void addFileInBackground(final Vault secret, final Uri data) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                CustomApp.jobManager.addJobInBackground(new AddFileJob(context, secret, data));
            }
        }).start();
    }

    void decrypt(final EncryptedFile encryptedFile, final Runnable onFinish) {
        new AsyncTask<EncryptedFile, Void, File>() {
            @Override
            protected File doInBackground(EncryptedFile... encryptedFiles) {
                return getFile(encryptedFile, onFinish);
            }

            @Override
            protected void onPostExecute(File tempFile) {
                if (tempFile != null) {
                    if (tempFile.getParentFile().equals(Storage.getTempFolder())) {
                        tempFile = new File(Storage.getTempFolder(), tempFile.getName());
                    }
                    Uri uri = OurFileProvider.getUriForFile(context, OurFileProvider.FILE_PROVIDER_AUTHORITY,
                            tempFile);
                    MimeTypeMap myMime = MimeTypeMap.getSingleton();
                    Intent newIntent = new Intent(android.content.Intent.ACTION_VIEW);
                    String mimeType = myMime.getMimeTypeFromExtension(encryptedFile.getType());
                    newIntent.setDataAndType(uri, mimeType);
                    newIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    //altIntent: resort to using file provider when content provider does not work.
                    Intent altIntent = new Intent(android.content.Intent.ACTION_VIEW);
                    Uri rawuri = Uri.fromFile(tempFile);
                    altIntent.setDataAndType(rawuri, mimeType);
                    afterDecrypt(newIntent, altIntent);
                }
            }
        }.execute(encryptedFile);
    }

    void sendMultiple(final ArrayList<FilesListFragment.DecryptArgHolder> args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                ArrayList<Uri> uris = new ArrayList<Uri>();
                Set<String> mimes = new HashSet<String>();
                MimeTypeMap myMime = MimeTypeMap.getSingleton();
                for (FilesListFragment.DecryptArgHolder arg : args) {
                    File tempFile = getFile(arg.encryptedFile, arg.onFinish);
                    //File specified is not invalid
                    if (tempFile != null) {
                        if (tempFile.getParentFile().equals(Storage.getTempFolder()))
                            tempFile = new java.io.File(Storage.getTempFolder(), tempFile.getName());
                        uris.add(OurFileProvider.getUriForFile(context, OurFileProvider.FILE_PROVIDER_AUTHORITY,
                                tempFile));
                        mimes.add(myMime.getMimeTypeFromExtension(arg.encryptedFile.getType()));

                    }
                }
                if (uris.size() == 0 || mimes.size() == 0)
                    return;
                Intent newIntent;
                if (uris.size() == 1) {
                    newIntent = new Intent(Intent.ACTION_SEND);
                    newIntent.putExtra(Intent.EXTRA_STREAM, uris.get(0));
                } else {
                    newIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
                    newIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
                }
                if (mimes.size() > 1)
                    newIntent.setType("text/plain"); //Mixed filetypes
                else
                    newIntent.setType(new ArrayList<String>(mimes).get(0));
                newIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                Intent chooserIntent = generateCustomChooserIntent(newIntent, uris);
                try {
                    startActivity(Intent.createChooser(chooserIntent,
                            CustomApp.context.getString(R.string.Dialog__send_file)));
                    FilesActivity.onPauseDecision.startActivity();
                } catch (android.content.ActivityNotFoundException e) {
                    Util.toast(context, CustomApp.context.getString(R.string.Error__no_activity_view),
                            Toast.LENGTH_LONG);
                    FilesActivity.onPauseDecision.finishActivity();
                }
            }
        }).start();
    }

    File getFile(final EncryptedFile encryptedFile, final Runnable onfinish) {
        CryptStateListener listener = new CryptStateListener() {
            @Override
            public void updateProgress(int progress) {
                updatePBar(encryptedFile, progress);
            }

            @Override
            public void setMax(int max) {
                maxPBar(encryptedFile, max);
            }

            @Override
            public void onFailed(int statCode) {
                String message;
                switch (statCode) {
                case Config.wrong_password:
                    message = getString(R.string.Error__wrong_password);
                    break;
                case Config.file_not_found:
                    message = getString(R.string.Error__file_not_found);
                    break;
                default:
                    message = getString(R.string.Error__unknown);
                }
                alert(message);
            }

            @Override
            public void Finished() {

                onfinish.run();
            }
        };
        return encryptedFile.readFile(listener);
    }

    void afterDecrypt(Intent newIntent, Intent altIntent) {
        try {
            startActivity(newIntent);
            FilesActivity.onPauseDecision.startActivity();
        } catch (android.content.ActivityNotFoundException e) {
            try {
                startActivity(altIntent);
                FilesActivity.onPauseDecision.startActivity();
            } catch (android.content.ActivityNotFoundException e2) {
                Util.toast(context, getString(R.string.Error__no_activity_view), Toast.LENGTH_LONG);
                FilesActivity.onPauseDecision.finishActivity();
            }
        } catch (IllegalStateException e) {
            //duh why you leave so early
            FilesActivity.onPauseDecision.finishActivity();
        }
    }

    void alert(String message) {
        DialogInterface.OnClickListener click = new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
                finish();
            }
        };
        Util.alert(context, getString(R.string.Error__decrypt_file), message, click, null);
    }

    void updatePBar(SecrecyFile file, int progress) {
        if (file.getProgressBar() != null)
            file.getProgressBar().setProgress(progress);
    }

    void maxPBar(EncryptedFile file, int max) {
        if (file.getProgressBar() != null)
            file.getProgressBar().setMax(max);
    }

    private Intent generateCustomChooserIntent(Intent prototype, ArrayList<Uri> uris) {
        List<Intent> targetedShareIntents = new ArrayList<Intent>();
        List<HashMap<String, String>> intentMetaInfo = new ArrayList<HashMap<String, String>>();
        Intent chooserIntent;

        Intent dummy = new Intent(prototype.getAction());
        dummy.setType(prototype.getType());
        List<ResolveInfo> resInfo = context.getPackageManager().queryIntentActivities(dummy, 0);

        if (!resInfo.isEmpty()) {
            for (ResolveInfo resolveInfo : resInfo) {
                if (resolveInfo.activityInfo == null
                        || resolveInfo.activityInfo.packageName.equalsIgnoreCase("com.doplgangr.secrecy"))
                    continue;

                HashMap<String, String> info = new HashMap<String, String>();
                info.put("packageName", resolveInfo.activityInfo.packageName);
                info.put("className", resolveInfo.activityInfo.name);
                info.put("simpleName",
                        String.valueOf(resolveInfo.activityInfo.loadLabel(context.getPackageManager())));
                intentMetaInfo.add(info);
                for (Uri uri : uris)
                    context.grantUriPermission(resolveInfo.activityInfo.packageName, uri,
                            Intent.FLAG_GRANT_READ_URI_PERMISSION);
            }

            if (!intentMetaInfo.isEmpty()) {
                // sorting for nice readability
                Collections.sort(intentMetaInfo, new Comparator<HashMap<String, String>>() {
                    @Override
                    public int compare(HashMap<String, String> map, HashMap<String, String> map2) {
                        return map.get("simpleName").compareTo(map2.get("simpleName"));
                    }
                });

                // create the custom intent list
                for (HashMap<String, String> metaInfo : intentMetaInfo) {
                    Intent targetedShareIntent = (Intent) prototype.clone();
                    targetedShareIntent.setPackage(metaInfo.get("packageName"));
                    targetedShareIntent.setClassName(metaInfo.get("packageName"), metaInfo.get("className"));
                    targetedShareIntents.add(targetedShareIntent);
                }
                chooserIntent = Intent.createChooser(targetedShareIntents.remove(targetedShareIntents.size() - 1),
                        CustomApp.context.getString(R.string.Dialog__send_file));
                chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,
                        targetedShareIntents.toArray(new Parcelable[targetedShareIntents.size()]));
                return chooserIntent;
            }
        }

        return new Intent(Intent.ACTION_SEND); //Unable to do anything. Duh.
    }

    void finish() {
        getActivity().finish();
    }
}