com.mikimedia.android.component.PicassoHandle.java Source code

Java tutorial

Introduction

Here is the source code for com.mikimedia.android.component.PicassoHandle.java

Source

/*
 *
 *  * Copyright (c) 2015. The MikiMedia Inc
 *  *
 *  * 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 com.mikimedia.android.component;

import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.os.Environment;
import android.os.StatFs;
import android.support.v4.content.ContextCompat;
import android.widget.ImageView;

import com.squareup.picasso.LruCache;
import com.squareup.picasso.OkHttpDownloader;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.Target;
import com.squareup.picasso.Transformation;

import java.io.File;

import javax.xml.transform.Transformer;

import static android.content.Context.ACTIVITY_SERVICE;
import static android.content.pm.ApplicationInfo.FLAG_LARGE_HEAP;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.Build.VERSION_CODES.HONEYCOMB;

/**
 * Picasso singleton to get access to the cache
 */
public abstract class PicassoHandle {

    protected static String STORAGE_LOCATION;
    protected static int ONLOADING_DRAWABLE_RESID;
    protected static int ONERROR_DRAWABLE_RESID;

    private static final File getDiskStorageLocation() {
        String path = Environment.getExternalStorageDirectory().toString() + STORAGE_LOCATION;
        return new File(path);
    }

    private final Picasso picasso;

    private final BitmapDrawable onLoadDrawable;

    private final BitmapDrawable onErrorDrawable;

    public BitmapDrawable getOnErrorDrawable() {
        return onErrorDrawable;
    }

    private static void checkPermissionsOrThrowException(Context context) {
        String[] permissions = new String[] { android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
                android.Manifest.permission.INTERNET, android.Manifest.permission.ACCESS_NETWORK_STATE };

        for (String permission : permissions) {
            int result = context.checkCallingOrSelfPermission(permission);
            if (result != PackageManager.PERMISSION_GRANTED) {
                throw new RuntimeException("Error: PicassoHandle permissions required: " + permission);
            }
        }
    }

    protected PicassoHandle(Context context) {
        checkPermissionsOrThrowException(context);

        this.onErrorDrawable = (BitmapDrawable) ContextCompat.getDrawable(context, ONERROR_DRAWABLE_RESID);
        this.onLoadDrawable = (BitmapDrawable) ContextCompat.getDrawable(context, ONLOADING_DRAWABLE_RESID);

        this.picasso = new Picasso.Builder(context).memoryCache((manager = new CacheManager(context)).cache)
                .downloader(OkHttpFactory.create()).build();
        this.picasso.setIndicatorsEnabled(false);
    }

    private final CacheManager manager;

    public CacheManager getCacheManager() {
        return this.manager;
    }

    public void loadTransform(String path, Target target, Transformation transformer) {
        picasso.load(path).placeholder(onLoadDrawable).error(onErrorDrawable).transform(transformer).into(target);
    }

    public void loadResize(String path, Target target, Point size) {
        picasso.load(path).placeholder(onLoadDrawable).error(onErrorDrawable).resize(size.x, size.y).centerCrop()
                .into(target);
    }

    public void load(String path, Target target) {
        picasso.load(path).placeholder(onLoadDrawable).error(onErrorDrawable).into(target);
    }

    public void load(String path, ImageView target) {
        picasso.load(path).placeholder(onLoadDrawable).error(onErrorDrawable).into(target);
    }

    //TODO : load the image url with a callback to a callback method/class
    // http://stackoverflow.com/questions/22143157/android-picasso-placeholder-and-error-image-styling
    //    Picasso.with(context)
    //            .load(imageUrl)
    //    .into(myImage,  new ImageLoadedCallback(progressBar) {
    //        @Override
    //        public void onSuccess() {
    //            if (this.progressBar != null) {
    //                this.progressBar.setVisibility(View.GONE);
    //            }
    //        }
    //    });

    public static final class CacheManager {

        private final LruCache cache;

        private CacheManager(Context context) {
            this.cache = new LruCache(calculateMemoryCacheSize(context));
        }

        // in bytes
        public int maxSizeRAM() {
            return cache.maxSize();
        }

        // in bytes
        public int usedSizeRAM() {
            return cache.size();
        }

        // clear mem
        public void clearRAM() {
            cache.clear();
        }

        public long usedSizeDISK() {
            return sizeOf(getDiskStorageLocation());
        }

        public boolean clearDISK() {
            return delete(getDiskStorageLocation());
        }

        private static int calculateMemoryCacheSize(Context context) {
            ActivityManager am = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
            boolean largeHeap = (context.getApplicationInfo().flags & FLAG_LARGE_HEAP) != 0;
            int memoryClass;
            if (largeHeap && SDK_INT >= HONEYCOMB) {
                memoryClass = am.getLargeMemoryClass();
            } else {
                memoryClass = am.getMemoryClass();
            }
            // Target ~15% of the available heap.
            return 1024 * 1024 * memoryClass / 7;
        }

        private static long sizeOf(File directory) {
            if (directory.exists()) {
                final File[] files = directory.listFiles();
                if (files == null) { // null if security restricted
                    return 0L;
                }
                long result = 0;
                for (int i = 0; i < files.length; i++) {
                    // Recursive call if it's a directory
                    if (files[i].isDirectory()) {
                        result += sizeOf(files[i]);
                    } else {
                        // Sum the file size in bytes
                        result += files[i].length();
                    }
                }
                return result; // return the file size
            }
            return 0;
        }

        private static boolean delete(File directory) {
            if (directory.exists()) {
                final File[] files = directory.listFiles();
                if (files == null) { // null if security restricted
                    return false;
                }

                boolean success;
                for (int i = 0; i < files.length; i++) {
                    // Recursive call if it's a directory
                    if (files[i].isDirectory()) {
                        success = delete(files[i]);
                    } else {
                        success = files[i].delete();
                    }
                    if (!success)
                        return false; // stop the whole process
                }

                return true;
            }
            return false;
        }

    }

    // to create the cache
    private static final class OkHttpFactory {

        private static final int MIN_DISK_CACHE_SIZE = 5 * 1024 * 1024; // 5MB
        private static final int MAX_DISK_CACHE_SIZE = 50 * 1024 * 1024; // 50MB

        private static OkHttpDownloader create() {
            File cacheDir = getDiskStorageLocation();
            return new OkHttpDownloader(cacheDir, calculateDiskCacheSize(cacheDir));
        }

        private static long calculateDiskCacheSize(File dir) {
            long size = MIN_DISK_CACHE_SIZE;

            try {
                StatFs statFs = new StatFs(dir.getAbsolutePath());
                long available = ((long) statFs.getBlockCount()) * statFs.getBlockSize();
                // Target 2% of the total space.
                size = available / 50;
            } catch (IllegalArgumentException ignored) {
            }

            // Bound inside min/max size for disk cache.
            return Math.max(Math.min(size, MAX_DISK_CACHE_SIZE), MIN_DISK_CACHE_SIZE);
        }

        //        EXAMPLE NEED PASSWORD AUTHENTICATION ETC IN HEADERS
        //        REF: http://stackoverflow.com/questions/24981469/custom-downloader-using-picasso
        //
        //        public static Picasso getImageLoader(Context ctx) {
        //            Picasso.Builder builder = new Picasso.Builder(ctx);
        //
        //            builder.downloader(new UrlConnectionDownloader(ctx) {
        //                @Override
        //                protected HttpURLConnection openConnection(Uri uri) throws IOException {
        //                    HttpURLConnection connection = super.openConnection(uri);
        //                    connection.setRequestProperty("X-HEADER", "VAL");
        //                    return connection;
        //                }
        //            });
        //
        //            return builder.build();
        //        }
        //
        //        OkHttpClient picassoClient = OkHttpClient();
        //
        //        picassoClient.interceptors().add(new Interceptor() {
        //            @Override
        //            public Response intercept(Chain chain) throws IOException {
        //                Request newRequest = chain.request().newBuilder()
        //                        .addHeader("X-HEADER", "VAL")
        //                        .build();
        //                return chain.proceed(newRequest);
        //            }
        //        });
        //
        //        new Picasso.Builder(context).downloader(new OkHttpDownloader(picassoClient)).build();

    }

}