/*
* Copyright 2015 Google Inc. All rights reserved.
*
* 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.google.samples.apps.iosched.map.util;
import com.google.samples.apps.iosched.provider.ScheduleContract;
import com.google.samples.apps.iosched.util.MapUtils;
import com.jakewharton.disklrucache.DiskLruCache;
import android.content.AsyncTaskLoader;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static com.google.samples.apps.iosched.util.LogUtils.LOGD;
import static com.google.samples.apps.iosched.util.LogUtils.LOGE;
import static com.google.samples.apps.iosched.util.LogUtils.makeLogTag;
/**
* Background task that queries the content provider and prepares a list of
* {@link com.google.android.gms.maps.model.TileOverlay}s
* for addition to the map.
* A tile overlay is always tied to a floor in the venue and is loaded directly from an SVG file.
* A {@link DiskLruCache} is used to create a {@link CachedTileProvider} for each overlay.
* <p>Note: The CachedTileProvider <b>must</b> be closed when the encapsulating map is stopped.
* (See
* {@link CachedTileProvider#closeCache()}
*/
public class TileLoadingTask extends AsyncTaskLoader<List<TileLoadingTask.TileEntry>> {
private static final String TAG = makeLogTag(TileLoadingTask.class);
private final float mDPI;
public TileLoadingTask(Context context, float dpi) {
super(context);
mDPI = dpi;
}
@Override
public List<TileEntry> loadInBackground() {
List<TileEntry> list = null;
// Create a URI to get a cursor for all map tile entries.
final Uri uri = ScheduleContract.MapTiles.buildUri();
Cursor cursor = getContext().getContentResolver().query(uri,
OverlayQuery.PROJECTION, null, null, null);
if (cursor != null) {
// Create a TileProvider for each entry in the cursor
final int count = cursor.getCount();
// Initialise the tile cache that is reused for all TileProviders.
// Note that the cache *MUST* be closed when the encapsulating Fragment is stopped.
DiskLruCache tileCache = MapUtils.openDiskCache(getContext());
list = new ArrayList<>(count);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
final int floor = cursor.getInt(OverlayQuery.TILE_FLOOR);
final String file = cursor.getString(OverlayQuery.TILE_FILE);
File f = MapUtils.getTileFile(getContext().getApplicationContext(), file);
if (f == null || !f.exists()) {
// Skip the file if it is invalid or does not exist.
LOGE(TAG, "Tile file not found for floor " + floor);
break;
}
CachedTileProvider provider;
try {
SVGTileProvider svgProvider = new SVGTileProvider(f, mDPI);
// Wrap the SVGTileProvider in a CachedTileProvider for caching on disk.
provider = new CachedTileProvider(Integer.toString(floor), svgProvider,
tileCache);
} catch (IOException e) {
LOGD(TAG, "Could not create Tile Provider.");
break;
}
list.add(new TileEntry(floor, provider));
cursor.moveToNext();
}
cursor.close();
}
return list;
}
private interface OverlayQuery {
String[] PROJECTION = {
ScheduleContract.MapTiles.TILE_FLOOR,
ScheduleContract.MapTiles.TILE_FILE
};
int TILE_FLOOR = 0;
int TILE_FILE = 1;
}
public class TileEntry {
public CachedTileProvider provider;
public int floor;
TileEntry(int floor, CachedTileProvider provider) {
this.floor = floor;
this.provider = provider;
}
}
}