flutter 混编打包成的插件包,flutter 下面的assets本地图片显示不了
flutter 混编打包成的插件包,flutter 下面的assets本地图片显示不了,正常运行混编的项目能显示出来,打包成插件的显示不出来,其他的功能正常
可以fork一下然后修改source sample,复现一下问题。这样就很容易debug了。
已经fork 了麻烦帮我看下
有时间帮我看看
你那个分支改动代码量太大了,看不到重点。你先说一下是Flutter中的dart代码获取不到assets,还是Android的Java代码获取不到assets?获取不到的演示代码在你的分支中是哪行?
crm/crm/.android/include_flutter.groovy这个文件找不到,编不过。你要不还是重新做个最小改动的复现吧。或者你能基于Flutter的sample指出哪里在shadow下会工作不正常,我也可以直接去看看调用关系。
嗯嗯,这个我提交没上去,flutter 代码找不到assets
那个android 被过滤提交了,没提交上去,现在应该有了
代码我没怎么改动,就插件里面提交了flutter demo
应该是Flutter的这个代码的问题。
AssetManager assetManager;
try {
assetManager = context.createPackageContext(context.getPackageName(), 0).getAssets();
} catch (NameNotFoundException e) {
assetManager = context.getAssets();
}
https://github.com/flutter/engine/blob/11fde578d53cd4f24abbeff4f151fc7f1a9e8c3f/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java#L281-L286
这里插件和宿主的PackageName是一样的,通过createPackageContext方法问系统创建Context,只能拿到正常安装的app的Context。所以它就拿到宿主的assets了。看这个代码,你可以通过override FlutterActivity的getPackageName方法,使它返回一个造成NameNotFoundException的名字,然后就可以正常拿到 FlutterActivity的assets了。
Shadow可以在ShadowContext里override这个createPackageContext方法来自动支持。但是这个需要假设插件中的代码使用宿主的packageName时都是想创建自己的Context。
你改过试了没,可以吗,通过override FlutterActivity的getPackageName方法 抛出异常崩溃
我没试过。你debug一下这个assetManager是不是宿主的就知道是不是这里的问题了。抛出的异常不是NameNotFoundException的话,你还可以override ShadowContext的createPackageContext方法,返回this。
抛出的异常是NameNotFoundException,override ShadowContext的createPackageContext方法 在哪里处理,是不是在 PluginDefaultProxyActivity PluginSingleInstance1ProxyActivity PluginSingleTask1ProxyActivity 里面覆盖?
插件里的Activity都是继承自ShadowContext的。你可以先确定一下context.createPackageContext的context是不是你的FlutterActivity。然后override那个类的createPackageContext就行了。
也可以直接修改: https://github.com/Tencent/Shadow/blob/master/projects/sdk/core/runtime/src/main/java/com/tencent/shadow/core/runtime/ShadowContext.java
大佬,还是不行,可能我搞错了,能不能帮我调试下
大佬,还是不行,可能我搞错了,能不能帮我调试下
不行是有Crash吗?先把Crash堆栈贴出来我看看。
Caused by: java.lang.RuntimeException: android.content.pm.PackageManager$NameNotFoundException: com.zhongcai.crm
at io.flutter.embedding.engine.loader.FlutterLoader.ensureInitializationComplete(FlutterLoader.java:283)
at io.flutter.embedding.engine.FlutterEngine.
看起就是FlutterEngine前面那个catch (NameNotFoundException e) 没什么用嘛,后面它还是去getApplicationInfo了。
你那就不要override getPackageName了,直接override createPackageContext方法返回this吧。严谨一点就判断传进来的包名和getPackageName返回值一样就return this。
嗯嗯,那我试试,在flutterActivivty 重写下createPackageContext return this
打包成功进入了,本地图片还是没有显示出来 package com.tencent.shadow.sample.plugin;
import android.content.Context; import android.content.pm.PackageManager; import android.os.Bundle; import android.text.TextUtils;
import androidx.annotation.NonNull;
import com.tencent.shadow.sample.plugin.statusbar.StatusBarCompat;
import io.flutter.embedding.android.FlutterActivity; import io.flutter.embedding.engine.FlutterEngine; import io.flutter.embedding.engine.FlutterEngineCache; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel;
public class FlutterAppActivity extends FlutterActivity {
public static CachedEngineIntentBuilder withCachedEngine(@NonNull String cachedEngineId) {
return new CachedEngineIntentBuilder(FlutterAppActivity.class, cachedEngineId);
}
String url;
@Override
protected void onCreate(Bundle savedInstanceState) {
String id = getIntent().getStringExtra("id");
url = "main?"+ (!TextUtils.isEmpty(id) ? id : "id=5837") + "&platform=android";
super.onCreate(savedInstanceState);
StatusBarCompat.setStatusBarColor(getWindow(),
getResources().getColor(android.R.color.transparent), true,true);
initChannel("crm");
}
// @Override // public String getInitialRoute() { // return TextUtils.isEmpty(url) ? super.getInitialRoute(): url; // }
@Override
public Context createPackageContext(String packageName, int flags) throws PackageManager.NameNotFoundException {
return this;
}
// @Override // public String getPackageName() { // return "com.zhongcai.crm"; // }
@Override
protected void onDestroy() {
super.onDestroy();
// FlutterHelper.onDestroy("crm"); }
private void initChannel(String engineId) {
FlutterEngine engine = FlutterEngineCache.getInstance().get(engineId);
MethodChannel nativeChannel = new MethodChannel(engine.getDartExecutor(), engineId);
nativeChannel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
switch (methodCall.method) {
case "close":
finish();
// 跳转原生页面
// Intent jumpToNativeIntent = new Intent(getActivity(), NativeActivity.class); // jumpToNativeIntent.putExtra("name", (String) methodCall.argument("name")); // //因为写的demo所以直接采用了魔法数字 方便文章中看的直观 // startActivityForResult(jumpToNativeIntent, 1001); break; default: result.notImplemented(); break; } } }); } }
https://github.com/flutter/flutter/blob/5c6605f70b945cff98670e64d0d6fc1417126da7/examples/image_list/lib/main.dart#L105
是这种加载assets吧?我可以调试下这个官方的example。
嗯嗯,好像没加载assets下面的 使用的是Image.asset
那你引用下你的代码中显示图片的代码是哪行。
我写的demo里面BottomBarWidget 里面 然后调用ImageHelper 中buildImage方法 ,里面用的image.asset 方法加载本地图片
我还是自己写了一下: https://github.com/shifujun/Shadow/commits/issue553 4个提交。
https://github.com/shifujun/Shadow/commit/4a5874e500f41bff1b043818aefd0ab957414687 是dart代码使用Image.asset显示图片。
最后一个提交前,sample-host运行效果:

最后一个提交把createPackageContextreturn this了,就正常了:

嗯嗯,我看看
你启动方式和我不一样 你是直接打开flutterAcitivy?
你可以在我代码的基础上改一下,看看能不能复现问题。我已经把flutter代码的aar上库了,不用再编译flutter部分了。 跟这个问题相关的只有传给FlutterEngine的context是哪个context的问题。
报错 Execution failed for task ':plugin-normal-apk:checkDebugAarMetadata'.
Could not resolve all files for configuration ':plugin-normal-apk:debugRuntimeClasspath'. Could not find com.example.my_flutter:flutter_debug:1.0. Searched in the following locations: - https://mirrors.tencent.com/nexus/repository/maven-public/com/example/my_flutter/flutter_debug/1.0/flutter_debug-1.0.pom - https://maven.pkg.github.com/tencent/shadow/com/example/my_flutter/flutter_debug/1.0/flutter_debug-1.0.pom - https://repo.maven.apache.org/maven2/com/example/my_flutter/flutter_debug/1.0/flutter_debug-1.0.pom - https://dl.google.com/dl/android/maven2/com/example/my_flutter/flutter_debug/1.0/flutter_debug-1.0.pom Required by: project :plugin-normal-apk > project :plugin-main-lib
Possible solution:
- Declare repository providing the artifact, see the documentation at https://docs.gradle.org/current/userguide/declaring_repositories.html
arr包总是导入不进去,这个有其他配置导致的吗 String storageUrl = System.env.FLUTTER_STORAGE_BASE_URL ?: "https://storage.googleapis.com" repositories { maven { url '../my_flutter_build_repo' } maven { url "$storageUrl/download.flutter.io" } }
不是maven的sample。直接在根目录执行./gradlew :sample-host:assembleDebug.
你要自己接入到其他项目里的话,可以参考:https://flutter.dev/docs/development/add-to-app/android/project-setup#manual-integration