Author: Nafiz

  • 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
  • SwiftUI for Flutter developer – Video 1

    As a flutter developer, there are not many things you can do on Xcode since Flutter itself builds everything for you but why not learn some app development with Swift and Xcode.

    Swift is a deep and large language and I find it complex, when I learned Objective-C back in 2010 with Xcode 3.x that was very hard to start but later it became easy for me.

    Today there is no reason to start learning Objective-C over Swift unless you have a specific interest.

    For Flutter developers, if flutter is your first mobile framework and dart is the first language you may find Swift is complex and hard to start but the idea behind all the languages is the same you just have to learn the syntax. Of course, some languages have specific features for some reasons.

    I have a series of videos for Flutter developers who want to learn Swift App Development with Xcode. For running Xcode you just need a Mac computer. Running Xcode on any Mac will work, most of the time you don’t need a very powerful Mac.

    I’m very new to making videos and teaching programming to others, if you find anything wrong, just let me know in the comments. Also if you can subscribe to my channel and like the video, I’m gonna appreciate that.

    So this is the first video, there going to be a few more videos. We are going to make an app with a login page and list page. We also going to use some APIs which also we are going to make ourselves in PHP.

    https://www.youtube.com/watch?v=f4kXQBsZBoI
    Spread the love