🙂 İNSANLARIN EN HAYIRLISI INSANLARA FAYDALI OLANDIR 🙂

Ramazan HABER / FLUTTER / Android ve IOS Webview kullanımı 2023 yeni How to add a Webview

1-) FLUTTER - Android ve IOS Webview kullanımı 2023 yeni How to add a Webview

 

NotFoundPage ile

 

açıklama :  android ve ios için gelişmiş webview uygulaması. bu uygulamada ileri ve geri buttonu vardır. ve bu buttonları sadece ios için çıksın diyebilirsiniz. çünkü ios da geri tuşu yoktur. github linki aşağıdadır ve güncel kalmaktadır. uygulama ayrıca whatsap,pdf,mail gibi yönlendirmeleride yapar. pdf ise indirme işlemi için ios->safari açar android->chrome açar

 

EKRAN GÖRÜNTÜSÜ

 

kaynak : https://pub.dev/packages/webview_flutter

kaynak : https://pub.dev/packages/url_launcher

github : https://github.com/ramazanhaber/flutter_webview_2023

 

kur :

flutter pub add webview_flutter

flutter pub add webview_flutter_android

flutter pub add webview_flutter_wkwebview

flutter pub add url_launcher

flutter pub add connectivity

 

1. ADIM -> AndroidManifest.xml e şunları ekle

package="com.ramzey.egitimwebview5">

<
uses-permission android:name="android.permission.INTERNET" />
<
uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />



<
application
    
android:usesCleartextTraffic="true"
    
android:hardwareAccelerated="true"

 

 

 

 <intent-filter>
                <
action android:name="android.intent.action.VIEW" />
                <
category android:name="android.intent.category.DEFAULT" />
                <
category android:name="android.intent.category.BROWSABLE" />
                <
data android:scheme="http" />
                <
data android:scheme="https" />
                <
data android:mimeType="application/pdf" />
            </
intent-filter>

        </
activity>
        <
meta-data
            
android:name="flutterEmbedding"
            
android:value="2" />
    </
application>
    
    <
queries>
        <
intent>
            <
action android:name="android.intent.action.VIEW" />
            <
data android:scheme="sms" />
        </
intent>
        <
intent>
            <
action android:name="android.intent.action.VIEW" />
            <
data android:scheme="tel" />
        </
intent>
        <
intent>
            <
action android:name="android.intent.action.VIEW" />
            <
data android:scheme="https" />
        </
intent>
    </
queries>
</
manifest>

 

 

1.1. ADIM -> AndroidManifest.xml tam kod

<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <uses-permission android:name="android.permission.INTERNET" />

    <application

        android:usesCleartextTraffic="true"

        android:hardwareAccelerated="true"

        android:label="indomindo"

        android:name="${applicationName}"

        android:icon="@mipmap/ic_launcher">

 

        <activity

 

            android:name=".MainActivity"

            android:exported="true"

            android:launchMode="singleTop"

            android:theme="@style/LaunchTheme"

            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"

            android:hardwareAccelerated="true"

            android:windowSoftInputMode="adjustResize">

            <!-- Specifies an Android theme to apply to this Activity as soon as

                 the Android process has started. This theme is visible to the user

                 while the Flutter UI initializes. After that, this theme continues

                 to determine the Window background behind the Flutter UI. -->

            <meta-data

              android:name="io.flutter.embedding.android.NormalTheme"

              android:resource="@style/NormalTheme"

              />

            <intent-filter>

                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>

            </intent-filter>

            <intent-filter>

                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />

                <category android:name="android.intent.category.BROWSABLE" />

                <data android:scheme="http" />

                <data android:scheme="https" />

                <data android:mimeType="application/pdf" />

            </intent-filter>

        </activity>

        <meta-data

            android:name="flutterEmbedding"

            android:value="2" />

        <!-- Don't delete the meta-data below.

             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->

 

    </application>

    <queries>

        <intent>

            <action android:name="android.intent.action.VIEW" />

            <data android:scheme="sms" />

        </intent>

        <intent>

            <action android:name="android.intent.action.VIEW" />

            <data android:scheme="tel" />

        </intent>

        <intent>

            <action android:name="android.intent.action.VIEW" />

            <data android:scheme="https" />

        </intent>

    </queries>

</manifest>

 

1.1 ADIM -> info.plist e şunları ekle

<key>NSAppTransportSecurity</key>

 <dict>

 <key>NSAllowsArbitraryLoads</key><true/>

</dict>

<key>LSApplicationQueriesSchemes</key>

<array>

  <string>sms</string>

  <string>tel</string>

</array>

 

 

2. ADIM ->  ctrl+shift+f ile ara(in project) neyi "minsdkversion" u ve aşağdaki gibi yap o sayfadakiler

compileSdkVersion 33

 

minSdkVersion 19
targetSdkVersion 33

 

 

2.1 ADIM NotFoundPage.dart

 

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

import 'main.dart';

class NotFoundPage extends StatefulWidget {
  
const NotFoundPage({super.key});

  
@override
  
State<NotFoundPage> createState() => _NotFoundPageState();
}

class _NotFoundPageState extends State<NotFoundPage> {
  
Future<bool> _checkInternetConnection() async {
    
var connectivityResult = await (Connectivity().checkConnectivity());
    
if (connectivityResult == ConnectivityResult.none) {
      
Navigator.pushReplacement(
        
context,
        
MaterialPageRoute(builder: (context) => NotFoundPage()),
      );

      
return false;
    }

    
return true;
  }

  
@override
  
Widget build(BuildContext context) {
    
return Scaffold(
      appBar:
AppBar(
        title:
Text('İnternet Bağlantı Hatası'),
      ),
      body:
Center(
        child:
Column(
          mainAxisAlignment:
MainAxisAlignment.center,
          children: [
            
Text(
              
'İnternet bağlantınız yok!',
              style:
TextStyle(fontSize: 20),
            ),
            
SizedBox(height: 20),
            
ElevatedButton(
              onPressed: ()
async {
                
bool varmi = await _checkInternetConnection();
                
if (varmi == false) {
                }
else {
                  
Navigator.pushReplacement(
                    context,
                    
MaterialPageRoute(builder: (context) => MyApp()),
                  );

                }
              },
              child:
Text('Tekrar deneyin'),
            ),
          ],
        ),
      ),
    );
  }
}

 

 

 

3. ADIM -> main.dart

import 'dart:io';

import 'package:connectivity/connectivity.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:webview_flutter_android/webview_flutter_android.dart';
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';

import 'NotFoundPage.dart';

Future<void> main() async {
  
WidgetsFlutterBinding.ensureInitialized();

  runApp(
MyApp());
}

class MyApp extends StatefulWidget {
  
MyApp({Key? key}) : super(key: key);

  
@override
  
State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  
@override
  
Widget build(BuildContext context) {
    
return MaterialApp(
      title:
'roketnot',
      debugShowCheckedModeBanner:
false,
      theme:
ThemeData(
        primarySwatch:
Colors.blue,
      ),
      home:
WebPage(),
    );
  }
}

class WebPage extends StatefulWidget {
  
WebPage({Key? key}) : super(key: key);

  
@override
  
State<WebPage> createState() => _WebPageState();
}

class _WebPageState extends State<WebPage> {
  
Future<void> _launchUrl(String url) async {
    
if (!await launchUrl(Uri.parse(url))) {
      
throw 'Could not launch $url';
    }
  }

  
late WebViewController controller;

  
Future<bool> _checkInternetConnection() async {
    
var connectivityResult = await (Connectivity().checkConnectivity());
    
if (connectivityResult == ConnectivityResult.none) {
      
Navigator.pushReplacement(
        
context,
        
MaterialPageRoute(builder: (context) => NotFoundPage()),
      );

      
return false;
    }

    
return true;
  }

  
@override
  
void initState() {
    
super.initState();
    _checkInternetConnection();

    
late final PlatformWebViewControllerCreationParams params;
    
if (WebViewPlatform.instance is WebKitWebViewPlatform) {
      
params = WebKitWebViewControllerCreationParams(
        allowsInlineMediaPlayback:
true,
        mediaTypesRequiringUserAction: <
PlaybackMediaTypes>{},
      );
    }
else {
      
params = PlatformWebViewControllerCreationParams();
    }

    
controller = WebViewController.fromPlatformCreationParams(params);
    
if (controller.platform is AndroidWebViewController) {
      
AndroidWebViewController.enableDebugging(true);
      (
controller.platform as AndroidWebViewController)
          .setMediaPlaybackRequiresUserGesture(
false);
    }

    
controller = WebViewController()
      ..setJavaScriptMode(
JavaScriptMode.unrestricted)
      ..setBackgroundColor(
Color(0x00000000))
      ..setNavigationDelegate(
        
NavigationDelegate(
          onProgress: (
int progress) {
            
// Update loading bar.
          
},
          onPageStarted: (
String url) {},
          onPageFinished: (
String url) {
            setState(() {});
          },
          onWebResourceError: (
WebResourceError error) async {
            
bool hasConnection = await _checkInternetConnection();

          },
          onNavigationRequest: (
NavigationRequest request) async {

            
bool hasConnection = await _checkInternetConnection();
            
if (!hasConnection) {
              
return NavigationDecision.prevent;
            }

            
final url = request.url;
            
final isPDF = request.url.endsWith('.pdf');
            
if (isPDF) {
              
if (Platform.isAndroid) {
                
if (await canLaunch(request.url)) {
                  
await launch(
                    request.
url,
                    forceSafariVC:
false,
                    forceWebView:
false,
                    headers: <
String, String>{'header_key': 'header_value'},
                  );
                  
return NavigationDecision.prevent;
                }
else {
                  
return NavigationDecision.navigate;
                }
              }
else if (Platform.isIOS) {
                
if (await canLaunch(request.url)) {
                  
await launch(
                    request.
url,
                    forceSafariVC:
true,
                    headers: <
String, String>{'header_key': 'header_value'},
                  );
                  
return NavigationDecision.prevent;
                }
else {
                  
return NavigationDecision.navigate;
                }
              }
else {
                
return NavigationDecision.navigate;
              }
            }
else if (url.startsWith('https://www.youtube.com/')) {
  _launchUrl(
url);
  
return NavigationDecision.prevent;
}
else if (url.startsWith('whatsapp://send')) {
  _launchUrl(
url);
  
return NavigationDecision.prevent;
}
else if (url.startsWith('tel:')) {
  _launchUrl(
url);
  
return NavigationDecision.prevent;
}
else if (url.startsWith('mailto:')) {
  _launchUrl(
url);
  
return NavigationDecision.prevent;
}
else if (url.startsWith('https://www.facebook.com/')) {
  _launchUrl(
url);
  
return NavigationDecision.prevent;
}
else if (url.startsWith('https://twitter.com/')) {
  _launchUrl(
url);
  
return NavigationDecision.prevent;
}
else if (url.startsWith('https://www.instagram.com/')) {
  _launchUrl(
url);
  
return NavigationDecision.prevent;
}
else {
  
return NavigationDecision.navigate;


            }
          },
        ),
      )
      ..loadRequest(
Uri.parse(webLink));
  }

  
String webLink = 'https://roketnot.com/';


  
Future<bool> _onBack() async {
    
var value = await controller.canGoBack();
    
if (value) {
      
controller.goBack();
      
return false;
    }
else {
      showDialog(
          context:
context,
          builder: (context) =>
CupertinoAlertDialog(
            title:
Text('Uygulamadan çıkmak istiyor musunuz?'),
            actions: [
              
TextButton(
                child:
Text('Hayır'),
                onPressed: () =>
Navigator.pop(context),
              ),
              
TextButton(
                child:
Text('Evet'),
                onPressed: () {
                  
if (Platform.isAndroid) {
                    
SystemNavigator.pop();
                  }
else if (Platform.isIOS) {
                    exit(
0);
                  }
                },
              ),
            ],
          ));
      
return false;
    }
  }

  
Future<bool> _onForward() async {
    
var value = await controller.canGoForward();
    
if (value) {
      
controller.goForward();
      
return false;
    }
else {
      
return true;
    }
  }


  
@override
  
Widget build(BuildContext context) {
    
return Scaffold(
      body:
SafeArea(
        child:
WillPopScope(
          onWillPop:
_onBack,
          child:
Container(
            child:
Stack(
              children: [
                
WebViewWidget(
                  controller:
controller,
                ),
                
Positioned(
                  bottom:
20,
                  left:
10,
                  child:
Platform.isIOS
                      
? backButton()
                      :
Container(), // Android için SizeBox diyebilirsin kapanır
                
),
                
Positioned(
                  bottom:
20,
                  left:
70,
                  child:
Platform.isIOS
                      
? nextButton()
                      :
Container(), // Android için SizeBox diyebilirsin kapanır
                
),
              ],
            ),
          ),
        ),
      ),
    );
  }

  
InkWell nextButton() {
    
return InkWell(
      onTap:
_onForward,
      child:
Container(
        decoration:
BoxDecoration(
          color:
Colors.black.withOpacity(0.4),
          borderRadius:
BorderRadius.circular(10),
        ),
        padding:
EdgeInsets.all(12),
        child:
Icon(Icons.arrow_forward_ios, color: Colors.white),
      ),
    );
  }

  
InkWell backButton() {
    
return InkWell(
      onTap:
_onBack,
      child:
Container(
        decoration:
BoxDecoration(
          color:
Colors.black.withOpacity(0.4),
          borderRadius:
BorderRadius.circular(10),
        ),
        padding:
EdgeInsets.all(12),
        child:
Icon(Icons.arrow_back_ios, color: Colors.white),
      ),
    );
  }
}

 

 

 

 

 2024 Haziran 11 Salı
 341