• Genel
  • Flutter ile WebView kullanımı

Flutter üzerinden webview nasıl kullanılır,
Flutter’da webview javascript nasıl aktif edilir, tasarım olarak nasıl gözüküyor, IOS webview uygulama onaylıyor mu inceleyeceğiz.
İzleyemeden anlayamam diyenler için : YouTube linki

Bazı developerlar gerek uğraşmak istemediği için gerekse farklı nedenlerden dolayı websitesinin mobil uygulamasını başta kodlamak yerine mobil uyumlu websitesini bir app’e gömer ve yayına alır.
Etik veya değil bunu tartışmak yerine gelin mantığına ve nasıl olduğuna bakalım.

Yeni proje oluşturmak ve eklentiyi yüklemek.

# Yeni proje oluştur
$ flutter create my_webview_project

# proje dizinine gir ve vs Code ile aç
$ cd my_webview_project && code .

Eklenti için:

dependencies:
  flutter:
    sdk: flutter
  webview_flutter: ^0.3.14+1

IOS için Info.plist dosyasına gömülü görünümlerin önizlemesinin gelmesi için , uygun değerleri eklememiz gerekir

<key>io.flutter.embedded_views_preview</key>
<true/>

Android için ekstra bir ayar istemeye gerek yok (internete erişim iznini aldığınızı varsayıyorum)
main.dart

import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

void main() => runApp(MaterialApp(home: WebViewExample()));

class WebViewExample extends StatefulWidget {
  @override
  _WebViewExampleState createState() => _WebViewExampleState();
}

WebViewController controllerGlobal;

Future<bool> _exitApp(BuildContext context) async {
  if (await controllerGlobal.canGoBack()) {
    print("onwill goback");
    controllerGlobal.goBack();
  } else {
    Scaffold.of(context).showSnackBar(
      const SnackBar(content: Text("No back history item")),
    );
    return Future.value(false);
  }
}

class _WebViewExampleState extends State<WebViewExample> {
  final Completer<WebViewController> _controller =
      Completer<WebViewController>();

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () => _exitApp(context),
      child: Scaffold(
        appBar: AppBar(
          // This drop down menu demonstrates that Flutter widgets can be shown over the web view.
          actions: <Widget>[
            NavigationControls(_controller.future),
          ],
        ),
     
        body: Builder(builder: (BuildContext context) {
          return WebView(
            initialUrl: 'https://www.flutterforum.org/',
            javascriptMode: JavascriptMode.unrestricted,
            onWebViewCreated: (WebViewController webViewController) {
              _controller.complete(webViewController);
            },
            onPageFinished: (String url) {
              print('Page finished loading: $url');
            },
          );
        }),
      ),
    );
  }
}

class NavigationControls extends StatelessWidget {
  const NavigationControls(this._webViewControllerFuture)
      : assert(_webViewControllerFuture != null);

  final Future<WebViewController> _webViewControllerFuture;

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<WebViewController>(
      future: _webViewControllerFuture,
      builder:
          (BuildContext context, AsyncSnapshot<WebViewController> snapshot) {
        final WebViewController controller = snapshot.data;
        controllerGlobal = controller;

        return Text("");
      },
    );
  }
}

Bu şekilde kolaylıkla bir webview uygulama oluşturabilrsiniz.

Apple webview uygulama kabul ettirme

Apple, android gibi uygulama testi için algoritmik yapay zekalar değil gerçek kişiler tarafından testlerini sağlıyor. Durum böyleyken, webview uygulamayı olduğu gibi kabul ettirmek çok zor. Ama mümkünatı var elbette.
Yapmanız gereken webview yanında ekstra birşeyler eklemek. Yandan açılır menü, appbar, alt gezinme araçları, bildirim vs. Bu şekilde birkaç ekleme yaparsanız Apple’da kabul edecektir.

    Ekstra merak ettiğiniz birşey varsa, bilgim dahilindeyse sorarsanız eklerim.
    İyi çalışmalar.

      2 months later

      Bu WebView eklentisinde bir türlü arka planda oynatmayı kapatamadım hocam. Home tuşuna basınca Android ekranına gelince yani video arka planda oynamaya devam ediyor. Kodlarım şu şekilde hocam:

      import 'dart:async';
      import 'package:flutter/material.dart';
      
      import 'package:webview_flutter/webview_flutter.dart';
      
      class MyWebView extends StatelessWidget {
        final String title;
        final String selectedUrl;
      
      
        final Completer<WebViewController> _controller =
        Completer<WebViewController>();
      
        MyWebView({
          @required this.title,
          @required this.selectedUrl,
        });
      
      
      
        @override
        Widget build(BuildContext context) {
          return Scaffold(
              appBar: AppBar(
                title: Text(title),
              ),
              body: WebView(
                initialUrl: selectedUrl,
                javascriptMode: JavascriptMode.unrestricted,
      
      
                onWebViewCreated: (WebViewController webViewController) {
                  _controller.complete(webViewController);
                },
      
      
      
              ));
      
        }
      
      }

      Flutter selam hocam sizin yazdığınız kodlar ile
      final String title;
      final String selectedUrl;

      kullanarak başka bir sınıftan veri gönderemedim. StatelessWidget da bunu yapabilirken, StatefullWidget da bunu yapamadım malesef.

      başka bir sınıftan butona tıklanırken;

      onPressed: () {
      Navigator.of(context).push(MaterialPageRoute(
      builder: (BuildContext context) => MyWebView(
      title: “Google”,
      selectedUrl: “https://google.com”,
      )));
      şeklinde url gönderebiliyorum, anca StatefullWidget da bunu yapamadım :/ Kusura bakmayın hem programlamada hem de Flutter da yeniyim 🙂

      AlperDuzgun Başka sınıfta göndermek için o değişkenleri en üste yazıp diğer sayfada tanımlamanız yeterli.

      Flutter Cevap verdiğiniz için ve ilgilendiğiniz için çok teşekkür ederim hocam 🙂 Dediğim gibi yeni başladığım için kavramlar çok yabancı geliyor, örnekle gösterebilmeniz mümkün mü? Zaten size attığım örnekte en üstte yazılı ve dediğim gibi StatelessWidget da çalıştırabildim, ancak Statefull da çalışmıyor denedim :/ Çalışmıyordan kastım elbette bir yerde yanlış yapıyorum, sizin örneğiniz üzerinden gösterebilirseniz çok memnun olurum 🙂

        AlperDuzgun final String title;

        Burada statelessin içinde değil dışında dener misiniz ?

          Ne yapmak istediğinizi yazın hocam
          Ben size kod haline getirip atayım
          Daha başlardayken soğutmalım sizi bu işlerden 🙂

          Çok teşekkür ederim hocam ilginiz için, amacım aslında kod halinde almak değilde, stateless ın içinde tanımladığım string ve constructor ları statefull için de nasıl yapabileceğimi öğrenmek.

          Benim şuan uygulamamda iki adet route um var. Birinci Linkleri gönderen butonların bulunduğu ana sayfa, diğeri ise webview in bulunduğu ayrı bir route.

          Ana sayfada ki bir butona tıkladığımda örnek aşağıdaki gibi bir aksiyon için olsun.

          onPressed: () {
          Navigator.of(context).push(MaterialPageRoute(
          builder: (BuildContext context) => MyWebView(
          selectedUrl: “https://google.com”,
          )));

          Yukarıda ki selected url’deki değeri webview in bulunduğu route daki initialUrl: selectedUrl, ye göndermek istiyorum. Bunu Stateless Widget ile yapabiliyorum. String ve Constructor tanımlayarak oluyor. Ama işin içine StatefullWidget girince bu tanımlar çalışmıyor hocam. Ya yanlış yere yerleştiriyorum ya da StatefullWidget da bu tanımlar kullanılmıyor 🙁 Acemi olduğumdan tam bilmiyorum. Kısa ve öz olarak StatefullWidget larda Route lar arası String değer gönderirken farklı yöntemler mi kullanılıyor? Bu ya da başka yöntemler kullanılıyorsa da bana basit bir örnek ile gösterirseniz sevinirim 🙂 İleride belki başka arkadaşlarında işine yarar 🙂

          İlgi ve alakanız için teşekkür ederim 🙂

          AlperDuzgun import ‘dart:async’;

          
          import 'package:flutter/material.dart';
          import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
          
          const kAndroidUserAgent =
              'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Mobile Safari/537.36';
          
          String selectedUrl = '';
          
          // ignore: prefer_collection_literals
          
          void main() => runApp(VideoWebview());
          
          class VideoWebview extends StatefulWidget {
            
            String adres;
            VideoWebview({this.adres});
            @override
            State<StatefulWidget> createState() => MyAppState(adres: adres);
          }
          
          int _bottomNavIndex = 0;
          
          class MyAppState extends State {
          String adres;
          MyAppState({
            this.adres
          });
            @override
            void initState() {
              
              selectedUrl=adres;
              super.initState();
            }
            final flutterWebViewPlugin = FlutterWebviewPlugin();
          
            @override
            Widget build(BuildContext context) {
              return MaterialApp(
                  debugShowCheckedModeBanner: false,
                  home: Scaffold(
                      body: WebviewScaffold(
                      appBar: AppBar(
                        backgroundColor: Colors.blueAccent,
                        actions: <Widget>[
                          BottomAppBar(
                            color: Colors.blueAccent,
                            child: Row(
                              children: <Widget>[
                               
                                IconButton(
                                  icon: const Icon(Icons.autorenew),
                                  onPressed: () {
                                    flutterWebViewPlugin.reload();
                                  },
                                ),
                              ],
                            ),
                          ),
                        ],
                      ),
                      url: selectedUrl,
                      withZoom: true,
                      withLocalStorage: true,
                      hidden: true,
                      initialChild: Container(
                        color: Color.fromRGBO(34, 211, 95, 100),
                        child: const Center(
                          child: CircularProgressIndicator(),
                        ),
                      ),
                    ),
                  ));
            }
          }
          
          class MyHomePage extends StatefulWidget {
            const MyHomePage({Key key, this.title}) : super(key: key);
          
            final String title;
          
            @override
            _MyHomePageState createState() => _MyHomePageState();
          }
          
          class _MyHomePageState extends State<MyHomePage> {
            // Instance of WebView plugin
            final flutterWebViewPlugin = FlutterWebviewPlugin();
          
            // On destroy stream
            StreamSubscription _onDestroy;
          
            // On urlChanged stream
            StreamSubscription<String> _onUrlChanged;
          
            // On urlChanged stream
            StreamSubscription<WebViewStateChanged> _onStateChanged;
          
            StreamSubscription<WebViewHttpError> _onHttpError;
          
            StreamSubscription<double> _onProgressChanged;
          
            StreamSubscription<double> _onScrollYChanged;
          
            StreamSubscription<double> _onScrollXChanged;
          
            final _urlCtrl = TextEditingController(text: selectedUrl);
          
            final _codeCtrl = TextEditingController(text: 'window.navigator.userAgent');
          
            final _scaffoldKey = GlobalKey<ScaffoldState>();
          
            final _history = [];
          
            @override
            void initState() {
              super.initState();
          
              flutterWebViewPlugin.close();
          
              _urlCtrl.addListener(() {
                selectedUrl = _urlCtrl.text;
              });
          
              // Add a listener to on destroy WebView, so you can make came actions.
          
              // Add a listener to on url changed
              _onUrlChanged = flutterWebViewPlugin.onUrlChanged.listen((String url) {
                if (mounted) {
                  setState(() {
                    _history.add('onUrlChanged: $url');
                  });
                }
              });
          
              _onProgressChanged =
                  flutterWebViewPlugin.onProgressChanged.listen((double progress) {
                if (mounted) {
                  setState(() {
                    _history.add('onProgressChanged: $progress');
                  });
                }
              });
          
              _onScrollYChanged =
                  flutterWebViewPlugin.onScrollYChanged.listen((double y) {
                if (mounted) {
                  setState(() {
                    _history.add('Scroll in Y Direction: $y');
                  });
                }
              });
          
              _onScrollXChanged =
                  flutterWebViewPlugin.onScrollXChanged.listen((double x) {
                if (mounted) {
                  setState(() {
                    _history.add('Scroll in X Direction: $x');
                  });
                }
              });
          
              _onStateChanged =
                  flutterWebViewPlugin.onStateChanged.listen((WebViewStateChanged state) {
                if (mounted) {
                  setState(() {
                    _history.add('onStateChanged: ${state.type} ${state.url}');
                  });
                }
              });
          
              _onHttpError =
                  flutterWebViewPlugin.onHttpError.listen((WebViewHttpError error) {
                if (mounted) {
                  setState(() {
                    _history.add('onHttpError: ${error.code} ${error.url}');
                  });
                }
              });
            }
          
            @override
            void dispose() {
              // Every listener should be canceled, the same should be done with this stream.
              _onDestroy.cancel();
              _onUrlChanged.cancel();
              _onStateChanged.cancel();
              _onHttpError.cancel();
              _onProgressChanged.cancel();
              _onScrollXChanged.cancel();
              _onScrollYChanged.cancel();
          
              flutterWebViewPlugin.dispose();
          
              super.dispose();
            }
          
            @override
            Widget build(BuildContext context) {
              return WebviewScaffold(
                primary: true,
                key: _scaffoldKey,
                url: selectedUrl,
                appBar: AppBar(
                  title: const Text('Widget WebView'),
                ),
                withZoom: true,
                withLocalStorage: true,
                hidden: true,
                initialChild: Container(
                  color: Colors.redAccent,
                  child: const Center(child: CircularProgressIndicator()),
                ),
                bottomNavigationBar: BottomAppBar(
                  child: Row(
                    children: <Widget>[
                      IconButton(
                        icon: const Icon(Icons.arrow_back_ios),
                        onPressed: () {
                          flutterWebViewPlugin.goBack();
                        },
                      ),
                      IconButton(
                        icon: const Icon(Icons.arrow_forward_ios),
                        onPressed: () {
                          flutterWebViewPlugin.goForward();
                        },
                      ),
                      IconButton(
                        icon: const Icon(Icons.autorenew),
                        onPressed: () {
                          flutterWebViewPlugin.reload();
                        },
                      ),
                    ],
                  ),
                ),
              );
            }
          }

          Kodumuz bu
          Çağırmak içinse

          RaisedButton(
                              child: Text("Video Alternatif link"),
                              onPressed: () {
                                Navigator.push(
                                    context,
                                    MaterialPageRoute(
                                        builder: (context) => VideoWebview(
                                              adres: "https://www.youtube.com/",
                                            )));
                              },
                            )

          Selam hocam ellerinize sağlık, tam istediğim gibi çalıştı 😄 Ancak öğrenmek için kodlarınızı incelediğimde;

          Statefull class ının içinde belirlediğiniz değişken ve constructor ları ile State class ının içinde de kullanmışsınız, orasını yapmamıştım :/ Eksiğimi orada görmüş oldum. Ancak aşağıdaki resimde belirttiğim 2 ve 4 numaranın neden kullanıldığını anlamadım 🙁

          https://prnt.sc/qa3ea3

          AlperDuzgun Bunlar en başta gönderdiğiniz url adresini widgetlera göndermek için

            2 months later