com.facebook.notifications.internal.asset.handlers.BitmapAssetHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.notifications.internal.asset.handlers.BitmapAssetHandler.java

Source

// Copyright (c) 2016-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

package com.facebook.notifications.internal.asset.handlers;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Parcel;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;

import com.facebook.notifications.internal.asset.Asset;
import com.facebook.notifications.internal.asset.AssetManager;
import com.facebook.notifications.internal.utilities.InvalidParcelException;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;

/**
 * Handles assets of the bitmap type
 */
public class BitmapAssetHandler implements AssetManager.AssetHandler<BitmapAssetHandler.BitmapAsset> {
    /**
     * A resource implementation for Bitmaps read from disk
     */
    static class BitmapAsset implements Asset {
        public static final Creator<BitmapAsset> CREATOR = new Creator<BitmapAsset>() {
            @Override
            public BitmapAsset createFromParcel(Parcel source) {
                return new BitmapAsset(source);
            }

            @Override
            public BitmapAsset[] newArray(int size) {
                return new BitmapAsset[size];
            }
        };
        private final @NonNull File createdFrom;
        private transient @Nullable Bitmap bitmap;

        private BitmapAsset(@NonNull File createdFrom) {
            this.createdFrom = createdFrom;
        }

        private BitmapAsset(@NonNull Parcel parcel) {
            createdFrom = new File(parcel.readString());
        }

        @Nullable
        private static Bitmap decodeBitmap(@NonNull File file) {
            try {
                // NOTE: We must be careful when decoding images on android. If a malicious push sends down
                // a payload image that is too large for us to reasonably decode, we must ensure that we can
                // safely fall back to a lower resolution if we don't have the memory for it.
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize = 1;

                while (true) {
                    InputStream cachedData = new FileInputStream(file);

                    try {
                        return BitmapFactory.decodeStream(cachedData, null, options);
                    } catch (OutOfMemoryError ex) {
                        // Ignore out of memory, try loading with less requested resolution.
                        System.gc();
                        options.inSampleSize *= 2;
                    } finally {
                        cachedData.close();
                    }
                }
            } catch (IOException ex) {
                Log.e(LOG_TAG, "IO Exception!", ex);
                return null;
            }
        }

        @NonNull
        public File getCreatedFrom() {
            return createdFrom;
        }

        @NonNull
        public Bitmap getBitmap() {
            if (bitmap == null) {
                bitmap = decodeBitmap(createdFrom);
                if (bitmap == null) {
                    throw new RuntimeException("Failed to decode bitmap from file");
                }
            }
            return bitmap;
        }

        @NonNull
        @Override
        public String getType() {
            return TYPE;
        }

        @Override
        public void validate() throws InvalidParcelException {
            if (!createdFrom.exists()) {
                throw new InvalidParcelException(new FileNotFoundException(
                        "Bitmap cache file does not exist: " + createdFrom.getAbsolutePath()));
            }
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(createdFrom.getAbsolutePath());
        }
    }

    public static final String TYPE = "Image";
    private static final String LOG_TAG = BitmapAssetHandler.class.getCanonicalName();

    @Nullable
    @Override
    public Set<URL> getCacheURLs(@NonNull JSONObject payload) {
        try {
            URL url = new URL(payload.getString("url"));
            Set<URL> set = new HashSet<>();
            set.add(url);

            return set;
        } catch (MalformedURLException ex) {
            return null;
        } catch (JSONException ex) {
            return null;
        }
    }

    @Nullable
    @Override
    public BitmapAsset createAsset(@NonNull JSONObject payload, @NonNull AssetManager.AssetCache cache) {
        try {
            URL url = new URL(payload.getString("url"));
            File cacheFile = cache.getCachedFile(url);
            if (cacheFile == null) {
                return null;
            }

            return new BitmapAsset(cacheFile);
        } catch (MalformedURLException ex) {
            Log.e(LOG_TAG, "JSON key 'url' was not a valid URL", ex);
            return null;
        } catch (JSONException ex) {
            Log.e(LOG_TAG, "JSON exception", ex);
            return null;
        }
    }

    @NonNull
    @Override
    public View createView(@NonNull BitmapAsset asset, @NonNull Context context) {
        ImageView imageView = new ImageView(context);
        imageView.setImageBitmap(asset.getBitmap());
        imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
        imageView.setAdjustViewBounds(true);

        return imageView;
    }
}