Commit e2251dec authored by justin's avatar justin

Merge branch 'v1.12.13-hotfixes'

parents 4ee76454 ac3bc276
...@@ -17,3 +17,4 @@ example/android/app/.classpath ...@@ -17,3 +17,4 @@ example/android/app/.classpath
example/android/app/.project example/android/app/.project
example/android/.project example/android/.project
flutter_boost flutter_boost
.flutter-plugins-dependencies
package com.idlefish.flutterboost;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.util.AttributeSet;
import android.view.Surface;
import android.view.TextureView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.Log;
import io.flutter.embedding.engine.renderer.FlutterRenderer;
import io.flutter.embedding.engine.renderer.RenderSurface;
public class XFlutterTextureView extends TextureView implements RenderSurface {
private static final String TAG = "FlutterTextureView";
private boolean isSurfaceAvailableForRendering = false;
private boolean isAttachedToFlutterRenderer = false;
@Nullable
private FlutterRenderer flutterRenderer;
private Surface renderSurface;
// Connects the {@code SurfaceTexture} beneath this {@code TextureView} with Flutter's native code.
// Callbacks are received by this Object and then those messages are forwarded to our
// FlutterRenderer, and then on to the JNI bridge over to native Flutter code.
private final SurfaceTextureListener surfaceTextureListener = new SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
Log.v(TAG, "SurfaceTextureListener.onSurfaceTextureAvailable()");
isSurfaceAvailableForRendering = true;
// If we're already attached to a FlutterRenderer then we're now attached to both a renderer
// and the Android window, so we can begin rendering now.
if (isAttachedToFlutterRenderer) {
connectSurfaceToRenderer();
}
}
@Override
public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {
Log.v(TAG, "SurfaceTextureListener.onSurfaceTextureSizeChanged()");
if (isAttachedToFlutterRenderer) {
changeSurfaceSize(width, height);
}
}
@Override
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {
// Invoked every time a new frame is available. We don't care.
}
@Override
public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
Log.v(TAG, "SurfaceTextureListener.onSurfaceTextureDestroyed()");
isSurfaceAvailableForRendering = false;
// If we're attached to a FlutterRenderer then we need to notify it that our SurfaceTexture
// has been destroyed.
if (isAttachedToFlutterRenderer) {
disconnectSurfaceFromRenderer();
}
// Return true to indicate that no further painting will take place
// within this SurfaceTexture.
return true;
}
};
/**
* Constructs a {@code FlutterTextureView} programmatically, without any XML attributes.
*/
public XFlutterTextureView(@NonNull Context context) {
this(context, null);
}
/**
* Constructs a {@code FlutterTextureView} in an XML-inflation-compliant manner.
*/
public XFlutterTextureView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
// Listen for when our underlying SurfaceTexture becomes available, changes size, or
// gets destroyed, and take the appropriate actions.
setSurfaceTextureListener(surfaceTextureListener);
}
@Nullable
@Override
public FlutterRenderer getAttachedRenderer() {
return flutterRenderer;
}
/**
* Invoked by the owner of this {@code FlutterTextureView} when it wants to begin rendering
* a Flutter UI to this {@code FlutterTextureView}.
*
* If an Android {@link SurfaceTexture} is available, this method will give that
* {@link SurfaceTexture} to the given {@link FlutterRenderer} to begin rendering
* Flutter's UI to this {@code FlutterTextureView}.
*
* If no Android {@link SurfaceTexture} is available yet, this {@code FlutterTextureView}
* will wait until a {@link SurfaceTexture} becomes available and then give that
* {@link SurfaceTexture} to the given {@link FlutterRenderer} to begin rendering
* Flutter's UI to this {@code FlutterTextureView}.
*/
public void attachToRenderer(@NonNull FlutterRenderer flutterRenderer) {
Log.v(TAG, "Attaching to FlutterRenderer.");
if (this.flutterRenderer != null) {
Log.v(TAG, "Already connected to a FlutterRenderer. Detaching from old one and attaching to new one.");
this.flutterRenderer.stopRenderingToSurface();
}
this.flutterRenderer = flutterRenderer;
isAttachedToFlutterRenderer = true;
// If we're already attached to an Android window then we're now attached to both a renderer
// and the Android window. We can begin rendering now.
if (isSurfaceAvailableForRendering) {
Log.v(TAG, "Surface is available for rendering. Connecting FlutterRenderer to Android surface.");
connectSurfaceToRenderer();
}
}
/**
* Invoked by the owner of this {@code FlutterTextureView} when it no longer wants to render
* a Flutter UI to this {@code FlutterTextureView}.
*
* This method will cease any on-going rendering from Flutter to this {@code FlutterTextureView}.
*/
public void detachFromRenderer() {
if (flutterRenderer != null) {
// If we're attached to an Android window then we were rendering a Flutter UI. Now that
// this FlutterTextureView is detached from the FlutterRenderer, we need to stop rendering.
// TODO(mattcarroll): introduce a isRendererConnectedToSurface() to wrap "getWindowToken() != null"
if (getWindowToken() != null) {
Log.v(TAG, "Disconnecting FlutterRenderer from Android surface.");
disconnectSurfaceFromRenderer();
}
flutterRenderer = null;
isAttachedToFlutterRenderer = false;
} else {
Log.w(TAG, "detachFromRenderer() invoked when no FlutterRenderer was attached.");
}
}
// FlutterRenderer and getSurfaceTexture() must both be non-null.
private void connectSurfaceToRenderer() {
if (flutterRenderer == null || getSurfaceTexture() == null) {
throw new IllegalStateException("connectSurfaceToRenderer() should only be called when flutterRenderer and getSurfaceTexture() are non-null.");
}
// flutterRenderer.startRenderingToSurface(new Surface(getSurfaceTexture()));
renderSurface = new Surface(getSurfaceTexture());
flutterRenderer.startRenderingToSurface(renderSurface);
}
// FlutterRenderer must be non-null.
private void changeSurfaceSize(int width, int height) {
if (flutterRenderer == null) {
throw new IllegalStateException("changeSurfaceSize() should only be called when flutterRenderer is non-null.");
}
Log.v(TAG, "Notifying FlutterRenderer that Android surface size has changed to " + width + " x " + height);
flutterRenderer.surfaceChanged(width, height);
}
// FlutterRenderer must be non-null.
private void disconnectSurfaceFromRenderer() {
if (flutterRenderer == null) {
throw new IllegalStateException("disconnectSurfaceFromRenderer() should only be called when flutterRenderer is non-null.");
}
flutterRenderer.stopRenderingToSurface();
if(renderSurface!=null){
renderSurface.release();
renderSurface = null;
}
}
}
\ No newline at end of file
...@@ -38,7 +38,6 @@ import io.flutter.embedding.engine.FlutterEngine; ...@@ -38,7 +38,6 @@ import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.renderer.FlutterRenderer; import io.flutter.embedding.engine.renderer.FlutterRenderer;
import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener; import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener;
import io.flutter.embedding.engine.renderer.RenderSurface; import io.flutter.embedding.engine.renderer.RenderSurface;
import io.flutter.embedding.engine.systemchannels.TextInputChannel;
import io.flutter.plugin.editing.TextInputPlugin; import io.flutter.plugin.editing.TextInputPlugin;
import io.flutter.plugin.platform.PlatformViewsController; import io.flutter.plugin.platform.PlatformViewsController;
import io.flutter.view.AccessibilityBridge; import io.flutter.view.AccessibilityBridge;
...@@ -183,7 +182,7 @@ public class XFlutterView extends FrameLayout { ...@@ -183,7 +182,7 @@ public class XFlutterView extends FrameLayout {
break; break;
case texture: case texture:
Log.v(TAG, "Internally using a FlutterTextureView."); Log.v(TAG, "Internally using a FlutterTextureView.");
FlutterTextureView flutterTextureView = new FlutterTextureView(getContext()); XFlutterTextureView flutterTextureView = new XFlutterTextureView(getContext());
renderSurface = flutterTextureView; renderSurface = flutterTextureView;
addView(flutterTextureView); addView(flutterTextureView);
break; break;
...@@ -400,7 +399,7 @@ public class XFlutterView extends FrameLayout { ...@@ -400,7 +399,7 @@ public class XFlutterView extends FrameLayout {
*/ */
@Override @Override
public boolean checkInputConnectionProxy(View view) { public boolean checkInputConnectionProxy(View view) {
return flutterEngine != null return flutterEngine != null&&view!=null
? flutterEngine.getPlatformViewsController().checkInputConnectionProxy(view) ? flutterEngine.getPlatformViewsController().checkInputConnectionProxy(view)
: super.checkInputConnectionProxy(view); : super.checkInputConnectionProxy(view);
} }
...@@ -676,7 +675,7 @@ public class XFlutterView extends FrameLayout { ...@@ -676,7 +675,7 @@ public class XFlutterView extends FrameLayout {
} }
public void release(){ public void release(){
if(textInputPlugin!=null){ if(textInputPlugin!=null){
// textInputPlugin.release(); textInputPlugin.release(this);
} }
} }
......
...@@ -28,8 +28,8 @@ public class XPlatformPlugin { ...@@ -28,8 +28,8 @@ public class XPlatformPlugin {
public static final int DEFAULT_SYSTEM_UI = View.SYSTEM_UI_FLAG_LAYOUT_STABLE public static final int DEFAULT_SYSTEM_UI = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
private Activity activity; private Activity activity;
private PlatformChannel platformChannel; private PlatformChannel platformChannel;
private PlatformChannel.SystemChromeStyle currentTheme; private PlatformChannel.SystemChromeStyle currentTheme;
private int mEnabledOverlays; private int mEnabledOverlays;
...@@ -95,26 +95,25 @@ public class XPlatformPlugin { ...@@ -95,26 +95,25 @@ public class XPlatformPlugin {
} }
}; };
public XPlatformPlugin( PlatformChannel platformChannel) { public XPlatformPlugin(PlatformChannel platformChannel) {
this.platformChannel = platformChannel; this.platformChannel = platformChannel;
this.platformChannel.setPlatformMessageHandler(mPlatformMessageHandler);
mEnabledOverlays = DEFAULT_SYSTEM_UI; mEnabledOverlays = DEFAULT_SYSTEM_UI;
} }
public void attachToActivity(Activity activity ){ public void attachToActivity(Activity activity ){
this.activity = activity; this.activity = activity;
this.platformChannel.setPlatformMessageHandler(mPlatformMessageHandler);
} }
/** /**
* Releases all resources held by this {@code PlatformPlugin}. * Releases all resources held by this {@code PlatformPlugin}.
* <p> * <p>
* Do not invoke any methods on a {@code PlatformPlugin} after invoking this method. * Do not invoke any methods on a {@code PlatformPlugin} after invoking this method.
*/ */
public void detachActivity() { public void detachActivity(Activity activity) {
this.activity=null; if (activity == this.activity) {
this.mPlatformMessageHandler=null; this.activity = null;
}
} }
private void playSystemSound(PlatformChannel.SoundType soundType) { private void playSystemSound(PlatformChannel.SoundType soundType) {
......
...@@ -72,6 +72,15 @@ public class XTextInputPlugin { ...@@ -72,6 +72,15 @@ public class XTextInputPlugin {
this.platformViewsController = platformViewsController; this.platformViewsController = platformViewsController;
// this.platformViewsController.attachTextInputPlugin(this); // this.platformViewsController.attachTextInputPlugin(this);
} }
public void release(View v){
if(mView!=null && mView.hashCode()==v.hashCode()){
mView= null;
}
}
public void updateView(View view){ public void updateView(View view){
mView = view; mView = view;
mImm = (InputMethodManager) view.getContext().getSystemService( mImm = (InputMethodManager) view.getContext().getSystemService(
...@@ -357,6 +366,8 @@ public class XTextInputPlugin { ...@@ -357,6 +366,8 @@ public class XTextInputPlugin {
String keyboardName = Settings.Secure.getString(mView.getContext().getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD); String keyboardName = Settings.Secure.getString(mView.getContext().getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
// The Samsung keyboard is called "com.sec.android.inputmethod/.SamsungKeypad" but look // The Samsung keyboard is called "com.sec.android.inputmethod/.SamsungKeypad" but look
// for "Samsung" just in case Samsung changes the name of the keyboard. // for "Samsung" just in case Samsung changes the name of the keyboard.
if(keyboardName==null) return false;
return keyboardName.contains("Samsung"); return keyboardName.contains("Samsung");
} }
......
...@@ -56,6 +56,7 @@ public class BoostFlutterActivity extends Activity ...@@ -56,6 +56,7 @@ public class BoostFlutterActivity extends Activity
// Default configuration. // Default configuration.
protected static final String DEFAULT_BACKGROUND_MODE = BackgroundMode.opaque.name(); protected static final String DEFAULT_BACKGROUND_MODE = BackgroundMode.opaque.name();
private static XPlatformPlugin sXPlatformPlugin;
public static Intent createDefaultIntent(@NonNull Context launchContext) { public static Intent createDefaultIntent(@NonNull Context launchContext) {
return withNewEngine().build(launchContext); return withNewEngine().build(launchContext);
...@@ -440,8 +441,8 @@ public class BoostFlutterActivity extends Activity ...@@ -440,8 +441,8 @@ public class BoostFlutterActivity extends Activity
@Nullable @Nullable
@Override @Override
public XPlatformPlugin providePlatformPlugin( @NonNull FlutterEngine flutterEngine) { public XPlatformPlugin providePlatformPlugin(@NonNull FlutterEngine flutterEngine) {
return new XPlatformPlugin( flutterEngine.getPlatformChannel()); return BoostViewUtils.getPlatformPlugin(flutterEngine.getPlatformChannel());
} }
/** /**
......
package com.idlefish.flutterboost.containers;
import com.idlefish.flutterboost.XPlatformPlugin;
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
class BoostViewUtils {
private static volatile XPlatformPlugin mInstance;
private BoostViewUtils() {
}
public static XPlatformPlugin getPlatformPlugin(PlatformChannel channel) {
if (mInstance == null) {
synchronized (BoostViewUtils.class) {
if (mInstance == null) {
mInstance = new XPlatformPlugin(channel);
}
}
}
return mInstance;
}
}
...@@ -230,7 +230,7 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer ...@@ -230,7 +230,7 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer
// Null out the platformPlugin to avoid a possible retain cycle between the plugin, this Fragment, // Null out the platformPlugin to avoid a possible retain cycle between the plugin, this Fragment,
// and this Fragment's Activity. // and this Fragment's Activity.
if (platformPlugin != null) { if (platformPlugin != null) {
platformPlugin.detachActivity(); platformPlugin.detachActivity(getContextActivity());
platformPlugin = null; platformPlugin = null;
} }
......
...@@ -14,13 +14,11 @@ import androidx.fragment.app.Fragment; ...@@ -14,13 +14,11 @@ import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import com.idlefish.flutterboost.FlutterBoost; import com.idlefish.flutterboost.FlutterBoost;
import com.idlefish.flutterboost.Utils;
import com.idlefish.flutterboost.XFlutterView; import com.idlefish.flutterboost.XFlutterView;
import com.idlefish.flutterboost.XPlatformPlugin; import com.idlefish.flutterboost.XPlatformPlugin;
import io.flutter.embedding.android.*; import io.flutter.embedding.android.*;
import io.flutter.embedding.engine.FlutterEngine; import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterShellArgs; import io.flutter.embedding.engine.FlutterShellArgs;
import io.flutter.plugin.platform.PlatformPlugin;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
...@@ -469,8 +467,7 @@ public class FlutterFragment extends Fragment implements FlutterActivityAndFragm ...@@ -469,8 +467,7 @@ public class FlutterFragment extends Fragment implements FlutterActivityAndFragm
@Nullable @Nullable
@Override @Override
public XPlatformPlugin providePlatformPlugin( @NonNull FlutterEngine flutterEngine) { public XPlatformPlugin providePlatformPlugin( @NonNull FlutterEngine flutterEngine) {
return new XPlatformPlugin(flutterEngine.getPlatformChannel()); return BoostViewUtils.getPlatformPlugin(flutterEngine.getPlatformChannel());
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment