Flutter Add Camera Permission Request for IOS

Find the info.plist file
And add the following :

<key>NSPhotoLibraryUsageDescription</key>
<string>App needs access to photo lib for profile images</string>

<key>NSCameraUsageDescription</key>
<string>To capture profile photo please grant camera access</string>

Flutter add Keystore to Github Actions as a Secret

View Full Article Here

https://proandroiddev.com/how-to-securely-build-and-sign-your-android-app-with-github-actions-ad5323452ce

2 Encoding the KeyStore

The next step treats the encoding of the KeyStore file. At this point, I assume you already own your KeyStore file. If you don’t have experience with app-signing, I suggest you take a look at the already mentioned documentation.

For encoding, we will make use of the popular Base64 encoding scheme. Base64 doesn’t stand for specific but various encoding schemes that allow you to convert binary data into a text representation.

In our case, the encoding of the KeyStorefile will allow us to store the file as text in our GitHub Secrets and later on in the GitHub Workflow process decode it back to our original KeyStore file.

The encryption step can easily be done by using OpenSSL. Download and install it, then navigate to the folder that contains your .jks file. Within the respective folder, execute the following command in your Unix terminal or just use Git bash on Windows:

openssl base64 < your_signing_keystore.jks | tr -d '\n' | tee your_signing_keystore_base64_encoded.txt

If everything went right, you should see a newly created file your_signing_keystore_base64_encoded.txt which contains a cryptic text that represents your KeyStore file.

3 The GitHub Actions Workflow

To build our CI/CD pipeline, we will use GitHub Actions. But before we can start implementing our Workflow, we first need to set up our GitHub secrets.

3.1 Set up your GitHub Secrets

In the following section, I assume that you used the identifiers from the mentioned build.gradle file. If you renamed the environment variables, you need to adapt the GitHub Secret names accordingly.

The first secret we will add is the encoded Base64 representation of our KeyStore file. To do so, go into your project's GitHub secrets and add a new GitHub Secret called KEYSTORE.

Copy the content from the your_signing_keystore_base64_encoded.txt file and paste it into the value field.

Next, create a secret that is called SIGNING_STORE_PASSWORD and contains your KeyStore password.

Afterward, create one that is called SIGNING_KEY_PASSWORD and contains your key alias password.

The last secret we need to add is called SIGNING_KEY_ALIAS and should contain the alias of your app.

3.2 The Workflow

Now that we set up our secrets, we can proceed with the actual Workflow.

Because we later want to be able to manually trigger our Workflow, we will define it as on: workflow_dispatch.

name: Build Release App Bundle

on: workflow_dispatch

To decode our encoded KeyStore file, we use the base64-to-file GitHub Action by Tim Heuer.

The GitHub Action allows us to define a parameter encodedString that will refer to our GitHub secret KEYSTORE. With the fileName parameter, we set the directory and filename of our KeyStore file in the temporary directory of our Workflow.

As we discussed in the first part of this article, our build.gradle will then be able to copy and use that file as the KeyStore.

DropdownButtonFormField & Validation from API

Requirements :
- API Service
- Object Model
Developer Recommendation : NB!!! - Use QuickType for your model.
(You need an already working api with a JSON response for quicktype) https://app.quicktype.io/
- DropDownMenuItem
NB!!! - The DropDownMenuItem must be wrapped in a form widget to implement validation.

HINT : Avoid casting variable types such as <String> or <List> or <Object> until your list is actually working. In the DropdownButtonFormField Snippet, you will see no types are declared.

Step 1 :
Configuration :
(On your page.dart or screen.dart)

You need to include these.
1 : Your Model from QuickType

// Model
import './model/support_fields_model.dart';
// API
import 'package:project_name/api/support_fields_service.dart';
// Includes
import 'package:flutter/material.dart';

DropdownButtonFormField Snippet :

child: Form(
  key: globalFormKey,
    Container(
      child: DropdownButtonFormField(
        hint: Text("-- Select Query --"),
        value: querySelect,
        validator: (querySelect) =>
            querySelect ==
                    "-- Select Query --"
                ? 'Select Query Required'
                : null,
        onChanged: (newValue) {
          setState(() {
            dropDownButtonCallback(
                newValue, "select_query");
          });
        },
        items: querySelectOptions
            .map<DropdownMenuItem>((map) {
          return DropdownMenuItem(
            value: map.name,
            child: Text(map.name),
          );
        }).toList(),
      ), // DropdownButtonFormField
    ), // Container
  ), // Form

Flutlab – Tabs

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // Application name
      title: 'Flutter Hello World',
      // Application theme data, you can set the colors for the application as
      // you want
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      // A widget which will be started on application startup
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final String title;

  const MyHomePage({@required this.title});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // The title text which will be shown on the action bar
        title: Text(title),
      ),
      body: Center(
        child: Container(
          child: DefaultTabController(
            length: 2,
            initialIndex: 0,
            child: Column(
              children: [
                TabBar(
                  labelColor: Colors.blue,
                  tabs: [
                    Tab(
                      text: 'OEM',
                    ),
                    Tab(
                      text: 'Hotshots',
                    )
                  ],
                ),
                Expanded(
                  child: TabBarView(
                    children: [
                      Column(children: [
                        Column(
                          children: <Widget>[
                            const ExpansionTile(
                              title: Text('Samsung (357)'),
                              children: <Widget>[
                                ListTile(
                                  title: Text('This is tile number 1'),
                                ),
                              ],
                            ),
                            const ExpansionTile(
                              title: Text('Huawei (4)'),
                              children: <Widget>[
                                ListTile(
                                  title: Text('Huawei P Smart 2021 NFC'),
                                ),
                                ListTile(
                                  title: Text('Huawei P40 lite 6/128GB Black'),
                                ),
                                ListTile(
                                  title: Text('MatePad T10 LTE 32GB Blue'),
                                ),
                                ListTile(
                                  title: Text('P40 lite 6/128GB Sakura Pink'),
                                ),
                              ],
                            ),
                            const ExpansionTile(
                              title: Text('Apple (21)'),
                              children: <Widget>[
                                ListTile(
                                  title: Text('This is tile number 1'),
                                ),
                              ],
                            ),
                            const ExpansionTile(
                              title: Text('Xiaomi (785)'),
                              children: <Widget>[
                                ListTile(
                                  title: Text('This is tile number 1'),
                                ),
                              ],
                            ),
                            const ExpansionTile(
                              title: Text('Oppo (138)'),
                              children: <Widget>[
                                ListTile(
                                  title: Text('This is tile number 1'),
                                ),
                              ],
                            ),
                          ],
                        ),
                      ]),
                      Center(
                        child: Text('Hotshots'),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Flutlab – Datatable

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // Application name
      title: 'Flutter Hello World',
      // Application theme data, you can set the colors for the application as
      // you want
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      // A widget which will be started on application startup
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final String title;

  const MyHomePage({@required this.title});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // The title text which will be shown on the action bar
        title: Text(title),
      ),
      body: Container(
        child: DataTable(
          columns: [
            DataColumn(label: Text('ID'), tooltip: 'Book identifier'),
            DataColumn(label: Text('Book')),
            DataColumn(label: Text('Author'))
          ],
          rows: [
            DataRow(cells: [
              DataCell(Text('#100')),
              DataCell(
                Text(
                  'Flutter Basics',
                  style: TextStyle(fontWeight: FontWeight.bold),
                ),
              ),
              DataCell(Text('David John')),
            ]),
            DataRow(cells: [
              DataCell(Text('#101')),
              DataCell(Text('Dart Internals')),
              DataCell(Text('Alex Wick')),
            ])
          ],
          showBottomBorder: true,
          headingTextStyle: TextStyle(fontWeight: FontWeight.bold, color: Colors.grey),
        ),
      ),
    );
  }
}

Flutter Display Name

Inside your pubpec.yml add the below

Dev Dependency add
flutter_launcher_name: "^0.0.1"

Then to set your name add
flutter_launcher_name:
name: "E-Centive"

dev_dependencies:
  flutter_launcher_name: "^0.0.1"
  
flutter_launcher_name:
  name: "E-Centive"

Flutter Setup

Step 1:
- Create a folder in your C drive called Flutter
- Download Flutter SDK and copy it into your Flutter folder
- Download Flutter here -> https://flutter.dev/docs/get-started/install/windows
- Extract Flutter into your folder. Then you remove the zip folder.

Step 2:
- Open your START MENU, and search "Edit Environment Variables For Your Account"
- Open it
- Assuming you copied your Flutter to C:\flutter
- In your environment Variables there is a Path option
- Edit Path and add a new variable and in there add the path to your Bin folder in Flutter
- C:\flutter\bin

Step 3:
- During install ensure you select Android SDK and HAXM and Android Virtual Device
- Download and Install Android Studio
- https://developer.android.com/studio

Step 4:
- Open your CMD or Power Shell and run "flutter doctor"
- If you get and ERROR for "Android licenses not accepted"
-- Run "flutter doctor --android-licenses"
-- Accept the licenses and run flutter doctor again to check

Step 5:
- Download and Install Java JDK
- https://www.oracle.com/java/technologies/javase-jdk16-downloads.html
- Open your START MENU, and search "Edit Environment Variables For Your Account"
- Now you are just going to add a new Variable
- Create a Folder in your C drive called Java
- Set you Variable Name to "JAVA_HOME"
- Set your Variable Value to "C:\Java\jdk-16.0.1" (Your Variable Value is the path to your Java JDK)

Step 6:
- In your C drive create a folder "flutter_projects"
- Open your C:\flutter_projects in CMD or Power Shell

(READ -> naming convention in flutter, all lower case and no spaces and no dashes)
- Run "flutter create project_name"

Step 7:
- Open your project in Android Studio. You will see an android icon when you search for it. Just open the folder for that project.
- You should be prompted for a flutter plugin. Accept and install the flutter plugin and then you can minimize your Android Studio.

Step 8:
- Open Visual Studio Code and install the Flutter and Dart Plugins
- You can find them by searching your packages with " publisher:"Dart Code" "