com.frostwire.android.MediaScanner.java Source code

Java tutorial

Introduction

Here is the source code for com.frostwire.android.MediaScanner.java

Source

/*
 * Created by Angel Leon (@gubatron), Alden Torres (aldenml)
 * Copyright (c) 2011-2016, FrostWire(R). All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.frostwire.android;

import android.content.Context;
import android.database.Cursor;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.SystemClock;

import com.frostwire.util.Logger;
import com.frostwire.util.Ref;

import org.apache.commons.io.IOUtils;

import java.lang.ref.WeakReference;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * @author gubatron
 * @author aldenml
 */
final class MediaScanner {

    private static final Logger LOG = Logger.getLogger(MediaScanner.class);

    public static void scanFiles(Context context, List<String> paths) {
        scanFiles(context, paths, 6);
    }

    private static void scanFiles(final Context context, List<String> paths, int retries) {
        if (paths.size() == 0) {
            return;
        }

        LOG.info("About to scan files n: " + paths.size() + ", retries: " + retries);

        final LinkedList<String> failedPaths = new LinkedList<>();

        final CountDownLatch finishSignal = new CountDownLatch(paths.size());

        MediaScannerConnection.scanFile(context, paths.toArray(new String[0]), null, (path, uri) -> {
            try {
                boolean success = true;
                if (uri == null) {
                    success = false;
                    failedPaths.add(path);
                } else {
                    // verify the stored size four faulty scan
                    long size = getSize(context, uri);
                    if (size == 0) {
                        LOG.warn("Scan returned an uri but stored size is 0, path: " + path + ", uri:" + uri);
                        success = false;
                        failedPaths.add(path);
                    }
                }
                if (!success) {
                    LOG.info("Scan failed for path: " + path + ", uri: " + uri);
                }
            } finally {
                finishSignal.countDown();
            }
        });

        try {
            finishSignal.await(10, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            // ignore
        }

        if (failedPaths.size() > 0 && retries > 0) {
            // didn't want to do this, but there is a serious timing issue with the SD
            // and storage in general
            SystemClock.sleep(2000);
            scanFiles(context, failedPaths, retries - 1);
        }
    }

    private static long getSize(Context context, Uri uri) {
        Cursor c = null;
        try {
            c = context.getContentResolver().query(uri, new String[] { "_size" }, null, null, null);

            if (c != null && c.moveToFirst()) {
                return c.getLong(0);
            }
        } catch (Throwable e) {
            LOG.error("Error getting file size for uri: " + uri, e);
        } finally {
            IOUtils.closeQuietly(c);
        }

        return 0;
    }
}