mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Merge pull request #2512 from jason-simmons/embed_sky_application
Move SkyApplication initialization into SkyMain
This commit is contained in:
commit
bf45869dbf
@ -132,7 +132,7 @@ public class SkyActivity extends Activity {
|
||||
return;
|
||||
}
|
||||
File dataDir = new File(PathUtils.getDataDirectory(this));
|
||||
File appBundle = new File(dataDir, SkyApplication.APP_BUNDLE);
|
||||
File appBundle = new File(dataDir, SkyMain.APP_BUNDLE);
|
||||
if (appBundle.exists()) {
|
||||
mView.runFromBundle(appBundle.getPath(), null);
|
||||
return;
|
||||
|
||||
@ -4,225 +4,16 @@
|
||||
|
||||
package org.domokit.sky.shell;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
import android.util.Log;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONTokener;
|
||||
|
||||
import org.chromium.base.BaseChromiumApplication;
|
||||
import org.chromium.base.library_loader.LibraryLoader;
|
||||
import org.chromium.base.library_loader.LibraryProcessType;
|
||||
import org.chromium.base.library_loader.ProcessInitException;
|
||||
import org.chromium.base.PathUtils;
|
||||
import org.chromium.mojo.sensors.SensorServiceImpl;
|
||||
import org.chromium.mojo.system.Core;
|
||||
import org.chromium.mojo.system.MessagePipeHandle;
|
||||
import org.chromium.mojom.activity.Activity;
|
||||
import org.chromium.mojom.activity.PathService;
|
||||
import org.chromium.mojom.flutter.platform.HapticFeedback;
|
||||
import org.chromium.mojom.flutter.platform.PathProvider;
|
||||
import org.chromium.mojom.flutter.platform.SystemChrome;
|
||||
import org.chromium.mojom.flutter.platform.SystemSound;
|
||||
import org.chromium.mojom.media.MediaService;
|
||||
import org.chromium.mojom.mojo.NetworkService;
|
||||
import org.chromium.mojom.sensors.SensorService;
|
||||
import org.chromium.mojom.vsync.VSyncProvider;
|
||||
import org.domokit.activity.ActivityImpl;
|
||||
import org.domokit.activity.PathServiceImpl;
|
||||
import org.domokit.media.MediaServiceImpl;
|
||||
import org.domokit.oknet.NetworkServiceImpl;
|
||||
import org.domokit.platform.HapticFeedbackImpl;
|
||||
import org.domokit.platform.PathProviderImpl;
|
||||
import org.domokit.platform.SystemChromeImpl;
|
||||
import org.domokit.platform.SystemSoundImpl;
|
||||
import org.domokit.vsync.VSyncProviderImpl;
|
||||
import android.app.Application;
|
||||
|
||||
/**
|
||||
* Sky implementation of {@link android.app.Application}, managing application-level global
|
||||
* state and initializations.
|
||||
* initializations.
|
||||
*/
|
||||
public class SkyApplication extends BaseChromiumApplication {
|
||||
public static final String APP_BUNDLE = "app.flx";
|
||||
static final String MANIFEST = "flutter.yaml";
|
||||
static final String SERVICES = "services.json";
|
||||
|
||||
private static final String TAG = "SkyApplication";
|
||||
private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "sky_shell";
|
||||
private static final String[] SKY_RESOURCES = {"icudtl.dat", APP_BUNDLE, MANIFEST};
|
||||
|
||||
private ResourceExtractor mResourceExtractor;
|
||||
|
||||
public ResourceExtractor getResourceExtractor() {
|
||||
return mResourceExtractor;
|
||||
}
|
||||
|
||||
public class SkyApplication extends Application {
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
initJavaUtils();
|
||||
initResources();
|
||||
initNative();
|
||||
onServiceRegistryAvailable(ServiceRegistry.SHARED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this function to add more resources for extraction.
|
||||
*/
|
||||
protected void onBeforeResourceExtraction(ResourceExtractor extractor) {
|
||||
extractor.addResources(SKY_RESOURCES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this function to register more services.
|
||||
*/
|
||||
protected void onServiceRegistryAvailable(ServiceRegistry registry) {
|
||||
parseServicesConfig(registry);
|
||||
|
||||
registry.register(Activity.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
Activity.MANAGER.bind(new ActivityImpl(), pipe);
|
||||
}
|
||||
});
|
||||
|
||||
registry.register(PathService.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
PathService.MANAGER.bind(new PathServiceImpl(getApplicationContext()), pipe);
|
||||
}
|
||||
});
|
||||
|
||||
registry.register(MediaService.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
MediaService.MANAGER.bind(new MediaServiceImpl(context, core), pipe);
|
||||
}
|
||||
});
|
||||
|
||||
registry.register(NetworkService.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
NetworkService.MANAGER.bind(new NetworkServiceImpl(context, core), pipe);
|
||||
}
|
||||
});
|
||||
|
||||
registry.register(SensorService.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
SensorService.MANAGER.bind(new SensorServiceImpl(context), pipe);
|
||||
}
|
||||
});
|
||||
|
||||
registry.register(VSyncProvider.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
VSyncProvider.MANAGER.bind(new VSyncProviderImpl(pipe), pipe);
|
||||
}
|
||||
});
|
||||
|
||||
registry.register(HapticFeedback.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
HapticFeedback.MANAGER.bind(new HapticFeedbackImpl(), pipe);
|
||||
}
|
||||
});
|
||||
|
||||
registry.register(PathProvider.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
PathProvider.MANAGER.bind(new PathProviderImpl(context), pipe);
|
||||
}
|
||||
});
|
||||
|
||||
registry.register(SystemChrome.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
SystemChrome.MANAGER.bind(new SystemChromeImpl(), pipe);
|
||||
}
|
||||
});
|
||||
|
||||
registry.register(SystemSound.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
SystemSound.MANAGER.bind(new SystemSoundImpl(), pipe);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the auto-generated services.json file, which contains additional services to register.
|
||||
*/
|
||||
private void parseServicesConfig(ServiceRegistry registry) {
|
||||
final AssetManager manager = getResources().getAssets();
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(manager.open(SERVICES)))) {
|
||||
StringBuffer json = new StringBuffer();
|
||||
while (true) {
|
||||
String line = reader.readLine();
|
||||
if (line == null)
|
||||
break;
|
||||
json.append(line);
|
||||
}
|
||||
|
||||
JSONObject object = (JSONObject) new JSONTokener(json.toString()).nextValue();
|
||||
JSONArray services = object.getJSONArray("services");
|
||||
for (int i = 0; i < services.length(); ++i) {
|
||||
JSONObject service = services.getJSONObject(i);
|
||||
String serviceName = service.getString("name");
|
||||
String className = service.getString("class");
|
||||
registerService(registry, serviceName, className);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
// Not all apps will have a services.json file.
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failure parsing service configuration file", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a third-party service.
|
||||
*/
|
||||
private void registerService(ServiceRegistry registry, final String serviceName, final String className) {
|
||||
registry.register(serviceName, new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
try {
|
||||
Class.forName(className)
|
||||
.getMethod("connectToService", Context.class, Core.class, MessagePipeHandle.class)
|
||||
.invoke(null, context, core, pipe);
|
||||
} catch(Exception e) {
|
||||
Log.e(TAG, "Failed to register service '" + serviceName + "'", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initJavaUtils() {
|
||||
PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX,
|
||||
getApplicationContext());
|
||||
}
|
||||
|
||||
private void initResources() {
|
||||
Context context = getApplicationContext();
|
||||
new ResourceCleaner(context).start();
|
||||
mResourceExtractor = new ResourceExtractor(context);
|
||||
onBeforeResourceExtraction(mResourceExtractor);
|
||||
mResourceExtractor.start();
|
||||
}
|
||||
|
||||
private void initNative() {
|
||||
try {
|
||||
LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER).ensureInitialized(this);
|
||||
} catch (ProcessInitException e) {
|
||||
Log.e(TAG, "Unable to load Sky Engine binary.", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
SkyMain.startInit(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,9 +6,44 @@ package org.domokit.sky.shell;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import android.content.res.AssetManager;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONTokener;
|
||||
|
||||
import org.chromium.base.JNINamespace;
|
||||
import org.chromium.base.PathUtils;
|
||||
import org.chromium.base.library_loader.LibraryLoader;
|
||||
import org.chromium.base.library_loader.LibraryProcessType;
|
||||
import org.chromium.base.library_loader.ProcessInitException;
|
||||
import org.chromium.mojo.sensors.SensorServiceImpl;
|
||||
import org.chromium.mojo.system.Core;
|
||||
import org.chromium.mojo.system.impl.CoreImpl;
|
||||
import org.chromium.mojo.system.MessagePipeHandle;
|
||||
import org.chromium.mojom.activity.Activity;
|
||||
import org.chromium.mojom.activity.PathService;
|
||||
import org.chromium.mojom.flutter.platform.HapticFeedback;
|
||||
import org.chromium.mojom.flutter.platform.PathProvider;
|
||||
import org.chromium.mojom.flutter.platform.SystemChrome;
|
||||
import org.chromium.mojom.flutter.platform.SystemSound;
|
||||
import org.chromium.mojom.media.MediaService;
|
||||
import org.chromium.mojom.mojo.NetworkService;
|
||||
import org.chromium.mojom.sensors.SensorService;
|
||||
import org.chromium.mojom.vsync.VSyncProvider;
|
||||
import org.domokit.activity.ActivityImpl;
|
||||
import org.domokit.activity.PathServiceImpl;
|
||||
import org.domokit.media.MediaServiceImpl;
|
||||
import org.domokit.oknet.NetworkServiceImpl;
|
||||
import org.domokit.platform.HapticFeedbackImpl;
|
||||
import org.domokit.platform.PathProviderImpl;
|
||||
import org.domokit.platform.SystemChromeImpl;
|
||||
import org.domokit.platform.SystemSoundImpl;
|
||||
import org.domokit.vsync.VSyncProviderImpl;
|
||||
|
||||
|
||||
/**
|
||||
* A class to intialize the native code.
|
||||
@ -17,21 +52,39 @@ import org.chromium.mojo.system.impl.CoreImpl;
|
||||
public class SkyMain {
|
||||
private static final String TAG = "SkyMain";
|
||||
|
||||
public static final String APP_BUNDLE = "app.flx";
|
||||
private static final String MANIFEST = "flutter.yaml";
|
||||
private static final String SERVICES = "services.json";
|
||||
|
||||
private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "sky_shell";
|
||||
private static final String[] SKY_RESOURCES = {"icudtl.dat", APP_BUNDLE, MANIFEST};
|
||||
|
||||
/**
|
||||
* A guard flag for calling nativeInit() only once.
|
||||
**/
|
||||
private static boolean sInitialized = false;
|
||||
|
||||
private static ResourceExtractor sResourceExtractor;
|
||||
|
||||
/**
|
||||
* Initializes the native system.
|
||||
* Starts initialization of the native system.
|
||||
**/
|
||||
public static void startInit(Context applicationContext) {
|
||||
initJavaUtils(applicationContext);
|
||||
initResources(applicationContext);
|
||||
initNative(applicationContext);
|
||||
onServiceRegistryAvailable(applicationContext, ServiceRegistry.SHARED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Blocks until initialization of the native system has completed.
|
||||
**/
|
||||
public static void ensureInitialized(Context applicationContext, String[] args) {
|
||||
if (sInitialized) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
SkyApplication app = (SkyApplication) applicationContext;
|
||||
app.getResourceExtractor().waitForCompletion();
|
||||
sResourceExtractor.waitForCompletion();
|
||||
nativeInit(applicationContext, args);
|
||||
// Create the mojo run loop.
|
||||
CoreImpl.getInstance().createDefaultRunLoop();
|
||||
@ -43,4 +96,149 @@ public class SkyMain {
|
||||
}
|
||||
|
||||
private static native void nativeInit(Context context, String[] args);
|
||||
|
||||
private static void onServiceRegistryAvailable(final Context applicationContext, ServiceRegistry registry) {
|
||||
parseServicesConfig(applicationContext, registry);
|
||||
|
||||
registry.register(Activity.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
Activity.MANAGER.bind(new ActivityImpl(), pipe);
|
||||
}
|
||||
});
|
||||
|
||||
registry.register(PathService.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
PathService.MANAGER.bind(new PathServiceImpl(applicationContext), pipe);
|
||||
}
|
||||
});
|
||||
|
||||
registry.register(MediaService.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
MediaService.MANAGER.bind(new MediaServiceImpl(context, core), pipe);
|
||||
}
|
||||
});
|
||||
|
||||
registry.register(NetworkService.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
NetworkService.MANAGER.bind(new NetworkServiceImpl(context, core), pipe);
|
||||
}
|
||||
});
|
||||
|
||||
registry.register(SensorService.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
SensorService.MANAGER.bind(new SensorServiceImpl(context), pipe);
|
||||
}
|
||||
});
|
||||
|
||||
registry.register(VSyncProvider.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
VSyncProvider.MANAGER.bind(new VSyncProviderImpl(pipe), pipe);
|
||||
}
|
||||
});
|
||||
|
||||
registry.register(HapticFeedback.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
HapticFeedback.MANAGER.bind(new HapticFeedbackImpl(), pipe);
|
||||
}
|
||||
});
|
||||
|
||||
registry.register(PathProvider.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
PathProvider.MANAGER.bind(new PathProviderImpl(context), pipe);
|
||||
}
|
||||
});
|
||||
|
||||
registry.register(SystemChrome.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
SystemChrome.MANAGER.bind(new SystemChromeImpl(), pipe);
|
||||
}
|
||||
});
|
||||
|
||||
registry.register(SystemSound.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
SystemSound.MANAGER.bind(new SystemSoundImpl(), pipe);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the auto-generated services.json file, which contains additional services to register.
|
||||
*/
|
||||
private static void parseServicesConfig(Context applicationContext, ServiceRegistry registry) {
|
||||
final AssetManager manager = applicationContext.getResources().getAssets();
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(manager.open(SERVICES)))) {
|
||||
StringBuffer json = new StringBuffer();
|
||||
while (true) {
|
||||
String line = reader.readLine();
|
||||
if (line == null)
|
||||
break;
|
||||
json.append(line);
|
||||
}
|
||||
|
||||
JSONObject object = (JSONObject) new JSONTokener(json.toString()).nextValue();
|
||||
JSONArray services = object.getJSONArray("services");
|
||||
for (int i = 0; i < services.length(); ++i) {
|
||||
JSONObject service = services.getJSONObject(i);
|
||||
String serviceName = service.getString("name");
|
||||
String className = service.getString("class");
|
||||
registerService(registry, serviceName, className);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
// Not all apps will have a services.json file.
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failure parsing service configuration file", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a third-party service.
|
||||
*/
|
||||
private static void registerService(ServiceRegistry registry, final String serviceName, final String className) {
|
||||
registry.register(serviceName, new ServiceFactory() {
|
||||
@Override
|
||||
public void connectToService(Context context, Core core, MessagePipeHandle pipe) {
|
||||
try {
|
||||
Class.forName(className)
|
||||
.getMethod("connectToService", Context.class, Core.class, MessagePipeHandle.class)
|
||||
.invoke(null, context, core, pipe);
|
||||
} catch(Exception e) {
|
||||
Log.e(TAG, "Failed to register service '" + serviceName + "'", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void initJavaUtils(Context applicationContext) {
|
||||
PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX,
|
||||
applicationContext);
|
||||
}
|
||||
|
||||
private static void initResources(Context applicationContext) {
|
||||
Context context = applicationContext;
|
||||
new ResourceCleaner(context).start();
|
||||
sResourceExtractor = new ResourceExtractor(context);
|
||||
sResourceExtractor.addResources(SKY_RESOURCES);
|
||||
sResourceExtractor.start();
|
||||
}
|
||||
|
||||
private static void initNative(Context applicationContext) {
|
||||
try {
|
||||
LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER).ensureInitialized(applicationContext);
|
||||
} catch (ProcessInitException e) {
|
||||
Log.e(TAG, "Unable to load Sky Engine binary.", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user