Sunday, December 8, 2019

Flutter App Publish Management : Set app icon, change version name, change version code and set app name and app title

INTRODUCTION

This post will help you sort out the common things that you need to do to publish Flutter application. So, keep on reading...

How to set app icon in Flutter (Android) :

First of all, you need an app icon image, for that create or download an image you want to set as your app icon and then go to https://romannurik.github.io/AndroidAssetStudio/icons-launcher.html to convert them to the required size. You'll need to put these icons in different 'minmap' folders present in the 'res' folder of your flutter project. Note : put the icons in their respective size folder i.e, hdpi, xhdpi...etc.

In your project explorer, go to 'android-->app-->src-->main-->androidmanifest.xml', In this file, there is an application tag, inside that tag you need to put this code.

 android:icon="@mipmap/launcher_icon"


Replace the 'launcher_icon' with your image name. Now you can launch your app and it will have the icon image that you had set.

How to set the app name in Flutter (Android) :

 In your project explorer, go to 'android-->app-->src-->main-->androidmanifest.xml', In this file, there is an application tag, inside that tag you need to put this code.

 android:label="Your_app_name"

Replace the 'Your_app_name' with your app name and launch your application to see the name below the app icon as you have set in the above code.


How to set app title in Flutter (Android) :

App title is something which appears when you go into the multitask window. To set the app title, go to the first widget that you return in the main() function. And in the first MaterialApp widget set the app title as the code below :

 MaterialApp(
      title: 'Your_app_title',

Launch the application to see the change.


How to change the version code and version name :

When you first publish your app, the version name and version code of your app is by default set to '1.0.0'  and '1' respectively. But, on further development, when you want to update your app you need to have a new version name and version code. To do so follow this simple step :
Go to 'pubspec.yaml' file, and find this line of code :

version1.0.0+1

Here, the number ahead of  '+' symbol represents version name and the number after it represents version code.

So change that to :

version1.1.0+2

 So, now you know, on updates after it just keep on increasing the digits.



Saturday, December 7, 2019

AndroidX incompability bug and How to resolve it

androidx has different version for the compile (1.0.0-rc01) and runtime (1.0.0) classpath

Android dependency 'androidx.core:core' has different version for the compile (1.0.0) and runtime (1.0.1) classpath. You should manually set the same version via DependencyResolution

Android dependency 'androidx.lifecycle:lifecycle-runtime' has different version for the compile (2.0.0-rc01) and runtime (2.0.0) classpath.

INTRODUCTION

If you are facing errors like above, chances are that you have androidx incompatibility issue in your project. Don't worry you can cure your project by reading this post. So, keep reading...

What is Androidx and what is this incompatibility ?

In a nutshell, Android used to provide support to previous versions of android using support libraries, then there many support libraries over the years. It created confusion in the minds of developers. AndroidX came to rescue, Android introduced a single library to all support libraries.

Now if you have support library code in your app or in a package you are using and you are also having AndroidX code in the same way then it created the incompability.

How to resolve it ?

android.enableJetifier=true
android.useAndroidX=true

paste this above code in your 'gradle.properties' file.

 subprojects {
        project.configurations.all {
            resolutionStrategy.eachDependency { details ->
                if (details.requested.group == 'com.android.support'
                        && !details.requested.name.contains('multidex') ) {
                    details.useVersion "27.1.1"
                }
                if (details.requested.group == 'androidx.core'
                        && !details.requested.name.contains('androidx') ) {
                    details.useVersion "1.0.1"
                }
            }
        }
    }

paste this above code below 'dependencies' section in this 'build.gradle' file which is in the same folder as your 'gradle.properties' file.

Now run your project. What we have done is resolved the dependencies with our code.

Please comment below if this worked or didn't worked for you.







Splash Screen in Flutter Right Way and Full Screen

INTRODUCTION

Hello developers, hope you're doing well. What is splash screen ? splash screen is the screen which show up when icon of an app is clicked and main page isn't yet loaded. In this post, we will see how to implement splash screen in flutter. There are 2 ways to do it but we will cover the right and standard way. Al tough I will tell you what's the other way in the end of the post. So, keep reading...

 We can divide this process into just 3 easy steps :

1. Add image in the 'drawable' folder
2. Add meta tag in the AndroidManifest.xml
3. Add your image in the launch_background.xml

So, let's start with the first step :

1.  Add image in the 'drawable' folder

In your project explorer, go to 'android-->src-->main-->res-->drawable'. In this folder, add the image you wish to show in your app.

2. Add meta tag in the AndroidManifest.xml

 In your project explorer, go to 'android-->src-->main-->AndroidManifest.xml'. In this file,
<meta-data
                android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
                android:value="true" />
check if this meta-data tag is added in the activity tag.
This keeps the window background of the activity showing until Flutter renders its first frame. It can be removed if there is no splash screen

3. Add your image in the launch_background.xml 

In your project explorer, go to 'android-->src-->main-->res-->drawable-->launch_background.xml'.

Replace the code inside this file with this code,

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
   
 <item>
        <color android:color="#FFF"></color>
    </item>
    <item >
        <bitmap
            android:gravity="center|fill_vertical"
            android:src="@drawable/your_image_name" />
    </item>
   
</layer-list>

Replace 'your_image_name' with your splash screen image name without the extension (.jpg or .png etc). Also, this android:gravity is the attribute for changing the aspect ratio and fit of your splash screen. The above code will fix most of the use cases but if you need a different aspect ratio then visit : https://developer.android.com/reference/android/graphics/drawable/BitmapDrawable.html#attr_android:gravity and experiment with different gravity types.

That's it. You're done ! Run your app now and you'll have your splash screen.

The other way to implement a splash screen is to create a widget with the image and set that widget as the root widget of the app and after few seconds navigate to the main widget. But that is a workaround and not the standard way.

Try this and comment if this worked or didn't worked for you,






Saturday, November 23, 2019

Flutter Cached Network Image with Pinch To Zoom Image Feature

INTRODUCTION


Hey there, adding pinch to zoom feature to an image is very simple in Flutter. In this tutorial, we will learn how to show cached network image and also how to add pinch to zoom feature to it.

PACKAGES WE WILL USE :


1. cached_network_image: ^1.1.3
https://pub.dev/packages/cached_network_image

2. pinch_zoom_image: ^0.2.5
https://pub.dev/packages/pinch_zoom_image

Showing cached network image :


For this, we need to use "cached_network_image" package. Let's add it to our pubspec.yaml as well  and save(VS Code automatically runs 'flutter pub get' when you save')/run- 'flutter pub get' in the  terminal. 

Next, we import the package :
import 'package:cached_network_image/cached_network_image.dart';

Then, we write the new 'FullScreenPage' widget code :

class FullScreenPage extends StatelessWidget {
   @override
  Widget build(BuildContext context) {
       return CachedNetworkImage(
        imageUrl: "https:// Your image URL",
        imageBuilder: (context, imageProvider) => Container(
                   decoration: BoxDecoration(
                   image: DecorationImage(
                      image: imageProvider,
                      fit: BoxFit.fill,
            ),
          ),
        ),
        placeholder: (context, url) =>
         CircularProgressIndicator(),
        errorWidget: (context, url, error) => Icon(Icons.error),
      );
    
  }
}



That's it, you're done. This 'CachedNetworkImage' widget will cache the image automatically for you. 'Placeholder' and 'errorWidget' attributes are optional but they provide advance controls.


Adding Pinch To Zoom Feature to Image :


For this, we need to use "pinch_zoom_image" package. Let's add it to our pubspec.yaml as well  and save(VS Code automatically runs 'flutter pub get' when you save')/run- 'flutter pub get' in the  terminal. 

Next, we import the package :
import 'package:pinch_zoom_image/pinch_zoom_image.dart';

Now let's update the above code :

class FullScreenPage extends StatelessWidget {
   @override
  Widget build(BuildContext context) {
       return PinchZoomImage(
  image: CachedNetworkImage(
        imageUrl: "https:// Your image URL",
        imageBuilder: (context, imageProvider) => Container(
           child: Center(
              child: Text("Sample Text",
            style: TextStyle(
                color: Colors.black,
                backgroundColor: Colors.white38,
                fontSize: 18,
                fontWeight: FontWeight.w500,
                wordSpacing: 1.0,
                fontStyle: FontStyle.italic),
          )),
                   decoration: BoxDecoration(
                   image: DecorationImage(
                      image: imageProvider,
                      fit: BoxFit.fill,
            ),
          ),
        ),
        placeholder: (context, url) =>
         CircularProgressIndicator(),
        errorWidget: (context, url, error) => Icon(Icons.error),
      ),
  zoomedBackgroundColor: Color.fromRGBO(2402402401.0),
  hideStatusBarWhileZooming: true,
);
  }
}



We have just wrapped our 'CachedNetworkImage' widget with the 'PinchZoomImage' widget and Voila ! We have added pinch to zoom feature to our image.

** You can find the complete project here :

 https://github.com/chetan-acharya/SpaceWander

Also, if you have any query, please comment below.

Sunday, November 17, 2019

Flutter HTTP REST API call with full screen cached image from network URL with translucent text overlay and download image, ask for permission, save it locally and show toast feature tutorial with examples

INTRODUCTION

Hey Folks, I've been developing mobile apps since starting of my career and I like it a lot. But, with Flutter, It has become so much fun and easy that I'm in love with this SDK. In case you're a complete beginner, I will suggest you to go through my post where I've introduced Flutter and how to setup and create a project. *LINK  COMING SOON*

WHAT WE WILL LEARN ?

In this tutorial, what we are going to learn is mentioned below :
1. How to call an API in Flutter ?
2. How to create a full screen image widget ?
3. How to show a cached image from network URL ?
4. How to display a translucent text overlay on an image ?
5. How to align buttons at the bottom horizontally and spaced evenly ?
6. How to ask for permission in Flutter ?
7. How to download an image from network URL and save it locally ?
8. How to show toast in Flutter ?

Our final app will look like this :




PACKAGES WE WILL USE :
1. http: ^0.12.0+2 

2 .cached_network_image: ^1.1.3

3. permission_handler: ^4.0.0
https://pub.dev/packages/permission_handler

4. toast: ^0.1.5
https://pub.dev/packages/toast

5. path_provider: ^1.4.2
https://pub.dev/packages/path_provider

6. dio: ^3.0.4
https://pub.dev/packages/dio


Now that we have passed the introduction phase, let's jump right to code.


1. How to call an API in Flutter ?

For calling an API, we need to use "http" package. Let's add it to our pubspec.yaml and 
save(VS Code automatically runs 'flutter pub get' when you save')/run- flutter pub get in the terminal.

dependencies:
  flutter:
    sdkflutter
  http^0.12.0+2


Next, we import the package in our dart file where we want to call the API :
import 'package:http/http.dart' as http;

We will also need to import 'async' library :
import 'dart:async';

Time to write method to call the API :
  Future _CallAPI() async {
  http.Response _response;
 _response = await http.get('https://REPLACE IT WITH YOUR API URL');
    
    Map<Stringdynamic> jsonResponse =
        json.decode(_response.body);
String imageUrl = jsonResponse["url"];
//replace 'url' with your JSON response key

     }


Here, in the 'imageUrl' string you will get the value of the json element from the API response. You can customize it according to the structure of the JSON object of your response.


2. How to create a full screen image widget ?

class FullScreenPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        image: DecorationImage(
          image: NetworkImage('https://Your image URL'),
          fit: BoxFit.fill
        ) ,
      ),
    );
  }
}

Just using this widget inside your 'Scaffold' or 'MaterialApp' will result in a full screen image.
Feel free to use image from your local asset in the 'image' attribute of the 'DecorationImage' Widget.

3. How to show a cached image from network URL ?

 For this, we need to use "cached_network_image" package. Let's add it to our pubspec.yaml as well   and save(VS Code automatically runs 'flutter pub get' when you save')/run- flutter pub get in the   terminal. 

Next, we import the package :
import 'package:cached_network_image/cached_network_image.dart';

Then, we write the new 'FullScreenPage' widget code :

class FullScreenPage extends StatelessWidget {
   @override
  Widget build(BuildContext context) {
       return CachedNetworkImage(
        imageUrl: "https:// Your image URL",
        imageBuilder: (context, imageProvider) => Container(
                   decoration: BoxDecoration(
                   image: DecorationImage(
                      image: imageProvider,
                      fit: BoxFit.fill,
            ),
          ),
        ),
        placeholder: (context, url) =>
         CircularProgressIndicator(),
        errorWidget: (context, url, error) => Icon(Icons.error),
      );
    
  }
}



That's it, you're done. This 'CachedNetworkImage' widget will cache the image automatically for you. 'Placeholder' and 'errorWidget' attributes are optional but they provide advance controls.


4. How to display a translucent text overlay on an image ?

For this, we just need to add a few more lines of code in the above code and the result will be :

class FullScreenPage extends StatelessWidget {
   @override
  Widget build(BuildContext context) {
       return CachedNetworkImage(
        imageUrl: "https:// Your image URL",
        imageBuilder: (context, imageProvider) => Container(
           child: Center(
              child: Text("Sample Text",
            style: TextStyle(
                color: Colors.black,
                backgroundColor: Colors.white38,
                fontSize: 18,
                fontWeight: FontWeight.w500,
                wordSpacing: 1.0,
                fontStyle: FontStyle.italic),
          )),
                   decoration: BoxDecoration(
                   image: DecorationImage(
                      image: imageProvider,
                      fit: BoxFit.fill,
            ),
          ),
        ),
        placeholder: (context, url) =>
         CircularProgressIndicator(),
        errorWidget: (context, url, error) => Icon(Icons.error),
      );
  }
}


In the above code, we have just added a 'Text' widget to the 'child' attribute of the 'Container' widget.
All the 'TextStyle' attribute is optional but 'backgroundColor' attribute with 'Colors.white38' is required to give the translucent visibility. You can play with different white values like 'white54', 'white30' to increase or decrease transparency.


5. How to align buttons at the bottom horizontally and spaced evenly ?

@override
  Widget build(BuildContext context) {
  
    return Scaffold(
      
        body: Stack(children: [
      Center(
          child: FullScreenPage( )),
      Align(
        alignment: Alignment.bottomCenter,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: <Widget>[
            RaisedButton(
                onPressed: () => _changeImageQuality(),
                child:Icon(Icons.hdr_on)                   ),
            RaisedButton(
                onPressed: () => _refresh(), child: Icon(Icons.flight)),
            RaisedButton(
                onPressed: () => _showHideInfo(),
                child: Icon(Icons.speaker_notes_off)),
            RaisedButton(
                onPressed: () => _downloadImage(),
                child: Icon(Icons.file_download)),
          ],
        ),
      ),
    ])

        
        );
  }

As you can see in the above code, our 'FullScreenPage' widget is used in the 'Scaffold' widget which is the root widget of the screen. The buttons are placed in the 'Row' widget which will align them horizontally. You can play with MainAxisAlignment.spaceAround .There's also 'spaceEvenly' and 'spaceBetween', use these to arrange buttons differently.


6. How to ask for permission in Flutter ?

 For this, we need to use "permission_handler" package. Let's add it to our pubspec.yaml as well   and  save(VS Code automatically runs 'flutter pub get' when you save')/run- flutter pub get in the   terminal.

 Next, we import the package :
import 'package:permission_handler/permission_handler.dart';

Now, let's write the code to ask permission where it's needed :

List<PermissionGroup> permissionList = new List<PermissionGroup>();
    permissionList.add(PermissionGroup.storage);
    final Map<PermissionGroupPermissionStatus> status =
        await PermissionHandler().requestPermissions(permissionList);
    if (status.values.first == PermissionStatus.granted) {
       // this means permission is granted
       }

You can add multiple permissions in the 'permissionList' to ask all the required permissions of your app at once.
Also keep in mind that you need to add the permission in the 'AndroidManifest.xml' like this :
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

7. How to download an image from network URL and save it locally ?

For this, we need to use "path_provider" and "dio" package. Let's add it to our pubspec.yaml as well  and  save(VS Code automatically runs 'flutter pub get' when you save')/run- flutter pub get in the  terminal.

 Next, we import the packages :

import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';

Now, let's write the code to download an image :

         Dio dio = Dio();
    var dir = await getExternalStorageDirectories(type: StorageDirectory.downloads);
  await dio.download(imageUrl, "${dir}/Your_fileName.jpeg");

As simple as that, this above code will download your image to the given directory. Feel free to change the 'type' attribute of the 'getExternalStorageDirectories' function.

8. How to show toast in Flutter ?

And, we have reached the final step, which to show a toast in flutter.

For this, we need to use "toast" package. Let's add it to our pubspec.yaml as well  and  save(VS Code automatically runs 'flutter pub get' when you save')/run- flutter pub get in the  terminal.

Next, we import the package :
import 'package:toast/toast.dart';

And now, we will update the above written download code with this new code with toast :

  Dio dio = Dio();
      try {
        var dir = await getExternalStorageDirectories(type: StorageDirectory.downloads);
      String progressString = '';

        await dio.download(imageUrl, "${dir}/Your_filename.jpeg",
            onReceiveProgress: (rec, total) {
          setState(() {
            progressString = ((rec / total) * 100).toStringAsFixed(0+ "%";
          });
          if (progressString == "100%") {
            Navigator.pop(context);
            Toast.show("Download completed !", context,
                duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);
          }
        });
      } catch (e) {
        Toast.show(e.toString(), context,
            duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);
      }

And that it, as simple as that. You're now ready to create an app with these features.

** You can find the complete project here :

 https://github.com/chetan-acharya/SpaceWander


Also, if you have any query, please comment below.