com.andremion.louvre.data.MediaLoader.java Source code

Java tutorial

Introduction

Here is the source code for com.andremion.louvre.data.MediaLoader.java

Source

/*
 * Copyright (c) 2017. Andr Mion
 *
 * 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.andremion.louvre.data;

import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.MergeCursor;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;

import com.andremion.louvre.R;

import static com.andremion.louvre.data.MediaQuery.ALL_IMAGE_PROJECTION;
import static com.andremion.louvre.data.MediaQuery.BUCKET_PROJECTION;
import static com.andremion.louvre.data.MediaQuery.BUCKET_SELECTION;
import static com.andremion.louvre.data.MediaQuery.BUCKET_SORT_ORDER;
import static com.andremion.louvre.data.MediaQuery.GALLERY_URI;
import static com.andremion.louvre.data.MediaQuery.IMAGE_PROJECTION;
import static com.andremion.louvre.data.MediaQuery.MEDIA_SORT_ORDER;

/**
 * {@link Loader} for media and bucket data
 */
public class MediaLoader implements LoaderManager.LoaderCallbacks<Cursor> {

    private static final int TIME_LOADER = 0;
    private static final int BUCKET_LOADER = 1;
    private static final int MEDIA_LOADER = 2;

    static final long ALL_MEDIA_BUCKET_ID = 0;
    private static final String BUCKET_ID = MediaStore.Images.Media.BUCKET_ID;

    public interface Callbacks {

        void onBucketLoadFinished(@Nullable Cursor data);

        void onMediaLoadFinished(@Nullable Cursor data);
    }

    private FragmentActivity mActivity;
    private Callbacks mCallbacks;
    private String mTypeFilter;

    public MediaLoader() {
        // 1 means all media type.
        mTypeFilter = "1";
    }

    @Override
    public final Loader<Cursor> onCreateLoader(int id, Bundle args) {
        if (id == TIME_LOADER) {
            return new CursorLoader(mActivity, GALLERY_URI, ALL_IMAGE_PROJECTION, mTypeFilter, null,
                    MEDIA_SORT_ORDER);
        }
        if (id == BUCKET_LOADER) {
            return new CursorLoader(mActivity, GALLERY_URI, BUCKET_PROJECTION,
                    String.format("%s AND %s", mTypeFilter, BUCKET_SELECTION), null, BUCKET_SORT_ORDER);
        }
        // id == MEDIA_LOADER
        return new CursorLoader(
                mActivity, GALLERY_URI, IMAGE_PROJECTION, String.format("%s=%s AND %s",
                        MediaStore.Images.Media.BUCKET_ID, args.getLong(BUCKET_ID), mTypeFilter),
                null, MEDIA_SORT_ORDER);
    }

    @Override
    public final void onLoadFinished(@NonNull Loader<Cursor> loader, @Nullable Cursor data) {
        if (mCallbacks != null) {
            if (loader.getId() == BUCKET_LOADER) {
                mCallbacks.onBucketLoadFinished(addAllMediaBucketItem(data));
            } else {
                mCallbacks.onMediaLoadFinished(data);
            }
        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        // no-op
    }

    public void onAttach(@NonNull FragmentActivity activity, @NonNull Callbacks callbacks) {
        mActivity = activity;
        mCallbacks = callbacks;
    }

    public void onDetach() {
        mActivity = null;
        mCallbacks = null;
    }

    public void setMediaTypes(@NonNull String[] mediaTypes) {
        StringBuilder filter = new StringBuilder();
        for (String type : mediaTypes) {
            if (filter.length() > 0) {
                filter.append(",");
            }
            filter.append(String.format("'%s'", type));
        }
        if (filter.length() > 0) {
            mTypeFilter = MediaStore.Images.ImageColumns.MIME_TYPE + " IN (" + filter + ")";
        }
    }

    public void loadBuckets() {
        ensureActivityAttached();
        mActivity.getSupportLoaderManager().restartLoader(BUCKET_LOADER, null, this);
    }

    public void loadByBucket(@IntRange(from = 0) long bucketId) {
        ensureActivityAttached();
        if (ALL_MEDIA_BUCKET_ID == bucketId) {
            mActivity.getSupportLoaderManager().restartLoader(TIME_LOADER, null, this);
        } else {
            Bundle args = new Bundle();
            args.putLong(BUCKET_ID, bucketId);
            mActivity.getSupportLoaderManager().restartLoader(MEDIA_LOADER, args, this);
        }
    }

    /**
     * Ensure that a FragmentActivity is attached to this loader.
     */
    private void ensureActivityAttached() {
        if (mActivity == null) {
            throw new IllegalStateException("The FragmentActivity was not attached!");
        }
    }

    /**
     * Add "All Media" item as the first row of bucket items.
     *
     * @param cursor The original data of all bucket items
     * @return The data with "All Media" item added
     */
    private Cursor addAllMediaBucketItem(@Nullable Cursor cursor) {
        if (cursor == null || !cursor.moveToPosition(0)) {
            return null;
        }
        ensureActivityAttached();
        long id = ALL_MEDIA_BUCKET_ID;
        String label = mActivity.getString(R.string.activity_gallery_bucket_all_media);
        String data = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
        MatrixCursor allMediaRow = new MatrixCursor(BUCKET_PROJECTION);
        allMediaRow.newRow().add(id).add(label).add(data);
        return new MergeCursor(new Cursor[] { allMediaRow, cursor });
    }

}