Closed Notzuonotdied closed 3 years ago
看了源码,不需要反射也可以解决:
args
中存入一个参数--aot-shared-library-name=so的路径
,这样子引擎初始化的时候,拿到的就是自定义的so的路径了。原理解析:
shellArgs.add("--" + AOT_SHARED_LIBRARY_NAME + "=" + aotSharedLibraryName);
// Most devices can load the AOT shared library based on the library name
// with no directory path. Provide a fully qualified path to the library
// as a workaround for devices where that fails.
shellArgs.add(
"--"
+ AOT_SHARED_LIBRARY_NAME
+ "="
+ applicationInfo.nativeLibraryDir
+ File.separator
+ aotSharedLibraryName);
AOT_SHARED_LIBRARY_NAME
,虚拟机在解析参数的时候,会优先加载最前的参数,然后逐个尝试load。明天看看
看了源码,不需要反射也可以解决:
- 在
args
中存入一个参数--aot-shared-library-name=so的路径
,这样子引擎初始化的时候,拿到的就是自定义的so的路径了。原理解析:
shellArgs.add("--" + AOT_SHARED_LIBRARY_NAME + "=" + aotSharedLibraryName); // Most devices can load the AOT shared library based on the library name // with no directory path. Provide a fully qualified path to the library // as a workaround for devices where that fails. shellArgs.add( "--" + AOT_SHARED_LIBRARY_NAME + "=" + applicationInfo.nativeLibraryDir + File.separator + aotSharedLibraryName);
- 这一块的代码其实传了两次
AOT_SHARED_LIBRARY_NAME
,虚拟机在解析参数的时候,会优先加载最前的参数,然后逐个尝试load。
你好,没看明白你的方法。新版本的flutter下,属性名不一致,FlutterLoader没有aotSharedLibraryName, 没看明白你是怎么解决的。
看了源码,不需要反射也可以解决:
- 在
args
中存入一个参数--aot-shared-library-name=so的路径
,这样子引擎初始化的时候,拿到的就是自定义的so的路径了。原理解析:
shellArgs.add("--" + AOT_SHARED_LIBRARY_NAME + "=" + aotSharedLibraryName); // Most devices can load the AOT shared library based on the library name // with no directory path. Provide a fully qualified path to the library // as a workaround for devices where that fails. shellArgs.add( "--" + AOT_SHARED_LIBRARY_NAME + "=" + applicationInfo.nativeLibraryDir + File.separator + aotSharedLibraryName);
- 这一块的代码其实传了两次
AOT_SHARED_LIBRARY_NAME
,虚拟机在解析参数的时候,会优先加载最前的参数,然后逐个尝试load。你好,没看明白你的方法。新版本的flutter下,属性名不一致,FlutterLoader没有aotSharedLibraryName, 没看明白你是怎么解决的。
这几天更新吧,办法还是有的。核心思想就是利用反射把补丁so包的路径给塞进去,让flutter加载就行了。你也可以自己试着实现,没必要照着我的来
Field field = FlutterLoader.class.getDeclaredField("flutterApplicationInfo");
field.setAccessible(true);
Class<?> flutterApplicationInfoClass = null;
if(field.get(flutterLoader) != null) {
flutterApplicationInfoClass = field.get(flutterLoader).getClass();
Field aotSharedLibraryNameField = flutterApplicationInfoClass.getDeclaredField("aotSharedLibraryName");
aotSharedLibraryNameField.setAccessible(true);
aotSharedLibraryNameField.set(field.get(flutterLoader), libPath);
field.set(flutterLoader, field.get(flutterLoader));
} else {
Method method = FlutterLoader.class.getDeclaredMethod("startInitialization", Context.class);
method.invoke(flutterLoader, context);
flutterApplicationInfoClass = field.get(flutterLoader).getClass();
Field aotSharedLibraryNameField = flutterApplicationInfoClass.getDeclaredField("aotSharedLibraryName");
aotSharedLibraryNameField.setAccessible(true);
aotSharedLibraryNameField.set(field.get(flutterLoader), libPath);
field.set(flutterLoader, field.get(flutterLoader));
}
这样解决了
我现在在想怎么把纯Flutter改成热更新
请问跳转flutter页面是怎么设置的?
我看了下,1.22.4版本版本的源码做了改动。
你这一块的代码已经没法使用了。
public static void reflect(String libPath) { try { FlutterLoader flutterLoader = FlutterLoader.getInstance(); Field field = FlutterLoader.class.getDeclaredField("aotSharedLibraryName"); field.setAccessible(true); field.set(flutterLoader, libPath); TinkerLog.i(TAG, "flutter patch is loaded successfully"); } catch (Exception e) { e.printStackTrace(); } }
这一块有计划修复么?
1.17源码 1.22.4源码
已经修复了
@heroghost 我上面发的“--AOT_SHARED_LIBRARY_NAME=“是可以通过ensureInitializationComplete的args传递进来的。
原因就在:
shellArgs.add("--" + AOT_SHARED_LIBRARY_NAME + "=" + aotSharedLibraryName);
// Most devices can load the AOT shared library based on the library name
// with no directory path. Provide a fully qualified path to the library
// as a workaround for devices where that fails.
shellArgs.add(
"--"
+ AOT_SHARED_LIBRARY_NAME
+ "="
+ applicationInfo.nativeLibraryDir
+ File.separator
+ aotSharedLibraryName);
上面的代码里面:shellArgs传递了两次--AOT_SHARED_LIBRARY_NAME
参数。
这里我们可以得出一个猜想:Flutter Engine在遇到传入多次--AOT_SHARED_LIBRARY_NAME
参数的时候,会通过循环的形式去判断哪一个路径可以load。(这一块我也验证过了,可以实现动态替换)
因此,可以得出如下结论:
想要替换,只需要将app.so的路径通过args数组,将“--AOT_SHARED_LIBRARY_NAME=<你的libapp.so的路径>”参数传递进来就可以实现动态替换了。
所以这一块不需要走反射了。
@heroghost 我上面发的“--AOT_SHARED_LIBRARY_NAME=“是可以通过ensureInitializationComplete的args传递进来的。
原因就在:
shellArgs.add("--" + AOT_SHARED_LIBRARY_NAME + "=" + aotSharedLibraryName); // Most devices can load the AOT shared library based on the library name // with no directory path. Provide a fully qualified path to the library // as a workaround for devices where that fails. shellArgs.add( "--" + AOT_SHARED_LIBRARY_NAME + "=" + applicationInfo.nativeLibraryDir + File.separator + aotSharedLibraryName);
上面的代码里面:shellArgs传递了两次
--AOT_SHARED_LIBRARY_NAME
参数。这里我们可以得出一个猜想:Flutter Engine在遇到传入多次
--AOT_SHARED_LIBRARY_NAME
参数的时候,会通过循环的形式去判断哪一个路径可以load。(这一块我也验证过了,可以实现动态替换)因此,可以得出如下结论:
想要替换,只需要将app.so的路径通过args数组,将“--AOT_SHARED_LIBRARY_NAME=<你的libapp.so的路径>”参数传递进来就可以实现动态替换了。
所以这一块不需要走反射了。
是的,源码里so路径还可以通过metadata配置
赞!那我先把这个issue关闭了
我看了下,1.22.4版本版本的源码做了改动。
你这一块的代码已经没法使用了。
这一块有计划修复么?
1.17源码
```java // Mutable because default values can be overridden via config properties private String aotSharedLibraryName = DEFAULT_AOT_SHARED_LIBRARY_NAME; public void ensureInitializationComplete( @NonNull Context applicationContext, @Nullable String[] args) { try { if (BuildConfig.DEBUG || BuildConfig.JIT_RELEASE) { } else { shellArgs.add("--" + AOT_SHARED_LIBRARY_NAME + "=" + aotSharedLibraryName); // Most devices can load the AOT shared library based on the library name // with no directory path. Provide a fully qualified path to the library // as a workaround for devices where that fails. shellArgs.add( "--" + AOT_SHARED_LIBRARY_NAME + "=" + applicationInfo.nativeLibraryDir + File.separator + aotSharedLibraryName); } } catch (Exception e) { Log.e(TAG, "Flutter initialization failed.", e); throw new RuntimeException(e); } } ```1.22.4源码
```java private FlutterApplicationInfo flutterApplicationInfo; public void ensureInitializationComplete( @NonNull Context applicationContext, @Nullable String[] args) { try { if (BuildConfig.DEBUG || BuildConfig.JIT_RELEASE) { } else { shellArgs.add( "--" + AOT_SHARED_LIBRARY_NAME + "=" + flutterApplicationInfo.aotSharedLibraryName); // Most devices can load the AOT shared library based on the library name // with no directory path. Provide a fully qualified path to the library // as a workaround for devices where that fails. shellArgs.add( "--" + AOT_SHARED_LIBRARY_NAME + "=" + flutterApplicationInfo.nativeLibraryDir + File.separator + flutterApplicationInfo.aotSharedLibraryName); } } catch (Exception e) { Log.e(TAG, "Flutter initialization failed.", e); throw new RuntimeException(e); } } ```