com.pdftron.pdf.utils.ViewerUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.pdftron.pdf.utils.ViewerUtils.java

Source

//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2016 by PDFTron Systems Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------

package com.pdftron.pdf.utils;

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.FloatEvaluator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Build;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.webkit.MimeTypeMap;

import com.pdftron.common.PDFNetException;
import com.pdftron.pdf.Annot;
import com.pdftron.pdf.PDFDoc;
import com.pdftron.pdf.PDFViewCtrl;
import com.pdftron.pdf.Page;
import com.pdftron.pdf.Rect;
import com.pdftron.pdf.tools.R;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ViewerUtils {

    public class ImageIntent {
        public Bitmap bitmap;
        public Uri uri;
        public String filePath;
    }

    public static Uri openImageIntent(Fragment fragment, int requestCode) {
        // Determine Uri of camera image to save.
        final String fname = "IMG_" + System.currentTimeMillis() + ".jpg";
        File sdImageMainDirectory = new File(fragment.getActivity().getExternalCacheDir(), fname);
        Uri outputFileUri = Uri.fromFile(sdImageMainDirectory);

        // Camera.
        final List<Intent> cameraIntents = new ArrayList<>();
        final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        final PackageManager packageManager = fragment.getActivity().getPackageManager();
        final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);
        for (ResolveInfo res : listCam) {
            final String packageName = res.activityInfo.packageName;
            final Intent intent = new Intent(captureIntent);
            intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
            intent.setPackage(packageName);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
            cameraIntents.add(intent);
        }

        // Filesystem.
        final Intent galleryIntent = new Intent(Intent.ACTION_PICK);
        galleryIntent.setType("image/*");
        //galleryIntent.setAction(Intent.ACTION_GET_CONTENT);

        // Chooser of filesystem options.
        final Intent chooserIntent = Intent.createChooser(galleryIntent, "Select Source");

        // Add the camera options.
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[] {}));

        fragment.startActivityForResult(chooserIntent, requestCode);
        return outputFileUri;
    }

    public static Map readImageIntent(Intent data, Context context, Uri outputFileUri)
            throws FileNotFoundException, Exception {
        final boolean isCamera;
        if (data == null || data.getData() == null) {
            isCamera = true;
        } else {
            final String action = data.getAction();
            if (action == null) {
                isCamera = false;
            } else {
                isCamera = action.equals(MediaStore.ACTION_IMAGE_CAPTURE);
            }
        }

        Uri imageUri;
        if (isCamera) {
            imageUri = outputFileUri;
            AnalyticsHandlerAdapter.getInstance().sendEvent(AnalyticsHandlerAdapter.CATEGORY_FILEBROWSER,
                    "Create new document from camera selected");
        } else {
            imageUri = data.getData();
            AnalyticsHandlerAdapter.getInstance().sendEvent(AnalyticsHandlerAdapter.CATEGORY_FILEBROWSER,
                    "Create new document from local image file selected");
        }

        String filePath;
        if (isCamera) {
            filePath = imageUri.getPath();
        } else {
            filePath = Utils.getRealPathFromImageURI(context, imageUri);
            if (Utils.isNullOrEmpty(filePath)) {
                filePath = imageUri.getPath();
            }
        }

        // try to get bitmap
        Bitmap bitmap = Utils.getBitmapFromImageUri(context, imageUri, filePath);

        // if a file is selected, check if it is an image file
        if (!isCamera) {
            // if type is null
            if (context.getContentResolver().getType(imageUri) == null) {
                String extension = MimeTypeMap.getFileExtensionFromUrl(imageUri.getPath());
                final String[] extensions = { "jpeg", "jpg", "tiff", "tif", "gif", "png", "bmp" };

                // if file extension is not an image extension
                if (!Arrays.asList(extensions).contains(extension) && extension != null && !extension.equals("")) {
                    throw new FileNotFoundException("file extension is not an image extension");
                }
                // if type is not an image
            } else if (!context.getContentResolver().getType(imageUri).startsWith("image/")) {
                throw new FileNotFoundException("type is not an image");
            }
        }

        //////////////////  Determine if image needs to be rotated   ///////////////////
        File imageFile = new File(imageUri.getPath());
        ExifInterface exif = new ExifInterface(imageFile.getAbsolutePath());
        int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);

        int imageRotation = 0;
        switch (orientation) {
        case ExifInterface.ORIENTATION_ROTATE_270:
            imageRotation = 270;
            break;
        case ExifInterface.ORIENTATION_ROTATE_180:
            imageRotation = 180;
            break;
        case ExifInterface.ORIENTATION_ROTATE_90:
            imageRotation = 90;
            break;
        }

        // in some devices (mainly Samsung), the EXIF is not saved with the image so look at the content
        // resolver as a second source of the image's rotation
        if (imageRotation == 0) {
            String[] orientationColumn = { MediaStore.Images.Media.ORIENTATION };
            Cursor cur = context.getContentResolver().query(imageUri, orientationColumn, null, null, null);
            orientation = -1;
            if (cur != null && cur.moveToFirst()) {
                orientation = cur.getInt(cur.getColumnIndex(orientationColumn[0]));
            }

            if (orientation > 0) {
                imageRotation = orientation;
            }
        }

        if (imageRotation != 0) {
            Matrix matrix = new Matrix();
            matrix.postRotate(imageRotation);
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        }

        Map<String, Object> output = new HashMap<>();
        output.put("bitmap", bitmap);
        output.put("uri", imageUri);
        output.put("path", filePath);
        output.put("camera", isCamera);
        return output;
    }

    public static boolean checkIntent(Map map) {
        if (map == null || map.get("bitmap") == null || !(map.get("bitmap") instanceof Bitmap)
                || map.get("path") == null || !(map.get("path") instanceof String) || map.get("uri") == null
                || !(map.get("uri") instanceof Uri) || map.get("camera") == null
                || !(map.get("camera") instanceof Boolean)) {
            return false;
        }
        return true;
    }

    /**
     * Helper method that creates a flashing view.
     *
     * @param context the context
     *
     * @return a new View with the background color already set.
     */
    public static View createFlashingView(Context context) {
        View flashingView = new View(context);
        flashingView.setBackgroundColor(context.getResources().getColor(R.color.annotation_flashing_box));
        return flashingView;
    }

    public static void jumpToAnnotation(PDFViewCtrl pdfViewCtrl, Annot annot, int pageNum) {
        pdfViewCtrl.setCurrentPage(pageNum);

        // Now add the flashing view on top of the selected annotation
        View flashingView = createFlashingView(pdfViewCtrl.getContext());
        // Get the annotation bounding box
        double[] pts1 = new double[] { 0.0f, 0.0f };
        double[] pts2 = new double[] { 0.0f, 0.0f };
        // Note that the returned Rect from the Annot object is in
        // page space, so we need to convert the points to screen
        // space before using them in the view layout.
        try {
            Rect annotRect = annot.getRect();
            // Lower left corner
            pts1 = pdfViewCtrl.convPagePtToScreenPt(annotRect.getX1(), annotRect.getY1(), pageNum);
            // Upper right corner
            pts2 = pdfViewCtrl.convPagePtToScreenPt(annotRect.getX2(), annotRect.getY2(), pageNum);
        } catch (PDFNetException e) {
            com.pdftron.pdf.utils.AnalyticsHandlerAdapter.getInstance().sendException(e);
        }
        // [start] adjusting position so that the annotation shows up in the middle of the screen
        double top = pts2[1];
        double bottom = pts1[1];
        if (pdfViewCtrl.getPagePresentationMode() == PDFViewCtrl.PAGE_PRESENTATION_SINGLE_CONT
                || pdfViewCtrl.getPagePresentationMode() == PDFViewCtrl.PAGE_PRESENTATION_FACING_CONT
                || pdfViewCtrl.getPagePresentationMode() == PDFViewCtrl.PAGE_PRESENTATION_FACING_COVER_CONT) {
            int screenMidY = pdfViewCtrl.getHeight() / 2;
            double height = Math.abs(pts1[1] - pts2[1]);
            double verticalOffset = pts2[1];
            if (pdfViewCtrl.getScrollY() > verticalOffset) {
                top = screenMidY;
                bottom = screenMidY + height;
            }
            double diff = pts2[1] - top;
            pdfViewCtrl.scrollBy(0, (int) diff);
        }
        // [end]
        // We also need to get the current scrolling position
        // in case the viewer is currently scrolled
        float sx = pdfViewCtrl.getScrollX();
        float sy = pdfViewCtrl.getScrollY();
        // The following deal with rotated pages
        int flashingRectLeft = (int) (pts1[0] + sx);
        int flashingRectTop = (int) (top + sy);
        int flashingRectRight = (int) (pts2[0] + sx);
        int flashingRectBottom = (int) (bottom + sy);
        try {
            Rect flashingRect = new Rect(pts1[0] + sx, top + sy, pts2[0] + sx, bottom + sy);
            flashingRect.normalize();

            flashingRectLeft = (int) flashingRect.getX1();
            flashingRectTop = (int) flashingRect.getY1();
            flashingRectRight = (int) flashingRect.getX2();
            flashingRectBottom = (int) flashingRect.getY2();
        } catch (PDFNetException ex) {
        }

        // Set the layout of the view (note that top/bottom are
        // inverted since in page space the lower-left corner
        // is the origin
        flashingView.layout(flashingRectLeft, flashingRectTop, flashingRectRight, flashingRectBottom);
        pdfViewCtrl.addView(flashingView);

        // And finally animate the flashing view
        animateView(flashingView, pdfViewCtrl);
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public static void animateView(final View view, final PDFViewCtrl pdfViewCtrl) {
        // Example of another animation that could be applied to the view.
        //ValueAnimator colorAnim = ObjectAnimator.ofInt(view, "backgroundColor", /*Red*/0xFFFF8080, /*Blue*/0xFF8080FF);
        //colorAnim.setDuration(1500);
        //colorAnim.setEvaluator(new ArgbEvaluator());
        //colorAnim.setRepeatCount(2);
        //colorAnim.setRepeatMode(ValueAnimator.REVERSE);

        // Honeycomb introduced new Animation classes that are easier to use
        // and provide more options. Let's do a runtime check here and use
        // older classes for pre-Honeycomb devices.
        if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) {
            AlphaAnimation anim1 = new AlphaAnimation(0.0f, 1.0f);
            final AlphaAnimation anim2 = new AlphaAnimation(1.0f, 0.0f);
            anim1.setDuration(500);
            anim2.setDuration(500);
            anim1.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                }

                @Override
                public void onAnimationRepeat(Animation animation) {
                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    view.startAnimation(anim2);
                }
            });
            anim2.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                }

                @Override
                public void onAnimationRepeat(Animation animation) {
                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    if (pdfViewCtrl != null) {
                        pdfViewCtrl.removeView(view);
                    }
                }
            });
            view.startAnimation(anim1);

        } else {
            // Since we want the flashing view to be removed once the animation
            // is finished, we use this listener to remove the view from
            // PDFViewCtrl when the event is triggered.
            Animator.AnimatorListener animListener = new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
                }

                @Override
                public void onAnimationRepeat(Animator animation) {
                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    pdfViewCtrl.removeView(view);
                }

                @Override
                public void onAnimationCancel(Animator animation) {
                }
            };

            // Get animator for the flashing view.
            Animator fader = createAlphaAnimator(view, animListener);

            // If using more than one animator, you can create a set and
            // play them together, or in some other order...
            AnimatorSet animation = new AnimatorSet();
            animation.playTogether(/*colorAnim, */fader);
            animation.start();
        }
    }

    /**
     * Creates an Animator object that varies the alpha property of the view. The
     * interpolation used is linear.
     *
     * @param view the view to be animated
     * @param listener the listener to be used by this Animator
     *
     * @return a new Animator object that will change the "alpha" property
     * of the view.
     */
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public static Animator createAlphaAnimator(View view, Animator.AnimatorListener listener) {
        if (view == null) {
            return null;
        }
        // We animate only the opacity of the view.
        ValueAnimator fader = ObjectAnimator.ofFloat(view, "alpha", 0.0f, 1.0f, 0.4f, 1.0f, 0.0f);
        fader.setDuration(1500);
        fader.setEvaluator(new FloatEvaluator());
        if (listener != null) {
            fader.addListener(listener);
        }
        return fader;
    }

    public static Annot getAnnotById(PDFDoc doc, String id, int pageNum) {
        try {
            Page page = doc.getPage(pageNum);
            if (page.isValid()) {
                int annotationCount = page.getNumAnnots();
                for (int a = 0; a < annotationCount; a++) {

                    Annot annotation = page.getAnnot(a);
                    if (annotation != null && annotation.isValid() && annotation.getUniqueID() != null) {
                        String annotId = annotation.getUniqueID().getAsPDFText();
                        if (id.equals(annotId)) {
                            return annotation;
                        }
                    }
                }
            }

        } catch (Exception e) {
            AnalyticsHandlerAdapter.getInstance().sendException(e);
        }
        return null;
    }
}