提交 7040ec58 编写于 作者: J Jason Simmons 提交者: GitHub

Use immersive mode on Android when all system UI overlays have been disabled (#2791)

This requires adding a way for platform services (namely SystemChromeImpl) to
listen for activity lifecycle events

Fixes https://github.com/flutter/flutter/issues/4885
上级 5ccb7f9a
......@@ -4,6 +4,7 @@ if (is_android) {
android_library("common_lib") {
java_files = [
"src/org/domokit/common/ActivityLifecycleListener.java",
"src/org/domokit/common/ResourcePaths.java",
]
}
......
......@@ -32,6 +32,7 @@ if (is_android) {
"//base:base_java",
"//mojo/public/java:bindings",
"//mojo/public/java:system",
"//sky/services/common:common_lib",
":interfaces_java",
]
}
......
......@@ -15,14 +15,18 @@ import org.chromium.mojom.flutter.platform.DeviceOrientation;
import org.chromium.mojom.flutter.platform.SystemChrome;
import org.chromium.mojom.flutter.platform.SystemUiOverlay;
import org.domokit.common.ActivityLifecycleListener;
/**
* Android implementation of SystemChrome.
*/
public class SystemChromeImpl implements SystemChrome {
public class SystemChromeImpl implements SystemChrome, ActivityLifecycleListener {
private final Activity mActivity;
private int mEnabledOverlays;
public SystemChromeImpl(Activity activity) {
mActivity = activity;
mEnabledOverlays = SystemUiOverlay.TOP | SystemUiOverlay.BOTTOM;
}
@Override
......@@ -84,19 +88,27 @@ public class SystemChromeImpl implements SystemChrome {
@Override
public void setEnabledSystemUiOverlays(int overlays,
SetEnabledSystemUiOverlaysResponse callback) {
mEnabledOverlays = overlays;
updateSystemUiOverlays();
callback.call(true);
}
private void updateSystemUiOverlays() {
int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
if ((overlays & SystemUiOverlay.TOP) == 0) {
if ((mEnabledOverlays & SystemUiOverlay.TOP) == 0) {
flags |= View.SYSTEM_UI_FLAG_FULLSCREEN;
}
if ((overlays & SystemUiOverlay.BOTTOM) == 0) {
if ((mEnabledOverlays & SystemUiOverlay.BOTTOM) == 0) {
flags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
}
if (mEnabledOverlays == 0) {
flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
}
mActivity.getWindow().getDecorView().setSystemUiVisibility(flags);
callback.call(true);
}
@Override
......@@ -106,4 +118,9 @@ public class SystemChromeImpl implements SystemChrome {
// so LIGHT vs DARK effectively isn't supported in Android.
callback.call(true);
}
@Override
public void onPostResume() {
updateSystemUiOverlays();
}
}
......@@ -149,78 +149,80 @@ public class FlutterMain {
registry.register(Activity.MANAGER.getName(), new ServiceFactory() {
@Override
public Binding connectToService(Context context, Core core, MessagePipeHandle pipe) {
public Binding connectToService(FlutterView view, Core core, MessagePipeHandle pipe) {
return Activity.MANAGER.bind(new ActivityImpl(), pipe);
}
});
registry.register(Clipboard.MANAGER.getName(), new ServiceFactory() {
@Override
public Binding connectToService(Context context, Core core, MessagePipeHandle pipe) {
return Clipboard.MANAGER.bind(new ClipboardImpl(context), pipe);
public Binding connectToService(FlutterView view, Core core, MessagePipeHandle pipe) {
return Clipboard.MANAGER.bind(new ClipboardImpl(view.getContext()), pipe);
}
});
registry.register(MediaService.MANAGER.getName(), new ServiceFactory() {
@Override
public Binding connectToService(Context context, Core core, MessagePipeHandle pipe) {
return MediaService.MANAGER.bind(new MediaServiceImpl(context, core), pipe);
public Binding connectToService(FlutterView view, Core core, MessagePipeHandle pipe) {
return MediaService.MANAGER.bind(new MediaServiceImpl(view.getContext(), core), pipe);
}
});
registry.register(NetworkService.MANAGER.getName(), new ServiceFactory() {
@Override
public Binding connectToService(Context context, Core core, MessagePipeHandle pipe) {
return NetworkService.MANAGER.bind(new NetworkServiceImpl(context, core), pipe);
public Binding connectToService(FlutterView view, Core core, MessagePipeHandle pipe) {
return NetworkService.MANAGER.bind(new NetworkServiceImpl(view.getContext(), core), pipe);
}
});
registry.register(SensorService.MANAGER.getName(), new ServiceFactory() {
@Override
public Binding connectToService(Context context, Core core, MessagePipeHandle pipe) {
return SensorService.MANAGER.bind(new SensorServiceImpl(context), pipe);
public Binding connectToService(FlutterView view, Core core, MessagePipeHandle pipe) {
return SensorService.MANAGER.bind(new SensorServiceImpl(view.getContext()), pipe);
}
});
registry.register(VSyncProvider.MANAGER.getName(), new ServiceFactory() {
@Override
public Binding connectToService(Context context, Core core, MessagePipeHandle pipe) {
public Binding connectToService(FlutterView view, Core core, MessagePipeHandle pipe) {
return VSyncProvider.MANAGER.bind(new VSyncProviderImpl(pipe), pipe);
}
});
registry.register(HapticFeedback.MANAGER.getName(), new ServiceFactory() {
@Override
public Binding connectToService(Context context, Core core, MessagePipeHandle pipe) {
return HapticFeedback.MANAGER.bind(new HapticFeedbackImpl((android.app.Activity) context), pipe);
public Binding connectToService(FlutterView view, Core core, MessagePipeHandle pipe) {
return HapticFeedback.MANAGER.bind(new HapticFeedbackImpl((android.app.Activity) view.getContext()), pipe);
}
});
registry.register(PathProvider.MANAGER.getName(), new ServiceFactory() {
@Override
public Binding connectToService(Context context, Core core, MessagePipeHandle pipe) {
return PathProvider.MANAGER.bind(new PathProviderImpl(context), pipe);
public Binding connectToService(FlutterView view, Core core, MessagePipeHandle pipe) {
return PathProvider.MANAGER.bind(new PathProviderImpl(view.getContext()), pipe);
}
});
registry.register(SystemChrome.MANAGER.getName(), new ServiceFactory() {
@Override
public Binding connectToService(Context context, Core core, MessagePipeHandle pipe) {
return SystemChrome.MANAGER.bind(new SystemChromeImpl((android.app.Activity) context), pipe);
public Binding connectToService(FlutterView view, Core core, MessagePipeHandle pipe) {
SystemChromeImpl chrome = new SystemChromeImpl((android.app.Activity) view.getContext());
view.addActivityLifecycleListener(chrome);
return SystemChrome.MANAGER.bind(chrome, pipe);
}
});
registry.register(SystemSound.MANAGER.getName(), new ServiceFactory() {
@Override
public Binding connectToService(Context context, Core core, MessagePipeHandle pipe) {
return SystemSound.MANAGER.bind(new SystemSoundImpl((android.app.Activity) context), pipe);
public Binding connectToService(FlutterView view, Core core, MessagePipeHandle pipe) {
return SystemSound.MANAGER.bind(new SystemSoundImpl((android.app.Activity) view.getContext()), pipe);
}
});
registry.register(UrlLauncher.MANAGER.getName(), new ServiceFactory() {
@Override
public Binding connectToService(Context context, Core core, MessagePipeHandle pipe) {
return UrlLauncher.MANAGER.bind(new UrlLauncherImpl((android.app.Activity) context), pipe);
public Binding connectToService(FlutterView view, Core core, MessagePipeHandle pipe) {
return UrlLauncher.MANAGER.bind(new UrlLauncherImpl((android.app.Activity) view.getContext()), pipe);
}
});
}
......@@ -262,11 +264,11 @@ public class FlutterMain {
private static void registerService(ServiceRegistry registry, final String serviceName, final String className) {
registry.register(serviceName, new ServiceFactory() {
@Override
public Binding connectToService(Context context, Core core, MessagePipeHandle pipe) {
public Binding connectToService(FlutterView view, Core core, MessagePipeHandle pipe) {
try {
return (Binding) Class.forName(className)
.getMethod("connectToService", Context.class, Core.class, MessagePipeHandle.class)
.invoke(null, context, core, pipe);
.getMethod("connectToService", FlutterView.class, Core.class, MessagePipeHandle.class)
.invoke(null, view, core, pipe);
} catch(Exception e) {
Log.e(TAG, "Failed to register service '" + serviceName + "'", e);
throw new RuntimeException(e);
......
......@@ -59,6 +59,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.domokit.common.ActivityLifecycleListener;
import org.domokit.activity.ActivityImpl;
import org.domokit.editing.KeyboardImpl;
import org.domokit.editing.KeyboardViewState;
......@@ -92,6 +93,7 @@ public class FlutterView extends SurfaceView
private final RawKeyboardServiceState mRawKeyboardState;
private final AccessibilityManager mAccessibilityManager;
private BroadcastReceiver discoveryReceiver;
private List<ActivityLifecycleListener> mActivityLifecycleListeners;
public FlutterView(Context context) {
this(context, null);
......@@ -136,16 +138,17 @@ public class FlutterView extends SurfaceView
Core core = CoreImpl.getInstance();
mPlatformServiceProvider = new ServiceProviderImpl(core, getContext(), ServiceRegistry.SHARED);
mPlatformServiceProvider = new ServiceProviderImpl(core, this, ServiceRegistry.SHARED);
ServiceRegistry localRegistry = new ServiceRegistry();
configureLocalServices(localRegistry);
mViewServiceProvider = new ServiceProviderImpl(core, getContext(), localRegistry);
mViewServiceProvider = new ServiceProviderImpl(core, this, localRegistry);
mAccessibilityManager = (AccessibilityManager)getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
mOnMessageListeners = new HashMap<String, OnMessageListener>();
mAsyncOnMessageListeners = new HashMap<String, OnMessageListenerAsync>();
mActivityLifecycleListeners = new ArrayList<ActivityLifecycleListener>();
setLocale(getResources().getConfiguration().locale);
......@@ -173,11 +176,18 @@ public class FlutterView extends SurfaceView
return mSkyEngine;
}
public void addActivityLifecycleListener(ActivityLifecycleListener listener) {
mActivityLifecycleListeners.add(listener);
}
public void onPause() {
mSkyEngine.onAppLifecycleStateChanged(AppLifecycleState.PAUSED);
}
public void onPostResume() {
for (ActivityLifecycleListener listener : mActivityLifecycleListeners)
listener.onPostResume();
mSkyEngine.onAppLifecycleStateChanged(AppLifecycleState.RESUMED);
}
......@@ -369,21 +379,21 @@ public class FlutterView extends SurfaceView
private void configureLocalServices(ServiceRegistry registry) {
registry.register(Keyboard.MANAGER.getName(), new ServiceFactory() {
@Override
public Binding connectToService(Context context, Core core, MessagePipeHandle pipe) {
return Keyboard.MANAGER.bind(new KeyboardImpl(context, mKeyboardState), pipe);
public Binding connectToService(FlutterView view, Core core, MessagePipeHandle pipe) {
return Keyboard.MANAGER.bind(new KeyboardImpl(view.getContext(), mKeyboardState), pipe);
}
});
registry.register(RawKeyboardService.MANAGER.getName(), new ServiceFactory() {
@Override
public Binding connectToService(Context context, Core core, MessagePipeHandle pipe) {
public Binding connectToService(FlutterView view, Core core, MessagePipeHandle pipe) {
return RawKeyboardService.MANAGER.bind(new RawKeyboardServiceImpl(mRawKeyboardState), pipe);
}
});
registry.register(ApplicationMessages.MANAGER.getName(), new ServiceFactory() {
@Override
public Binding connectToService(Context context, Core core, MessagePipeHandle pipe) {
public Binding connectToService(FlutterView view, Core core, MessagePipeHandle pipe) {
return ApplicationMessages.MANAGER.bind(new ApplicationMessagesImpl(), pipe);
}
});
......
......@@ -16,5 +16,5 @@ import org.chromium.mojo.system.MessagePipeHandle;
* clients.
**/
interface ServiceFactory {
Binding connectToService(Context context, Core core, MessagePipeHandle pipe);
Binding connectToService(FlutterView view, Core core, MessagePipeHandle pipe);
}
......@@ -23,15 +23,15 @@ class ServiceProviderImpl implements ServiceProvider {
private static final String TAG = "ServiceProviderImpl";
private Core mCore;
private Context mContext;
private FlutterView mView;
private ServiceRegistry mRegistry;
private HashSet<Binding> mBindings = new HashSet<Binding>();
ServiceProviderImpl(Core core, Context context, ServiceRegistry registry) {
ServiceProviderImpl(Core core, FlutterView view, ServiceRegistry registry) {
assert core != null;
assert context != null;
assert view != null;
mCore = core;
mContext = context;
mView = view;
mRegistry = registry;
}
......@@ -48,7 +48,7 @@ class ServiceProviderImpl implements ServiceProvider {
pipe.close();
return;
}
final Binding binding = factory.connectToService(mContext, mCore, pipe);
final Binding binding = factory.connectToService(mView, mCore, pipe);
mBindings.add(binding);
binding.registerErrorHandler(new ConnectionErrorHandler() {
@Override
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册