从 Android 动态功能模块将资产加载到 WebView

Posted

技术标签:

【中文标题】从 Android 动态功能模块将资产加载到 WebView【英文标题】:Load assets into WebView from Android Dynamic Feature Module 【发布时间】:2020-02-08 20:15:05 【问题描述】:

这个问题是关于当从 Google Play 加载应用程序时,将资产文件夹中的 html 内容加载到 android 动态功能模块内的 WebView 组件中。你怎么能那样做?现在,当我的代码使用 WebView.loadUrl 时,我收到“找不到文件”错误。

请注意,这个问题不是关于如何将 HTML 内容加载到主 Android 'app' 模块内的 WebView 中。这也不是关于如何让它在模拟器上本地运行 - 在动态功能模块中的模拟器上加载 HTML 内容时可以正常加载。

我的项目结构如下:

Top
   - app (parent module)
   | - src
     | - ...
   - module 1 (child module)
   | - src
     | - main
       | - assets (html is under this folder)
       | - java 
         | - org.example.fragment
           | - WebFragment

所以模块 1 是一个带有 Fragment 的 Android 功能模块,它加载了应该加载资产的 android.webkit.WebView。但从 Google Play 加载应用时,无法加载 HTML 内容。

下面是模块 1 中的片段代码,它应该加载 HTML:

public class WebFragment extends Fragment 

    protected static final String DEFAULT_LOCATION = "file:///android_asset/";

    protected WebView gameView;

    private static final String TAG = "MindGymWebFragment";

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
        SplitCompat.install(getContext());
        View v = inflater.inflate(R.layout.fragment_web_mindgym, container, false);
        try 
            String gameToOpen = this.getArguments().getString("gameToOpen");
            gameView = v.findViewById(R.id.memory_game_view);
            setupSettings();
            boolean isMemory = "Memory".equals(gameToOpen);
            boolean isDestress = "DeStress".equals(gameToOpen);
            if (isMemory) 
                gameView.loadUrl(DEFAULT_LOCATION + "memory/memory.html");
             else if (isDestress) 
                gameView.loadUrl(DEFAULT_LOCATION + "breathe/breathing.html");
            
            MainActivity mainActivity = (MainActivity) getActivity();
            mainActivity.unselectHomeTab();
            if (isMemory || isDestress) 
                mainActivity.setDailyOnABar(getString(org.brahmakumaris.beezone.R.string.mind_gym));
            

         catch (Exception e) 
            Log.e(TAG, "Cannot initializa game", e);
        
        return v;
    

    protected void setupSettings() 
        WebSettings settings = gameView.getSettings();
        settings.setLoadWithOverviewMode(true);
        settings.setUseWideViewPort(true);
        settings.setAllowFileAccess(true);
        settings.setAllowContentAccess(true);
        settings.setAllowFileAccessFromFileURLs(true);
        settings.setAllowUniversalAccessFromFileURLs(true);
        settings.setBlockNetworkImage(false);
        settings.setBlockNetworkLoads(false);
        settings.setLoadsImagesAutomatically(true);
        settings.setDomStorageEnabled(true);
        settings.setLoadWithOverviewMode(true);
        settings.setjavascriptEnabled(true);
        settings.setMediaPlaybackRequiresUserGesture(false);
    

    @Override
    public void onDestroy() 
        gameView.destroy();
        gameView = null;
        super.onDestroy();
    


那么:如何从 Google Play 提供的动态功能模块加载 HTML?

更新 1:如果将 html 资源复制到 app/src/main/assets 文件夹,上面的代码将起作用 - 但这显然不是我们想要的。从 Google Play 下载模块时,模块 1 的 webview 应该能够访问模块 1 的 assets 文件夹。

【问题讨论】:

【参考方案1】:

经过大量研究,我在互联网上找到了这个:

https://chromium.googlesource.com/chromium/src.git/+/master/docs/android_dynamic_feature_modules.md

限制 DFM 有以下限制:

WebView:我们不支持 WebView 的 DFM。如果您的功能被 WebView 你不能把它放到 DFM 中。

因此您不能在动态功能模块中使用 WebView。

【讨论】:

但它适用于网页 URL。它只为本地 html 文件提供 FILE NOT FOUND 消息。 @SagarYadav 是正确的。然而我的意图是加载本地 html 文件。 谢谢@gil.fernandes。只是为了确认您的评论,您的意思是,带有 Web URL 的 WebView 在动态功能中工作,而带有本地 URL 的 WebView 在动态功能中不起作用,对吗? @SagarYadav 是的,这是我目前的理解。 在我的情况下,它甚至没有加载 WebUrl。它崩溃说:android.content.res.Resources$NotFoundException:资源 ID #0x7e070017

以上是关于从 Android 动态功能模块将资产加载到 WebView的主要内容,如果未能解决你的问题,请参考以下文章

为远程 html 页面从 Android 中的本地资产加载 jQuery

Android SDK Webview加载不在资产文件夹中的本地文件

来自资产的 Android WebView JavaScript

Android Google Maps v2 从资产中的图像加载 OverlayTile

Android:使用 Webview 从资产加载大图像

无法从 Windows 上的资产 index.android.bundle 加载脚本