|
6 | 6 |
|
7 | 7 | import com.badlogic.gdx.backends.android.AndroidApplication; |
8 | 8 | import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration; |
9 | | -import com.google.common.base.Charsets; |
10 | | -import com.google.common.io.ByteStreams; |
11 | | -import org.destinationsol.Const; |
| 9 | +import com.google.common.reflect.Reflection; |
12 | 10 | import org.destinationsol.SolApplication; |
13 | | -import org.destinationsol.modules.ModuleManager; |
| 11 | +import org.destinationsol.modules.FacadeModuleConfig; |
| 12 | +import org.terasology.context.Lifetime; |
| 13 | +import org.terasology.gestalt.android.AndroidAssetsFileSource; |
14 | 14 | import org.terasology.gestalt.android.AndroidModuleClassLoader; |
| 15 | +import org.terasology.gestalt.android.AndroidModulePathScanner; |
| 16 | +import org.terasology.gestalt.di.ServiceRegistry; |
| 17 | +import org.terasology.gestalt.di.index.UrlClassIndex; |
| 18 | +import org.terasology.gestalt.module.Module; |
| 19 | +import org.terasology.gestalt.module.ModuleEnvironment; |
| 20 | +import org.terasology.gestalt.module.ModuleMetadataJsonAdapter; |
| 21 | +import org.terasology.gestalt.module.ModulePathScanner; |
15 | 22 |
|
16 | 23 | import java.io.File; |
17 | | -import java.io.FileInputStream; |
18 | | -import java.io.FileOutputStream; |
19 | | -import java.io.IOException; |
20 | 24 | import java.io.InputStream; |
21 | 25 | import java.io.InputStreamReader; |
22 | | -import java.io.OutputStreamWriter; |
| 26 | +import java.util.Collections; |
23 | 27 |
|
24 | 28 | public class SolAndroid extends AndroidApplication { |
25 | 29 | @Override |
26 | 30 | public void onCreate(Bundle savedInstanceState) { |
27 | 31 | super.onCreate(savedInstanceState); |
28 | 32 | AndroidApplicationConfiguration config = new AndroidApplicationConfiguration(); |
29 | 33 |
|
30 | | - File filesDir = getFilesDir(); |
31 | | - copyModulesToDataDir(filesDir); |
32 | | - |
33 | | - // Android does not allow changing the system security policy. |
34 | | - // Modules should still be restricted via classpath filtering though. |
35 | | - ModuleManager manager = new ModuleManager(new File(filesDir, "modules"), false, |
36 | | - (module, parent, permissionProvider) -> AndroidModuleClassLoader.create(module, parent, permissionProvider, getCodeCacheDir())); |
37 | | - |
38 | | - try { |
39 | | - manager.init(); |
40 | | - } catch (Exception e) { |
41 | | - Log.e("DESTINATION_SOL_INIT", "Failed to initialise ModuleManager."); |
42 | | - } |
43 | | - |
44 | 34 | try { |
45 | | - initialize(new SolApplication(manager, 60.0f), config); |
| 35 | + initialize(new SolApplication(60.0f, new AndroidServices(getAssets(), getCodeCacheDir())), config); |
46 | 36 | } catch (Exception e) { |
47 | 37 | Log.e("DESTINATION_SOL", "FATAL ERROR: Forced abort!", e); |
48 | 38 | } |
49 | 39 | } |
50 | 40 |
|
51 | | - private void clearCachedModules(File modulesDir) { |
52 | | - File[] files = modulesDir.listFiles(); |
53 | | - if (files != null) { |
54 | | - for (File file : modulesDir.listFiles()) { |
55 | | - clearCachedModules(file); |
56 | | - } |
| 41 | + private static class AndroidServices extends ServiceRegistry { |
| 42 | + public AndroidServices(AssetManager assets, File codeCacheDir) { |
| 43 | + this.with(FacadeModuleConfig.class).lifetime(Lifetime.Singleton).use(() -> new AndroidModuleConfig(assets, codeCacheDir)); |
| 44 | + this.with(ModulePathScanner.class).lifetime(Lifetime.Singleton).use(() -> new AndroidModulePathScanner(assets, codeCacheDir)); |
57 | 45 | } |
58 | | - |
59 | | - modulesDir.delete(); |
60 | 46 | } |
61 | 47 |
|
62 | | - private void copyModulesToDataDir(File dataDir) { |
63 | | - File assetVersionFile = new File(dataDir, "version.txt"); |
64 | | - String versionString = ""; |
65 | | - if (assetVersionFile.exists()) { |
66 | | - try (FileInputStream inputStream = new FileInputStream(assetVersionFile)) { |
67 | | - try (InputStreamReader streamReader = new InputStreamReader(inputStream, Charsets.UTF_8)) { |
68 | | - StringBuilder builder = new StringBuilder(); |
69 | | - char[] buffer = new char[32]; |
70 | | - while (streamReader.read(buffer) != -1) { |
71 | | - builder.append(buffer); |
72 | | - } |
73 | | - versionString = builder.toString(); |
74 | | - } catch (Exception e) { |
75 | | - e.printStackTrace(); |
76 | | - } |
77 | | - } catch (Exception e) { |
78 | | - e.printStackTrace(); |
79 | | - } |
80 | | - } |
81 | | - |
82 | | - boolean refreshCache = (!versionString.equals(Const.VERSION) || com.miloshpetrov.sol2.android.BuildConfig.DEBUG); |
| 48 | + private static class AndroidModuleConfig implements FacadeModuleConfig { |
| 49 | + private final AssetManager assets; |
| 50 | + private final File codeCacheDir; |
83 | 51 |
|
84 | | - if (refreshCache) { |
85 | | - try (FileOutputStream stream = new FileOutputStream(assetVersionFile)) { |
86 | | - try (OutputStreamWriter writer = new OutputStreamWriter(stream)) { |
87 | | - writer.write(Const.VERSION); |
88 | | - } catch (Exception e) { |
89 | | - e.printStackTrace(); |
90 | | - } |
91 | | - } catch (Exception e) { |
92 | | - e.printStackTrace(); |
93 | | - } |
94 | | - |
95 | | - clearCachedModules(new File(dataDir, "modules")); |
| 52 | + public AndroidModuleConfig(AssetManager assets, File codeCacheDir) { |
| 53 | + this.assets = assets; |
| 54 | + this.codeCacheDir = codeCacheDir; |
96 | 55 | } |
97 | 56 |
|
98 | | - copyModules(dataDir, "modules", refreshCache); |
99 | | - |
100 | | - File musicFolder = new File(dataDir, "music"); |
101 | | - File soundFolder = new File(dataDir, "sound"); |
102 | | - if (!musicFolder.exists()) { |
103 | | - musicFolder.mkdir(); |
| 57 | + @Override |
| 58 | + public File getModulesPath() { |
| 59 | + return new File("modules"); |
104 | 60 | } |
105 | 61 |
|
106 | | - if (!soundFolder.exists()) { |
107 | | - soundFolder.mkdir(); |
| 62 | + // Android does not allow changing the system security policy. |
| 63 | + // Modules should still be restricted via classpath filtering though. |
| 64 | + @Override |
| 65 | + public boolean useSecurityManager() { |
| 66 | + return false; |
108 | 67 | } |
109 | | - } |
110 | 68 |
|
111 | | - private void copyModules(File dataDir, String rootDir, boolean replaceFiles) { |
112 | | - AssetManager assets = getAssets(); |
113 | | - try { |
114 | | - String[] filesToCopy = assets.list(rootDir); |
115 | | - for (String fileToCopy : filesToCopy) { |
116 | | - String filePath = rootDir + "/" + fileToCopy; |
117 | | - File file = new File(dataDir + "/" + rootDir, fileToCopy); |
118 | | - file.mkdirs(); |
119 | | - if (assets.list(filePath).length > 0) { |
120 | | - // File is a directory |
121 | | - if (!file.exists()) { |
122 | | - file.mkdirs(); |
123 | | - } |
124 | | - copyModules(dataDir, filePath, replaceFiles); |
125 | | - } else { |
126 | | - if (file.exists() && replaceFiles) { |
127 | | - // Replace old copies with newer ones |
128 | | - file.delete(); |
129 | | - } |
| 69 | + @Override |
| 70 | + public Module createEngineModule() { |
| 71 | + try { |
| 72 | + InputStream engineModuleMetadataStream = assets.open("engine/module.json"); |
| 73 | + return new Module(new ModuleMetadataJsonAdapter().read(new InputStreamReader(engineModuleMetadataStream)), |
| 74 | + new AndroidAssetsFileSource(assets, "engine"), |
| 75 | + Collections.emptyList(), UrlClassIndex.byClassLoaderPrefix("org.destinationsol"), x -> { |
| 76 | + String classPackageName = Reflection.getPackageName(x); |
| 77 | + return "org.destinationsol".equals(classPackageName) || classPackageName.startsWith("org.destinationsol."); |
| 78 | + }); |
| 79 | + } catch (Exception e) { |
| 80 | + Log.e("DestinationSol", "Error loading engine module!"); |
| 81 | + return null; |
| 82 | + } |
| 83 | + } |
130 | 84 |
|
131 | | - file.createNewFile(); |
| 85 | + @Override |
| 86 | + public ModuleEnvironment.ClassLoaderSupplier getClassLoaderSupplier() { |
| 87 | + return (module, parent, permissionProvider) -> AndroidModuleClassLoader.create(module, parent, permissionProvider, codeCacheDir); |
| 88 | + } |
132 | 89 |
|
133 | | - byte[] buffer = new byte[512]; |
134 | | - try (InputStream inputStream = assets.open(filePath)) { |
135 | | - try (FileOutputStream outputStream = new FileOutputStream(file)) { |
136 | | - ByteStreams.copy(inputStream, outputStream); |
137 | | - } catch (Exception e) { |
138 | | - Log.e("DESTINATION_SOL", "", e); |
139 | | - e.printStackTrace(); |
140 | | - } |
141 | | - } catch (IOException e) { |
142 | | - Log.e("DESTINATION_SOL", "", e); |
143 | | - e.printStackTrace(); |
144 | | - } |
145 | | - } |
146 | | - } |
147 | | - } catch (IOException e) { |
148 | | - Log.e("DESTINATION_SOL", "", e); |
149 | | - e.printStackTrace(); |
| 90 | + @Override |
| 91 | + public Class<?>[] getAPIClasses() { |
| 92 | + return new Class<?>[0]; |
150 | 93 | } |
151 | 94 | } |
152 | 95 | } |
0 commit comments