/** * OpenAtlasForAndroid Project * The MIT License (MIT) Copyright (OpenAtlasForAndroid) 2015 Bunny Blue,achellies * <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.framework; import android.app.Application; import android.content.ComponentName; import android.content.pm.PackageManager; import android.content.res.Resources; import com.openatlas.hack.AndroidHack; import com.openatlas.hack.OpenAtlasHacks; import com.openatlas.log.ILog; import com.openatlas.log.Logger; import com.openatlas.log.LoggerFactory; import com.openatlas.log.OpenAtlasLog; import com.openatlas.runtime.BundleLifecycleHandler; import com.openatlas.runtime.ClassLoadFromBundle; import com.openatlas.runtime.ClassNotFoundInterceptorCallback; import com.openatlas.runtime.DelegateClassLoader; import com.openatlas.runtime.DelegateComponent; import com.openatlas.runtime.FrameworkLifecycleHandler; import com.openatlas.runtime.InstrumentationHook; import com.openatlas.runtime.PackageLite; import com.openatlas.runtime.RuntimeVariables; import org.osgi.framework.Bundle; import org.osgi.framework.BundleException; import org.osgi.framework.BundleListener; import org.osgi.framework.FrameworkListener; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.Properties; public class Atlas { protected static Atlas instance; static final Logger log; private BundleLifecycleHandler bundleLifecycleHandler; private FrameworkLifecycleHandler frameworkLifecycleHandler; static { log = LoggerFactory.getInstance("Atlas"); } public static Atlas getInstance() { if (instance != null) { return instance; } synchronized (Atlas.class) { if (instance == null) { instance = new Atlas(); } } return instance; } public void init(Application application) throws Exception { String packageName = application.getPackageName(); OpenAtlasHacks.defineAndVerify(); ClassLoader classLoader = Atlas.class.getClassLoader(); DelegateClassLoader delegateClassLoader = new DelegateClassLoader(classLoader); Framework.systemClassLoader = classLoader; RuntimeVariables.delegateClassLoader = delegateClassLoader; RuntimeVariables.delegateResources = initResources(application); RuntimeVariables.androidApplication = application; AndroidHack.injectClassLoader(packageName, delegateClassLoader); AndroidHack.injectInstrumentationHook(new InstrumentationHook(AndroidHack .getInstrumentation(), application.getBaseContext())); injectApplication(application, packageName); this.bundleLifecycleHandler = new BundleLifecycleHandler(); Framework.syncBundleListeners.add(this.bundleLifecycleHandler); this.frameworkLifecycleHandler = new FrameworkLifecycleHandler(); Framework.frameworkListeners.add(this.frameworkLifecycleHandler); AndroidHack.hackH(); // Framework.initialize(properties); } /** *@since 1.0.0 * **/ private Resources initResources(Application application) throws Exception { Resources resources = application.getResources(); if (resources != null) { return resources; } log.error(" !!! Failed to get init resources."); return application.getPackageManager().getResourcesForApplication(application.getApplicationInfo()); } public void injectApplication(Application application, String packageName) throws Exception { OpenAtlasHacks.defineAndVerify(); AndroidHack.injectApplication(packageName, application); } public void startup(Properties properties) throws BundleException { Framework.startup(properties); } // public void startup() throws BundleException { // Framework.startup(); // } public void shutdown() throws BundleException { Framework.shutdown(false); } public Bundle getBundle(String pkgName) { return Framework.getBundle(pkgName); } public Bundle getBundleOnDemand(String pkgName) { if (pkgName == null || pkgName.length() == 0) { return null; } if (Framework.getBundle(pkgName) == null) { ClassLoadFromBundle.checkInstallBundleAndDependency(pkgName); } return Framework.getBundle(pkgName); } public Bundle installBundle(String location, InputStream inputStream) throws BundleException { return Framework.installNewBundle(location, inputStream); } public Bundle installBundle(String location, File apkFile) throws BundleException { return Framework.installNewBundle(location, apkFile); } public void updateBundle(String pkgName, InputStream inputStream) throws BundleException { Bundle bundle = Framework.getBundle(pkgName); if (bundle != null) { bundle.update(inputStream); return; } throw new BundleException("Could not update bundle " + pkgName + ", because could not find it"); } public void updateBundle(String pkgName, File mBundleFile) throws BundleException { if (!mBundleFile.exists()) { throw new BundleException("file not found" + mBundleFile.getAbsolutePath()); } Bundle bundle = Framework.getBundle(pkgName); if (bundle != null) { bundle.update(mBundleFile); return; } throw new BundleException("Could not update bundle " + pkgName + ", because could not find it"); } public boolean restoreBundle(String[] packageNames) { return Framework.restoreBundle(packageNames); } public void installOrUpdate(String[] packageNames, File[] bundleFiles) throws BundleException { Framework.installOrUpdate(packageNames, bundleFiles); } public void uninstallBundle(String pkgName) throws BundleException { Bundle bundle = Framework.getBundle(pkgName); if (bundle != null) { BundleImpl bundleImpl = (BundleImpl) bundle; try { File archiveFile = bundleImpl.getArchive().getArchiveFile(); if (archiveFile.canWrite()) { archiveFile.delete(); } bundleImpl.getArchive().purge(); File revisionDir = bundleImpl.getArchive().getCurrentRevision() .getRevisionDir(); bundle.uninstall(); if (revisionDir != null) { Framework.deleteDirectory(revisionDir); return; } return; } catch (Exception e) { log.error("uninstall bundle error: " + pkgName + e.getMessage()); return; } } throw new BundleException("Could not uninstall bundle " + pkgName + ", because could not find it"); } public List<Bundle> getBundles() { return Framework.getBundles(); } public Resources getDelegateResources() { return RuntimeVariables.delegateResources; } public ClassLoader getDelegateClassLoader() { return RuntimeVariables.delegateClassLoader; } public Class<?> getComponentClass(String pkgName) throws ClassNotFoundException { return RuntimeVariables.delegateClassLoader.loadClass(pkgName); } public ClassLoader getBundleClassLoader(String pkgName) { Bundle bundle = Framework.getBundle(pkgName); if (bundle != null) { return ((BundleImpl) bundle).getClassLoader(); } return null; } public PackageLite getBundlePackageLite(String pkgName) { return DelegateComponent.getPackage(pkgName); } public File getBundleFile(String pkgName) { Bundle bundle = Framework.getBundle(pkgName); if (bundle != null) { return ((BundleImpl) bundle).archive.getArchiveFile(); } return null; } public InputStream openAssetInputStream(String packageName, String assetName) throws IOException { Bundle bundle = Framework.getBundle(packageName); if (bundle != null) { return ((BundleImpl) bundle).archive.openAssetInputStream(assetName); } return null; } public InputStream openNonAssetInputStream(String packageName, String assetName) throws IOException { Bundle bundle = Framework.getBundle(packageName); if (bundle != null) { return ((BundleImpl) bundle).archive.openNonAssetInputStream(assetName); } return null; } public void addFrameworkListener(FrameworkListener frameworkListener) { Framework.addFrameworkListener(frameworkListener); } public void removeFrameworkListener(FrameworkListener frameworkListener) { Framework.removeFrameworkListener(frameworkListener); } public void addBundleListener(BundleListener bundleListener) { Framework.addBundleListener(bundleListener); } public void removeBundleListener(BundleListener bundleListener) { Framework.removeBundleListener(bundleListener); } public void onLowMemory() { this.bundleLifecycleHandler.handleLowMemory(); } public void enableComponent(String componentName) { PackageLite packageLite = DelegateComponent.getPackage(componentName); if (packageLite != null && packageLite.disableComponents != null) { for (String disableComponent : packageLite.disableComponents) { PackageManager packageManager = RuntimeVariables.androidApplication .getPackageManager(); ComponentName componentName2 = new ComponentName( RuntimeVariables.androidApplication.getPackageName(), disableComponent); try { packageManager.setComponentEnabledSetting(componentName2, 1, 1); log.debug("enableComponent: " + componentName2.getClassName()); } catch (Exception e) { log.error("enableComponent error: " + componentName2.getClassName() + e.getMessage()); } } } } public void setLogger(ILog iLog) { OpenAtlasLog.setExternalLogger(iLog); } public void setClassNotFoundInterceptorCallback( ClassNotFoundInterceptorCallback classNotFoundInterceptorCallback) { Framework.setClassNotFoundCallback(classNotFoundInterceptorCallback); } }