it.tidalwave.mobile.android.asset.AndroidSmartAssetManager Maven / Gradle / Ivy
/***********************************************************************************************************************
*
* blueBill Mobile - Android - open source birding
* Copyright (C) 2009-2011 by Tidalwave s.a.s. (http://www.tidalwave.it)
*
***********************************************************************************************************************
*
* 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.
*
***********************************************************************************************************************
*
* WWW: http://bluebill.tidalwave.it/mobile
* SCM: https://java.net/hg/bluebill-mobile~android-src
*
**********************************************************************************************************************/
package it.tidalwave.mobile.android.asset;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.inject.Provider;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilterInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import it.tidalwave.netbeans.util.Locator;
import it.tidalwave.mobile.io.IoUtils;
import it.tidalwave.mobile.io.MasterFileSystem;
import it.tidalwave.mobile.asset.SmartAssetManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import android.content.res.AssetManager;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import lombok.Cleanup;
/***********************************************************************************************************************
*
* @author Fabrizio Giudici
* @version $Id$
*
**********************************************************************************************************************/
public class AndroidSmartAssetManager implements SmartAssetManager
{
private static final Logger log = LoggerFactory.getLogger(AndroidSmartAssetManager.class);
private final String basePath;
private final Provider masterFileSystem = Locator.createProviderFor(MasterFileSystem.class);
private final Provider assetManager = Locator.createProviderFor(AssetManager.class);
private boolean forceReload = false;
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
public AndroidSmartAssetManager()
throws NameNotFoundException
{
final Context context = Locator.find(Context.class);
final PackageManager packageManager = context.getPackageManager();
final PackageInfo info = packageManager.getPackageInfo(context.getPackageName(), 0);
basePath = "assets/" + info.versionName;
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
@Nonnull
public File findAsset (final @Nonnull String fileName)
throws IOException
{
final File folder = masterFileSystem.get().getExternalFileSystem().getFile(basePath);
final File file = new File(folder, fileName);
if (!file.exists())
{
throw new FileNotFoundException(fileName);
}
return file;
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
class ProgressInputStream extends FilterInputStream
{
@Nonnegative
private final long size;
private long done;
private final ProgressListener progressListener;
public ProgressInputStream (final @Nonnull InputStream in,
final @Nonnull ProgressListener progressListener,
final @Nonnegative long size)
{
super(in);
this.progressListener = progressListener;
this.size = size;
}
@Override
public int read() throws IOException
{
progress(1);
return super.read();
}
@Override
public int read (byte[] bytes, int i, int i1) throws IOException
{
final int n = super.read(bytes, i, i1);
progress(n);
return n;
}
private void progress (final @Nonnegative int step)
{
done += step;
progressListener.notifyProgress((int)((100 * done) / size), done);
}
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
public void installAsset (final @Nonnull String fileName)
throws IOException
{
installAsset(fileName, ProgressListener.DEFAULT);
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
public void installAsset (final @Nonnull String fileName, final @Nonnull ProgressListener progressListener)
throws IOException
{
File targetFile = null;
try
{
log.info("installAsset({})", fileName);
final long time = System.currentTimeMillis();
final long length = assetManager.get().openFd(fileName).getLength();
final File folder = masterFileSystem.get().getExternalFileSystem().getFile(basePath);
folder.mkdirs();
targetFile = new File(folder, fileName);
if (targetFile.exists() && !forceReload)
{
log.info(">>>> already exists at {} ...", targetFile);
}
else
{
// TODO: consistency check on the copied file (size)
log.info(">>>> copying to {} ...", targetFile);
@Cleanup final ProgressInputStream is = new ProgressInputStream(assetManager.get().open(fileName), progressListener, length);
@Cleanup final OutputStream os = new FileOutputStream(targetFile);
IoUtils.copy(is, os);
log.debug(">>>> copied in {} msec", System.currentTimeMillis() - time);
// TODO: consistency check on the copied file (size)
// Recall that if the resource has been erroneously packed, it will be truncated at 1MB
// TODO: drive the progress bar with the real progress
}
}
catch (IOException e)
{
log.error("Cannot copy {} ({}) - removing partial data...", fileName, e.toString());
log.error("", e);
if (targetFile != null)
{
targetFile.delete();
}
throw new IOException("Couldn't install asset " + fileName + " because of " + e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy