[Vuejs]-Intercepting Remote Image Requests in Flutter WebView and Fallback to Local Assets

0πŸ‘

βœ…

I wanted to share the solution I found for my issue.

Initially, someone (who? it disappeared) suggested hijacking the Flutter cache, but after some research, I found that this approach would be quite complex, given that it’s tied to some low-level features of Flutter and Android.

Instead, I used the flutter_inappwebview plugin. I use it to create a local server, allowing access to resources via a local URL.

On the VueJS side, I created a component that I named LazyImage in my Vue3 application, which behaves as follows: it tries to access the asset locally and if successful, it displays it. If not, it falls back to the remote URL.

Here is a proof of concept of what it looks like:

main.dart

import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';

InAppLocalhostServer localhostServer = new InAppLocalhostServer();

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await localhostServer.start();

  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {
  InAppWebViewController? webViewController;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: SafeArea(
          child: InAppWebView(
            initialOptions: InAppWebViewGroupOptions(
              crossPlatform: InAppWebViewOptions(),
            ),
            onWebViewCreated: (InAppWebViewController controller) {
              webViewController = controller;
              //This is where my vue webapp is located, it could be remote
              controller.loadUrl(urlRequest: URLRequest(url: Uri.parse("http://192.168.1.16:8080")));
            },
          ),
        ),
      ),
    );
  }
}

And on the Vue.js side:

LazyImage.vue

<template>
    <div>
      <img v-if="imageExists" :src="imageUrl" @error="loadFallbackImage" />
    </div>
</template>
  
<script>
export default {
  data() {
    return {
      imageUrl: 'http://localhost:8080/help/image.jpg',
      imageExists: true,
    };
  },
  methods: {
    loadFallbackImage() {
      this.imageUrl = require('@/assets/fallback_image.jpg');
    },
  },
};
</script>

So, in conclusion, the flutter_inappwebview plugin coupled with a custom Vue component helped me solve the issue of leveraging local assets over remote assets, if available, without the need to tamper with lower-level features.

Thank you all for your time and help. This question can now be considered closed.

Best Regards

Leave a comment