com.android.gallery3d2.ingest.IngestService.java Source code

Java tutorial

Introduction

Here is the source code for com.android.gallery3d2.ingest.IngestService.java

Source

/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * 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.android.gallery3d2.ingest;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.MediaScannerConnection;
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
import android.mtp.MtpDevice;
import android.mtp.MtpDeviceInfo;
import android.mtp.MtpObjectInfo;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
import android.util.SparseBooleanArray;
import android.widget.Adapter;

import com.android.gallery3d2.R;
import com.android.gallery3d2.app.NotificationIds;
import com.android.gallery3d2.data.MtpClient;
import com.android.gallery3d2.util.BucketNames;
import com.android.gallery3d2.util.UsageStatistics;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class IngestService extends Service
        implements ImportTask.Listener, MtpDeviceIndex.ProgressListener, MtpClient.Listener {

    public class LocalBinder extends Binder {
        IngestService getService() {
            return IngestService.this;
        }
    }

    private static final int PROGRESS_UPDATE_INTERVAL_MS = 180;

    private static MtpClient sClient;

    private final IBinder mBinder = new LocalBinder();
    private ScannerClient mScannerClient;
    private MtpDevice mDevice;
    private String mDevicePrettyName;
    private MtpDeviceIndex mIndex;
    private IngestActivity mClientActivity;
    private boolean mRedeliverImportFinish = false;
    private int mRedeliverImportFinishCount = 0;
    private Collection<MtpObjectInfo> mRedeliverObjectsNotImported;
    private boolean mRedeliverNotifyIndexChanged = false;
    private boolean mRedeliverIndexFinish = false;
    private NotificationManager mNotificationManager;
    private NotificationCompat.Builder mNotificationBuilder;
    private long mLastProgressIndexTime = 0;
    private boolean mNeedRelaunchNotification = false;

    @Override
    public void onCreate() {
        super.onCreate();
        mScannerClient = new ScannerClient(this);
        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        mNotificationBuilder = new NotificationCompat.Builder(this);
        mNotificationBuilder.setSmallIcon(android.R.drawable.stat_notify_sync) // TODO drawable
                .setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, IngestActivity.class), 0));
        mIndex = MtpDeviceIndex.getInstance();
        mIndex.setProgressListener(this);

        if (sClient == null) {
            sClient = new MtpClient(getApplicationContext());
        }
        List<MtpDevice> devices = sClient.getDeviceList();
        if (devices.size() > 0) {
            setDevice(devices.get(0));
        }
        sClient.addListener(this);
    }

    @Override
    public void onDestroy() {
        sClient.removeListener(this);
        mIndex.unsetProgressListener(this);
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    private void setDevice(MtpDevice device) {
        if (mDevice == device)
            return;
        mRedeliverImportFinish = false;
        mRedeliverObjectsNotImported = null;
        mRedeliverNotifyIndexChanged = false;
        mRedeliverIndexFinish = false;
        mDevice = device;
        mIndex.setDevice(mDevice);
        if (mDevice != null) {
            MtpDeviceInfo deviceInfo = mDevice.getDeviceInfo();
            if (deviceInfo == null) {
                setDevice(null);
                return;
            } else {
                mDevicePrettyName = deviceInfo.getModel();
                mNotificationBuilder.setContentTitle(mDevicePrettyName);
                new Thread(mIndex.getIndexRunnable()).start();
            }
        } else {
            mDevicePrettyName = null;
        }
        if (mClientActivity != null) {
            mClientActivity.notifyIndexChanged();
        } else {
            mRedeliverNotifyIndexChanged = true;
        }
    }

    protected MtpDeviceIndex getIndex() {
        return mIndex;
    }

    protected void setClientActivity(IngestActivity activity) {
        if (mClientActivity == activity)
            return;
        mClientActivity = activity;
        if (mClientActivity == null) {
            if (mNeedRelaunchNotification) {
                mNotificationBuilder.setProgress(0, 0, false)
                        .setContentText(getResources().getText(R.string.ingest_scanning_done));
                mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_SCANNING,
                        mNotificationBuilder.build());
            }
            return;
        }
        mNotificationManager.cancel(NotificationIds.INGEST_NOTIFICATION_IMPORTING);
        mNotificationManager.cancel(NotificationIds.INGEST_NOTIFICATION_SCANNING);
        if (mRedeliverImportFinish) {
            mClientActivity.onImportFinish(mRedeliverObjectsNotImported, mRedeliverImportFinishCount);
            mRedeliverImportFinish = false;
            mRedeliverObjectsNotImported = null;
        }
        if (mRedeliverNotifyIndexChanged) {
            mClientActivity.notifyIndexChanged();
            mRedeliverNotifyIndexChanged = false;
        }
        if (mRedeliverIndexFinish) {
            mClientActivity.onIndexFinish();
            mRedeliverIndexFinish = false;
        }
    }

    protected void importSelectedItems(SparseBooleanArray selected, Adapter adapter) {
        List<MtpObjectInfo> importHandles = new ArrayList<MtpObjectInfo>();
        for (int i = 0; i < selected.size(); i++) {
            if (selected.valueAt(i)) {
                Object item = adapter.getItem(selected.keyAt(i));
                if (item instanceof MtpObjectInfo) {
                    importHandles.add(((MtpObjectInfo) item));
                }
            }
        }
        ImportTask task = new ImportTask(mDevice, importHandles, BucketNames.IMPORTED, this);
        task.setListener(this);
        mNotificationBuilder.setProgress(0, 0, true)
                .setContentText(getResources().getText(R.string.ingest_importing));
        startForeground(NotificationIds.INGEST_NOTIFICATION_IMPORTING, mNotificationBuilder.build());
        new Thread(task).start();
    }

    @Override
    public void deviceAdded(MtpDevice device) {
        if (mDevice == null) {
            setDevice(device);
            UsageStatistics.onEvent(UsageStatistics.COMPONENT_IMPORTER, "DeviceConnected", null);
        }
    }

    @Override
    public void deviceRemoved(MtpDevice device) {
        if (device == mDevice) {
            setDevice(null);
            mNeedRelaunchNotification = false;
            mNotificationManager.cancel(NotificationIds.INGEST_NOTIFICATION_SCANNING);
        }
    }

    @Override
    public void onImportProgress(int visitedCount, int totalCount, String pathIfSuccessful) {
        if (pathIfSuccessful != null) {
            mScannerClient.scanPath(pathIfSuccessful);
        }
        mNeedRelaunchNotification = false;
        if (mClientActivity != null) {
            mClientActivity.onImportProgress(visitedCount, totalCount, pathIfSuccessful);
        }
        mNotificationBuilder.setProgress(totalCount, visitedCount, false)
                .setContentText(getResources().getText(R.string.ingest_importing));
        mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_IMPORTING, mNotificationBuilder.build());
    }

    @Override
    public void onImportFinish(Collection<MtpObjectInfo> objectsNotImported, int visitedCount) {
        stopForeground(true);
        mNeedRelaunchNotification = true;
        if (mClientActivity != null) {
            mClientActivity.onImportFinish(objectsNotImported, visitedCount);
        } else {
            mRedeliverImportFinish = true;
            mRedeliverObjectsNotImported = objectsNotImported;
            mRedeliverImportFinishCount = visitedCount;
            mNotificationBuilder.setProgress(0, 0, false)
                    .setContentText(getResources().getText(R.string.import_complete));
            mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_IMPORTING,
                    mNotificationBuilder.build());
        }
        UsageStatistics.onEvent(UsageStatistics.COMPONENT_IMPORTER, "ImportFinished", null, visitedCount);
    }

    @Override
    public void onObjectIndexed(MtpObjectInfo object, int numVisited) {
        mNeedRelaunchNotification = false;
        if (mClientActivity != null) {
            mClientActivity.onObjectIndexed(object, numVisited);
        } else {
            // Throttle the updates to one every PROGRESS_UPDATE_INTERVAL_MS milliseconds
            long currentTime = SystemClock.uptimeMillis();
            if (currentTime > mLastProgressIndexTime + PROGRESS_UPDATE_INTERVAL_MS) {
                mLastProgressIndexTime = currentTime;
                mNotificationBuilder.setProgress(0, numVisited, true)
                        .setContentText(getResources().getText(R.string.ingest_scanning));
                mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_SCANNING,
                        mNotificationBuilder.build());
            }
        }
    }

    @Override
    public void onSorting() {
        if (mClientActivity != null)
            mClientActivity.onSorting();
    }

    @Override
    public void onIndexFinish() {
        mNeedRelaunchNotification = true;
        if (mClientActivity != null) {
            mClientActivity.onIndexFinish();
        } else {
            mNotificationBuilder.setProgress(0, 0, false)
                    .setContentText(getResources().getText(R.string.ingest_scanning_done));
            mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_SCANNING, mNotificationBuilder.build());
            mRedeliverIndexFinish = true;
        }
    }

    // Copied from old Gallery3d code
    private static final class ScannerClient implements MediaScannerConnectionClient {
        ArrayList<String> mPaths = new ArrayList<String>();
        MediaScannerConnection mScannerConnection;
        boolean mConnected;
        Object mLock = new Object();

        public ScannerClient(Context context) {
            mScannerConnection = new MediaScannerConnection(context, this);
        }

        public void scanPath(String path) {
            synchronized (mLock) {
                if (mConnected) {
                    mScannerConnection.scanFile(path, null);
                } else {
                    mPaths.add(path);
                    mScannerConnection.connect();
                }
            }
        }

        @Override
        public void onMediaScannerConnected() {
            synchronized (mLock) {
                mConnected = true;
                if (!mPaths.isEmpty()) {
                    for (String path : mPaths) {
                        mScannerConnection.scanFile(path, null);
                    }
                    mPaths.clear();
                }
            }
        }

        @Override
        public void onScanCompleted(String path, Uri uri) {
        }
    }
}