Learn Flutter day 4 : Stateful Widgets

Hello Friends,

In the last blog we learn about stateless widgets, you can check the last blog here -

https://bigakash.blogspot.com/2021/03/learn-flutter-3rd-day-flutter.html

In this post we will learn Stateful widgets and will see some common widgets that are used in building layout/UI for flutter applications.

So Lets get started!!

Stateful Widgets -

Stateful widgets maintain state that can be changed based on user interactions.

To build these widgets we require two classes - 1) StatefulWidget & 2) State class.

Stateful Widget object itself is immutable and can be regenerated but the State object persists over the lifetime of widgets to hold state/information.

There is a shortcut to create a Stateful widget in Android Studio. Just type 'stful' outside the widget class that we had created in last post example and it will generate the boilerplate code for 2 classes one for stateless widget and one for its state. 

We will name this as StatefulCounter widget which will include a 'increment' button and a text which will show the count. The count will increase whenever we press the 'increment' button as below -

In the above code we have created a class _StatefulCounterState  which will maintain the state of the widget. The _increment() method will be called when the button is pressed.

In the _increment() method we are calling setState() which indicates that some of the internal state has changed, at this time widget rebuild itself by calling build() method.

In the build() method we are returning the parent Scaffold widget with the Container widget in its body property. This Container widget can have one child only. So we have created a Center widget which will center its child. As its child we have created a Column widget which will have 2 children -

1) Elevated Button  & 2) Text which will show the count.

Whenever we press this button the count will increase. 

Useful Widgets -

1) Image - This widget is used to show images on the UI. There are several ways or constructors are provided to load the image as -

1) Image.asset To obtain image from assets folder.

2) Image.network To obtain image from link or url.

3) Image.file To obtain image from a file or local path.

Image.asset(
"assets/images/image/exa.png",
fit: BoxFit.cover,
)

2) Stack - This widget can contain multiple children widgets one above the others.

  child: Stack(
children: <Widget>[
Container(
color: RED,
),
Container(
margin: EdgeInsets.symmetric(vertical: 10, horizontal: 20),
color: BLUE_LIGHT,
),
Container(
margin: EdgeInsets.symmetric(vertical: 30, horizontal: 60),
color: PURPLE,
),
],
);

3) Container -

Container contains only one child and it can manage its width, height and background also.

Container(
color: RED,
child: Text("Hello world"),
width: 200.0,
height: 100.0,
margin:
EdgeInsets.only(left: 10.0, right: 50.0, top: 10, bottom: 30)

)

4) Row & Column -

We have already used these two widgets in our examples. These widgets can be used to show multiple widgets in one direction, The Row-widget will show widget in the horizontal direction and the Column widget will show widget in the vertical direction. We can also use 'mainAxisAlignment' to control the alignment of the widgets.

So here we saw Stateful widget and some useful widgets. You can check the complete code on github repository below -

https://github.com/akash-bisariya/LearnFlutterApp

In next blog post we will see how to build the screen layouts in a flutter application using widgets.

Thanks for the reading... 

Learn Flutter Day 3 - Flutter Architecture & Widgets

Hi Friends,

Today we will learn about Flutter Architecture, how it works under the hood and then we will learn about Widgets to develop UI interfaces in Flutter.

Let's Get Started!!

Flutter Architecture-

Flutter is an open source cross platform development toolkit, It is designed to reuse the same code with different platforms like Android, iOS and Web.

In development phase Flutter applications runs in VM and then for release they are directly compiled to machine code.

Flutter is designed as an layer system with no layer has privileged access to the layer below.

Developers interact with the Flutter Framework. It provides a reactive framework written in Dart language which includes Foundational libraries like animation, painting etc, rendering layer (converting UI code into pixels) for rendering layouts, Widgets layer for rendering objects for layout and then Material & Cupertino library for implementing Material or iOS design language.

The core of the Flutter is Flutter Engine written in C++. It is reponsible for rasterizing composited scenes whenever a new frame needs to be painted. It provides the low level implementation of Flutter's core API, I/O, plugin architecture and Dart runtime and compile toolchain.

A platform specific Embedder coordinates with the underlying operating system for services like rendering surfaces, accessibility and input. It is written in language appropriate for the platform like Java/C++ for Android, Objective C/Objective C++ for iOS and macOS and C++ for Windows and Linux.

Flutter Widgets-

In Flutter widgets are everything from images, icons to layouts of the application. These are classes used to build UI elements. We can make complex widgets or layouts by composing simple widgets.

A widget declares its user interface by overiding the build() method. This method is designed to be fast so that it can be called by the framework whenever needed to render the frame. On each rendered frame Flutter can recreate only those parts of the UI where state has changed by calling that widget's build() method. Therefore it is important that build method should return quickly and heavy computational task should be done in asynchronous manner.

Widget State-

A widget can be of two types - Stateless or Stateful.

Widget that don't have any properties that can change over time like icon or label are Stateless Widget.

Widget that needs to change based on  user interaction or any other factors are Stateful widget.

There are various widget available in Flutter framework such as Center, Text, Row, Column, Stack, Container etc and some top level widget like MaterialApp and CupertinoApp.

Stateless Widget Example-

Now we will see how to create a stateless widget in the Flutter. Also we will learn including external package/library. Here we have used open source package named 'english_words' which contains some most used english words  and will display these words randomly on Home-Screen. Lets see main.dart file now -


In the above code first we create a main() function which simply calls the runApp() function that contains a widget MaterialApp. This widget is required to implement material design in application. It contains title property and home property which is used for routes or top level Navigator. Navigator helps in transitioning smoothly between screens. The home property calls the FlutterHome() class as below -


This class extends with StatelesWidget. As we know Stateless widget need to override build() method to display the widget in terms of other lower level widget.

This function will return the Scaffold class which is also a widget that provides a default App bar, a title and a body property that holds widget tree for the Homescreen. In body we have added a Column widget which displays its children in a vertical array. Then we have 2 Text widgets as children of the column widget, we will show random words in these 2 widgets.

Using External Package-

To use the external package 'english_words'we need to append - 'english_words: ^3.1.5-nullsafety.0'

to the dependencies list in pubspec.yaml file as below -

dependencies:
  flutter
:
    sdk
: flutter

  cupertino_icons
: ^1.0.2
  english_words
: ^3.1.5-nullsafety.0  

Now import this package in main.dart file as -

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

Now to get the random words we use WordPair.random().asPascalCase

This will return random word each time we click on hot reload or save the project.

So here we saw StateLess widget in action. You can check the code on github repository below

https://github.com/akash-bisariya/LearnFlutterApp

In next blog post we will see how to create Stateful widgets which change on any user interaction.

Thanks for reading... 





 


2nd day with Flutter - Dive into Dart!!

             


Hello Friends,

This is 2nd blog on this series #30DaysOfFlutter.

In the last blog we learn about how to install/setup the flutter. You can check my previous blog if you had not done it yet -

https://bigakash.blogspot.com/2021/02/1st-day-with-flutter-hello-flutter.html

I know I am not able to post blog regularly but I will try now to be regular for this series.

So Lets Gets Start!!

As we know for flutter development the programming language used is #Dart which is made by Google, so in this post we will dive into dart language and try to get familiar with it so that we can start writing flutter applications.

Dart is an object oriented programming language and its syntax is very much smilar to java or other object oriented langauge. We will see here some important concepts/features/syntax that differentiate it with other languages -

1. Main function - Each app must have a top level main function as shown below -

// Entry point of the application
void main() {
  var name = 'XYZ'; // Declare and initialize a  string variable.
  print(name); // Display name on console.
}

2. Functions - Function are usually created in following way -

Integer sun(Integer a, Integer b) {
  return a+b;
}
You just need to define return type, function name and function body to create a function. In Dart inserting the return type is even not required as it can use type inference to infer the return type.

Arrow function can also be used which is a function with only one line of code for example -

void printName(String name) => print(name);

3. Function Parameters - A function can have 2 types of parameters : Required & Optional
The optional parameter can be of two types - Named & Positional.

Lets see an example of 'Named' parameter first which are declared using curly brackets ({}).

/// Two optional parameters - firstName & lastName
void printHelloWorld({String firstName, String lastName}) { print(...) }
We can call this function as -
printHelloWorld(firstName: 'ABCD', lastName: 'EFGH');
Also If required you can make 'Named' parameters mandatory in a function by annotating them with @required attribute.

To declare 'Positional' parameters we need to use square brackets ([]). Following is an example of it -

String printMessage(String firstName, String lastNAme, [String message]) {
  var text = 'Hello $firstName $lastNAme';
if (message != null) { text = '$result $message!!';
} return text;
}
You can call this function with or without the 'message' parameter as -

printMessage('Akash', 'Bisariya');   // Hello Akash Bisariya
printMessage('Akash', 'Bisariya', 'Good evening')   // Hello Akash Bisariya GoodEvening!!
 

4. Variables - Dart does not have keywords public, protected and private. If an identifier starts with an underscore ( _ ) , it will be private to its library/dart app. You can also use 'var' keyword to create a variable -

var name = 'XYZ';
Dart language has some built in types -
  • numbers - It's further divided into 2 types - integers(int) & doubles(double)
  • strings - You can use either single '' or double "" quotes to create string.
  • booleans - 
  • lists (also known as arrays)
  • sets
  • maps
  • runes (for expressing Unicode characters in a string such as laughing emojis)
  • symbols (these are compile time constants)
5. Classes - You can define a class simply by using 'class' keyword followed by its name. You can create object of this class by using its constructor. To define class constructor we have 2 ways  -
1) Generative constructor & 2) Named constructor.
Follwing is an example of both -
class Person{ String name; String lastName; String this.age;

Person(this.name, this.lastName);  Person.newEntry(){this.age=0}   }
var p1 = new Person(2, 2);
var p2 = new Person.newEntry();
6. Mixins - Its a relatively new feature when comapring with other object oriented language like java.
By 'Mixin' we can reuse the class code in mulitple class hiearchies. Dart uses 'with' keyword for this feature.
class A extends object {
  .....

  void printMessgae() {
    print("This is mixin class")
  }
}
class B with A
  {
 ....
}

Now you can use the 'printMessage' method with the object of class B.

You can only extend the 'Mixin' class with Object class.


So friends these are some features of Dart language, we will use these features when developing the Flutter applications later.

For more detailed review of Dart language you can use the following official Doc -

https://dart.dev/guides/language/language-tour

Thanks for reading. From next post we will start developing the Flutter application.

1st day with flutter - Hello Flutter!!

Hi Friends,

I am here with you to share the First day experience of #30DaysOfFlutter.

In this series we will learn flutter together!!

So we will run today hello world application using flutter step by step.

First Step - Installation

This is the most tricky part for any new developer who is started learning Flutter. Go through following steps of installing flutter sdk.

First you need to go to flutter get-started link  as below -

https://flutter.dev/docs/get-started/install

You need to select you operating system here for downloading the Flutter installation bundle.

Here I will go for the windows OS but the steps for all the OS will be same.

After downloading extract the zip file and place the flutter folder in the desired directory for ex -  C:\src\flutter

Second Step - Add Environment Variable

This is the second important step before running our first Flutter application. 

In this we will add Flutter to Path environment variable. So first type 'env' in the start bar and select Edit Environment variables for your account.

Now under User variable  check if there is an entry called 'Path'

  • If the entry exists, append the full path to flutter\bin using ; as a separator from existing values.
  • If the entry doesn’t exist, create a new user variable named Path with the full path to flutter\bin as its value.

This step is also required to run Flutter commands in terminal.

Third Step - Run Flutter Doctor

From the terminal window goto the Flutter directory and run the following command -

This command will check your environment and displays a report of the status of our Flutter installation.

Final Step - Set up IDE :- Android Studio

Android studio offers a complete IDE experience for Flutter. You can also use others IDEs such as IntelliJ for an Android developer android studio is preferrable option. 

Start Android Studio and open Plugins from menu. Search for Flutter plugin and install that. Click yes when prompted to install the Dart plugin.

Now restart the Android Studio.

Create Flutter Project

Start a new Flutter project from File --> New.

Select Flutter application as the project type then click on Next.

Verify the Flutter Sdk path specifies the SDK's location. If this field is empty then provide the Flutter SDK path here - for example

C:\src\flutter

Enter the project name and then click on Next. 

Click finish.

Wait for android studio to create the project.

You may need to configure the Dart Sdk path if Dart not configure error is coming after the project creation.

You can provide Dart sdk path as below -

c:\src\flutter\bin\cache\dart-sdk

Run your First Flutter App now

In the android studio toolbar select the android device emulator before running your first app. You can also connect your own device via Usb and run the app on the device.

Yeah we have done that!!!


This is our first Flutter app running in the device. 

So we have completed the first day with flutter and running our sample flutter application.

You can find the source code on my github repository -

https://github.com/akash-bisariya/FirstFlutterApp

Thanks guys please do post any question or issue in the comments.





 


Hello Everyone,

Here I am exciting to share with you a new blog series based on #30DaysOfFlutter. I was waiting for the event like this to learn the Flutter from the basic since long time.

Flutter is basically an open source cross platform software development kit to develop applications not only for mobiles but also for desktop clients like Windows, Linux or Mac.

The course #30DaysOfFlutter is created by Google which says that by the end of 30 days we will have 1 month of Flutter experience and we will be on the way to create our first Flutter app.

I am really excited now:) 

It will be starting from 1st Feb 2020. Although the registrations are closed now for this course but I will be sharing all my learnings of this course on this blog over the next month onwards.

You can also let me know your views in the comments.

Thanks.

Retrofit Offline Caching or Response Caching in Android

Hello friends,

Today I am posting about the caching in Retrofit, a network library in Android.

As we know caching is controlled by the Http Headers which are sent by the server in response.
Here we a use a powerful feature of Retrofit library of Intercepting the Request or Reponses.Interceptors are used to intercept and modify the request and responses.

We can use the caching in two ways -

1. There are some cases when identical request is made within a small period of time such as within 60 seconds, in such cases we can use cache to fetch the same response of the request that was fetched last time instead of makig a new API request.

2.Also we can use the response that was last fetched so that we can show the same response when the device is offline.

First create "ResponseCachingInterceptor" class that implements the Interceptor interface from okhttp class as below.
This is basically used for caching the network response for a minute.

    private static class ResponseCachingInterceptor implements Interceptor {

        @Override
            public Response intercept(Chain chain) throws IOException {
            Response response = chain.proceed(chain.request());
            return response.newBuilder()
                    .removeHeader("Pragma")
                    .removeHeader("Access-Control-Allow-Origin")
                    .removeHeader("Vary")
                    .removeHeader("Cache-Control")
                    .header("Cache-Control", "public, max-age=60")
                    .build();
        }
    }

Here we overiding the intercept method.
The "chain.proceed" returns the reponse of the Api request and then we modify its headers to implement caching.
First we remove some headers such as "Pragma","Cache-Control" and others to remove misconfiguration in these headers.
And then we add the "Cache-Control" header that is responsible for the caching.Here we use "max-age=60" to set the time-frame of 60 seconds.

Now we will create the "OfflineResponseCacheInterceptor" for offline cache handling as below-

          private static class OfflineResponseCacheInterceptor implements Interceptor {
           @Override            
           public okhttp3.Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                NetworkInfo networkInfo =((ConnectivityManager) 
                (context.getSystemService(Context.CONNECTIVITY_SERVICE))).getActiveNetworkInfo();
                if (networkInfo==null) {
                    request = request.newBuilder()
                            .removeHeader("Pragma")
                            .removeHeader("Access-Control-Allow-Origin")
                            .removeHeader("Vary")
                            .removeHeader("Cache-Control")
                            .header("Cache-Control",
                                    "public, only-if-cached, max-stale= 60")
                            .build();
                }
                return chain.proceed(request);
            }
        }

Here again we remove some header and the override the "Cache-Control" header as 
"public, only-if-cached, max-stale=60"
Here max-stale=60 denotes the expiration of cached response.After that time it will return with status code = 504 if network is not available otherwise it will revalidate the response from the server.


Now you can apply these interceptors to the okhttpclient as given below-

OkHttpClient okHttpClient = new OkHttpClient.Builder()
        //Enable Response Caching
        .addNetworkInterceptor(new ResponseCachingInterceptor())
        //Enable Offline Response Caching
        .addInterceptor(new OfflineResponseCacheInterceptor())
        .cache(cache)
        .build();

And that's all we need to implement caching in Retrofit.
The above approach to caching is what Retrofit uses and it works pretty well if the right headers are sent.You just have to define the cache location and headers, everything is pretty much handled by the library.
   

Video Encryption and Decryption in Android

Hi friends,

Today I will write about the video encryption and decryption in android.
In video encryption we convert a sample video into a encrypted format that cannot be played by any media player. It can only be played after the decryption of that video using private key.
We encrypt the video by encrypting the small chunks of video one by one since the issue of memory constraint in Android.
If we had to encrypt the whole file we have to load the complete file into RAM which would have caused "OutOfMemoryEncryption" leading to crash.

Here is the Encrypter class i have created for Encrypting and Decrypting the video files.

In Encrypt method we have 4 parameters-

1.Secret Key      -----  key used to encrypt and decrypt file

2.AlgorithParameterSpec     ----  parameter required for algorithm used in this process

3.Input Stream   ------ Video file in Input stream format

4.Output Stream     ------   decrypted video file from the encrypted file

public class Encrypter {
    private final static int DEFAULT_READ_WRITE_BLOCK_BUFFER_SIZE = 1024;
    private final static String ALGO_VIDEO_ENCRYPTOR = "AES/CBC/PKCS5Padding";

    @SuppressWarnings("resource")
    public static void encrypt(SecretKey key, 
            AlgorithmParameterSpec paramSpec, InputStream in, OutputStream out)
            throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
            InvalidAlgorithmParameterException, IOException {
        try {
            Cipher c = Cipher.getInstance(ALGO_VIDEO_ENCRYPTOR);
            c.init(Cipher.ENCRYPT_MODE, key, paramSpec);
            out = new CipherOutputStream(out, c);
            int count = 0;
            byte[] buffer = new byte[DEFAULT_READ_WRITE_BLOCK_BUFFER_SIZE];
            while ((count = in.read(buffer)) >= 0) {
                out.write(buffer, 0, count);
            }
        } finally {
            out.close();
        }
    }
    @SuppressWarnings("resource")
    public static void decrypt(SecretKey key, AlgorithmParameterSpec paramSpec, 
            InputStream in, OutputStream out)
            throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
            InvalidAlgorithmParameterException, IOException {
        try {
            Cipher c = Cipher.getInstance(ALGO_VIDEO_ENCRYPTOR);
            c.init(Cipher.DECRYPT_MODE, key, paramSpec);
            out = new CipherOutputStream(out, c);
            int count = 0;
            byte[] buffer = new byte[DEFAULT_READ_WRITE_BLOCK_BUFFER_SIZE];
            while ((count = in.read(buffer)) >= 0) {
                out.write(buffer, 0, count);
            }
        } finally {
            out.close();
        }
    }
}

Now we use this class in our MainActivity to decrypt and encrypt video files.

Here I access video files of my phone and store in a arraylist named "listOfVideo".
I use "path" variable to store a particular video path saved our phone's sdcard.
Then i created 3 files namely  ---
1. InFile
2. OutFile
3. OutFile Dec

"InFile" is the video file we have to encrypted.
"OutFile" is the encrypted file afer encryption process.
"OutFile Dec" is the decrypted video file from the one we encrypted so we can play this video.

Then We use a automatically generated SecretKey "key" that we have generated using Algorithm "AES".Now we have to store this key to use it later in decrypting the video file. I store it in "keyData"
"key2" is generated from this "keyData" and used in decrypting the video we have encrypted.

At last we have to generate initialization vector "iv" to create  the AlgorithParameterSpec parameter of algorithm
And now we use the Encrpyt and Decrypt methods of Encryptor class to First encrypt the video and then decrypt it...............

public class MainActivity extends AppCompatActivity {
    private final static String ALGO_RANDOM_NUM_GENERATOR = "SHA1PRNG";
    private final static String ALGO_SECRET_KEY_GENERATOR = "AES";
    private final static int IV_LENGTH = 16;
    Cursor mVideoCursor;
    ArrayList<HashMap<String, String>> listOfVideo;
    @Override    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listOfVideo = new ArrayList();
        String[] videoColumns = {MediaStore.Video.Media.DATA,MediaStore.Video.Media.DURATION,
        MediaStore.Video.Media.SIZE,MediaStore.Video.Media.DISPLAY_NAME};
        mVideoCursor = getApplicationContext().getContentResolver().query
                (MediaStore.Video.Media.EXTERNAL_CONTENT_URI, videoColumns, null, null, null);
        mVideoCursor.moveToFirst();
        for (int i = 0; i < mVideoCursor.getCount(); i++) {
            listOfVideo.add(new HashMap<String, String>() {
                {
                    put("data", String.valueOf(mVideoCursor.getString( 
                    mVideoCursor.getColumnIndex(MediaStore.Video.Media.DATA))));
                    put("duration", String.valueOf(mVideoCursor.getString(
                    mVideoCursor.getColumnIndex(MediaStore.Video.Media.DURATION))));
                    put("displayName", String.valueOf(mVideoCursor.getString(
                    mVideoCursor.getColumnIndex(MediaStore.Video.Media.DISPLAY_NAME))));
                    put("size", String.valueOf(mVideoCursor.getString(
                    mVideoCursor.getColumnIndex(MediaStore.Video.Media.SIZE))));
                    mVideoCursor.moveToNext();

                }
            });
        }
 
        String path = listOfVideo.get(0).get("data");
        File inFile = new File(listOfVideo.get(0).get("data"));
        File outFile = new File(path.substring(0, path.lastIndexOf("/"))+"/enc_video.swf");
        File outFile_dec = new File(path.substring(0, path.lastIndexOf("/"))+"/dec_video.mp4");

        try {
            SecretKey key = KeyGenerator.getInstance(ALGO_SECRET_KEY_GENERATOR).generateKey();
            byte[] keyData = key.getEncoded();
            SecretKey key2 = new SecretKeySpec(keyData, 0, keyData.length, ALGO_SECRET_KEY_GENERATOR);  
            byte[] iv = new byte[IV_LENGTH];
            SecureRandom.getInstance(ALGO_RANDOM_NUM_GENERATOR).nextBytes(iv);
            AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);

            Encrypter.encrypt(key, paramSpec, 
            new FileInputStream(inFile), new FileOutputStream(outFile));
            Encrypter.decrypt(key2, paramSpec, 
            new FileInputStream(outFile), new FileOutputStream(outFile_dec));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    }




Thanks!!!!!!!
You can refer to my repository on Github for more source code -
 https://github.com/akash-bisariya/Video-Encryption-Decryption





Learn Flutter day 4 : Stateful Widgets

Hello Friends, In the last blog we learn about stateless widgets, you can check the last blog here - https://bigakash.blogspot.com/2021/03/l...