/** * OpenAtlasForAndroid Project * <p> * The MIT License (MIT) * Copyright (c) 2015 Bunny Blue * <p> * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to the following conditions: * <p> * The above copyright notice and this permission notice shall be included in all copies * or substantial portions of the Software. * <p> * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * @author BunnyBlue */ package com.openatlas.android.initializer; import android.app.Application; import android.os.Environment; import android.os.Handler; import android.os.Looper; import android.os.StatFs; import android.util.Log; import android.widget.Toast; import com.openatlas.framework.OpenAtlas; import com.openatlas.framework.AtlasConfig; import com.openatlas.log.Logger; import com.openatlas.log.LoggerFactory; import com.openatlas.runtime.RuntimeVariables; import org.osgi.framework.Bundle; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; public class BundlesInstaller { Logger log = LoggerFactory.getInstance("BundlesInstaller"); private static boolean isTargetApp; private static BundlesInstaller instance; BundleDebug bundleDebug; private Application application; private boolean isInitialized; private boolean isDone; BundlesInstaller() { } void init(Application application, BundleDebug bundleDebug, boolean inTargetApp) { this.application = application; this.bundleDebug = bundleDebug; isTargetApp = inTargetApp; this.isInitialized = true; } static synchronized BundlesInstaller getInstance() { if (instance != null) { return instance; } synchronized (BundlesInstaller.class) { if (instance == null) { instance = new BundlesInstaller(); } } return instance; } public synchronized void process(boolean onlyProcessAutos, boolean reInstall) { if (!this.isInitialized) { Log.e("BundlesInstaller", "Bundle Installer not initialized yet, process abort!"); } else if (!this.isDone || reInstall) { ZipFile zipFile = null; try { zipFile = new ZipFile(this.application.getApplicationInfo().sourceDir); List<String> bundleList = fetchBundleFileList(zipFile, "lib/"+AtlasConfig.PRELOAD_DIR+"/libcom_", ".so"); if (bundleList != null && bundleList.size() > 0 && getAvailableSize() < ((long) (((bundleList.size() * 2) * 1024) * 1024))) { new Handler(Looper.getMainLooper()).post(new Runnable() { public void run() { Toast.makeText(RuntimeVariables.androidApplication, "Ops No Space ", Toast.LENGTH_SHORT).show(); } }); } if (onlyProcessAutos) { List bundles = new ArrayList(); for (String location : bundleList) { for (String replace : AtlasConfig.AUTO) { if (location.contains(replace.replace(".", "_"))) { bundles.add(location); } } } processAutoStartBundles(zipFile, bundles, this.application); } else { installBundle(zipFile, (List) bundleList, this.application); } if (!reInstall) { Utils.updatePackageVersion(this.application); } } catch (IOException e) { Log.e("BundlesInstaller", "IOException while processLibsBundles >>>", e); } finally { if (zipFile != null) { try { zipFile.close(); } catch (IOException e) { e.printStackTrace(); } } if (reInstall) { this.isDone = true; } } if (reInstall) { this.isDone = true; } } } private List<String> fetchBundleFileList(ZipFile zipFile, String prefix, String suffix) { List<String> arrayList = new ArrayList<String>(); try { Enumeration<?> entries = zipFile.entries(); while (entries.hasMoreElements()) { String name = ((ZipEntry) entries.nextElement()).getName(); if (name.startsWith(prefix) && name.endsWith(suffix)) { arrayList.add(name); } } } catch (Throwable e) { Log.e("BundlesInstaller", "Exception while get bundles in assets or lib", e); } return arrayList; } private long getAvailableSize() { StatFs statFs = new StatFs(Environment.getDataDirectory().getPath()); return ((long) statFs.getAvailableBlocks()) * ((long) statFs.getBlockSize()); } public void processAutoStartBundles(ZipFile zipFile, List<String> bundles, Application application) { for (String location : bundles) { installBundle(zipFile, location, application); } if (isTargetApp) { for (String location : AtlasConfig.AUTO) { Bundle bundle = OpenAtlas.getInstance().getBundle(location); if (bundle != null) { try { bundle.start(); } catch (Throwable e) { Log.e("BundlesInstaller", "Could not auto start bundle: " + bundle.getLocation(), e); } } } } } private void installBundle(ZipFile zipFile, List<String> bundles, Application application) { for (String location : AtlasConfig.DELAY) { String mLocation = contains(bundles, location.replace(".", "_")); if (mLocation != null && mLocation.length() > 0) { installBundle(zipFile, mLocation, application); bundles.remove(mLocation); } } for (String location : bundles) { installBundle(zipFile, location, application); } if (isTargetApp) { String[] auto = AtlasConfig.AUTO; for (String location:auto){ Bundle bundle = OpenAtlas.getInstance().getBundle(location); if (bundle != null) { try { bundle.start(); } catch (Throwable e) { Log.e("BundlesInstaller", "Could not auto start bundle: " + bundle.getLocation(), e); } } } } } private String contains(List<String> bundles, String location) { if (bundles == null || location == null) { return null; } for (String mLocation : bundles) { if (mLocation.contains(location)) { return mLocation; } } return null; } private boolean installBundle(ZipFile zipFile, String location, Application application) { log.info("processLibsBundle entryName " + location); this.bundleDebug.installExternalBundle(location); String fileNameFromEntryName = Utils.getFileNameFromEntryName(location); String packageNameFromEntryName = Utils.getPackageNameFromEntryName(location); if (packageNameFromEntryName == null || packageNameFromEntryName.length() <= 0) { return false; } File archvieFile = new File(new File(application.getFilesDir().getParentFile(), "lib"), fileNameFromEntryName); if (OpenAtlas.getInstance().getBundle(packageNameFromEntryName) != null) { return false; } try { if (archvieFile.exists()) { OpenAtlas.getInstance().installBundle(packageNameFromEntryName, archvieFile); } else { OpenAtlas.getInstance().installBundle(packageNameFromEntryName, zipFile.getInputStream(zipFile.getEntry(location))); } log.info("Succeed to install bundle " + packageNameFromEntryName); return true; } catch (Throwable e) { Log.e("BundlesInstaller", "Could not install bundle.", e); return false; } } }