Author: Smin Rana

  • How can I add item number on the cart icon on AppBar icon in Flutter

    Having a shopping cart icon on the right side of the AppBar on Flutter it’s not that hard, you can use basically a stack widget and inside the stack get IconButton and Positioned widgets.

    Here is the code and screenshot

    appBar: AppBar(
            // Here we take the value from the MyHomePage object that was created by
            // the App.build method, and use it to set our appbar title.
            title: Text(appBarTitle),
            actions: [
              Stack(
                children: [
                  IconButton(
                    onPressed: () {},
                    icon: const Icon(
                      Icons.shopping_cart_rounded,
                      size: 30,
                    ),
                  ),
                  Positioned(
                    top: 4,
                    right: 6,
                    child: Container(
                      height: 22,
                      width: 22,
                      decoration: const BoxDecoration(
                        shape: BoxShape.circle,
                        color: Colors.purple,
                      ),
                      child: const Center(
                          child: Text(
                        "2",
                        style: TextStyle(
                          fontSize: 12,
                          fontWeight: FontWeight.bold,
                        ),
                      )),
                    ),
                  ),
                ],
              ),
            ],
          )
    Spread the love
  • Download PDF in Flutter using Java on Android

    Downloading PDF file in the user download directory on Android is a very common feature, a lot of app uses PDF viewing and downloading feature.

    I hoped that flutter plugins could solve my problem but they didn’t. Fortunately, it was working great on iOS but it was not on android. So I decided to use my old java code in Flutter using Method Channel.

    First I tried two Flutter plugins one for permission and one for creating a directory.

    flutter pub add path_provider
    flutter pub add permission_handler

    Request permission was very easy and it worked on both iOS and Android

    Future<bool> _requestWritePermission() async {
        await Permission.storage.request();
        var r = await Permission.storage.request();
    
        return r.isGranted;
      }

    Since it was working on iOS, I decided to leave that code and separate platform code by importing ‘dart:io’ show Platform. Use this code on your onTap action.

    static const channel = MethodChannel('com.flutterframework/test');
    
    bool hasPermission = await _requestWritePermission();
    
    if (hasPermission) {
      if (Platform.isAndroid) {
        final int downloader = await channel.invokeMethod(
          'download',
          <String, String>{'title': title, 'pdf': pdf},
        );
        print(downloader);
      }
    
      if (Platform.isIOS) {
        var dir = await getApplicationDocumentsDirectory();
        if (dir != null) {
          String saveName = "$title.pdf";
          String savePath = "${dir.path}/$saveName";
          print(savePath);
    
          try {
            await Dio().download(pdf, savePath,
                onReceiveProgress: (received, total) {
              if (total != -1) {
                var percentage = (received / total * 100);
                print(percentage);
                if (percentage >= 100.0) {
                  ScaffoldMessenger.of(context).showSnackBar(
                      snackMessage(
                          'Download completed, please open Files app.'));
                }
              }
            });
            print("File is saved to download folder.");
          } on DioError catch (e) {
            ScaffoldMessenger.of(context).showSnackBar("Download error");
          }
        }
      }
    } else {
      ScaffoldMessenger.of(context).showSnackBar(filePermissionError);
    }
    

    Finally, the Java code, create a Java class in your main directory.

    package your_package;
    
    import android.app.DownloadManager;
    import android.content.Context;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Environment;
    
    public class DownloadHelper {
        public static void downloadPDF(Context context, String title, String pdfUrl) {
            try {
                DownloadManager.Request request = new DownloadManager.Request(Uri.parse(pdfUrl));
                request.setDescription("MyApp");
                request.setTitle(title);
                // in order for this if to run, you must use the android 3.2 to compile your app
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                    request.allowScanningByMediaScanner();
                    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
                }
    
                if (Build.VERSION.SDK_INT <= 17) {
                    request.setDestinationInExternalFilesDir(context, "Documents", "MyFolder/" + title + ".pdf");
                } else {
                    request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "MyFolder/" + title + ".pdf");
                }
    
                // get download service and enqueue file
                DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
                manager.enqueue(request);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            }
        }
    }
    

    Call that Java code from MainActivity, my MainActivity in Kotlin

    class MainActivity: FlutterActivity() {
        private val CHANNEL = "com.flutterframework/test";
        private lateinit var channel: MethodChannel
    
        override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
            super.configureFlutterEngine(flutterEngine)
            channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
            channel.setMethodCallHandler { call, result ->
                if (call.method == "download") {
                    val pdfTitle = call.argument<String>("title")
                    val pdfUrl = call.argument<String>("pdf")
                    Log.d("TAG", pdfTitle.toString());
                    Log.d("TAG", pdfUrl.toString());
    
                    DownloadHelper.downloadPDF(this, pdfTitle, pdfUrl);
                }
            }
        }
    }

    Download the complete project on GitHub

    Spread the love
  • API testing in Flutter

    API testing in Flutter

    It is very common to use API in our Flutter projects. Testing makes the Flutter project very easy to maintain, in this way you will save a lot of debugging time. Also when you have testing in place you can always check whether API working as expected. 

    Let’s create a simple API endpoint in PHP in our local server. If you don’t anything about PHP web development, It’s quite fun to work in PHP. This PHP file just responds with a JSON which has a list of Books, nothing complex right? 

    Server:

    <?php
    
    $b1 = ['title' => 'Beginning App Development with Flutter', 'author' => 'Rap Payne'];
    $b2 = ['title' => 'Beginning Flutter: A Hands On Guide to App Development', 'author' => 'Marco L. Napoli'];
    $b2 = ['title' => 'Flutter Apprentice', 'author' => 'Vincenzo Guzzi, Kevin D Moore, Vincent Ngo and Michael Katz'];
    
    $books = [$b1, $b2];
    
    header("content-type: application/json; charset=UTF-8");
    echo json_encode($books, JSON_PRETTY_PRINT);
    
    [
        {
            "title": "Beginning App Development with Flutter",
            "author": "Rap Payne"
        },
        {
            "title": "Flutter Apprentice",
            "author": "Vincenzo Guzzi, Kevin D Moore, Vincent Ngo and Michael Katz"
        }
    ]

    Flutter:


    Let’s first create a flutter project called “api_test”, we will use VSCode for the rest of the project.

    flutter create api_test

    Let’s add http package by this command, run on your terminal.

    flutter pub add http

    Go to your lib folder and create two files model.dart and service.dart.

    Model: 

    On the model.dart creates a book class.

    class Book {
      final String title;
      final String author;
    
      Book({required this.title, required this.author});
    }

    API:

    In the service, class create an abstract class like this 

    abstract class BookApi {
    import 'package:api_test/model.dart';
    import 'package:http/http.dart' as http;
    import 'dart:convert' as convert;
    
    abstract class BookApi {
      Future<List<Book>> books();
    }
    
    class BookService implements BookApi {
      Future<List<Book>> books() async {
        var url = Uri.parse('http://localhost/flutter/book.php');
        var response = await http.get(url);
    
        //print(response.body);
        if (response.statusCode == 200) {
          final listResponse = convert.jsonDecode(response.body) as List;
          List<Book> books = listResponse
              .map(
                (e) => Book(
                  title: e['title'],
                  author: e['author'],
                ),
              )
              .toList();
          return books;
        } else {
          print('Request failed with status: ${response.statusCode}.');
          return [];
        }
      }
    }
    
    

    create another class in the same file for the above BookApi method implementation

    Test:

    Create a test file called book_service_test.dart in test folder

    import 'package:api_test/model.dart';
    import 'package:api_test/service.dart';
    import 'package:flutter_test/flutter_test.dart';
    
    void main() {
      var book_service = BookService();
    
      test('book api', () async {
        final result = await book_service.books();
        print(" test $result");
    
        expect(result.isNotEmpty, true);
        expect(result, isA<List<Book>>());
      });
    }
    

    Our tests are passed when the list is not empty and list has a book type.

    Download the full source code

    Spread the love