Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>smallsizedNew to Visual Studio Code? Get it now.
smallsized

smallsized

smallsized

|
1 install
| (0) | Free
hello
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Android Practicals:

1:A Simple Calculator

activity_main.xml

<EditText
    android:id="@+id/et1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Enter Number 1"
    android:inputType="numberDecimal"/>

<EditText
    android:id="@+id/et2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Enter Number 2"
    android:inputType="numberDecimal"/>

<TextView
    android:id="@+id/tvResult"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Result: "
    android:textSize="24sp"
    android:padding="20dp"/>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <Button android:id="@+id/btnAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Add" android:layout_weight="1"/>
    <Button android:id="@+id/btnSub" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Sub" android:layout_weight="1"/>
    <Button android:id="@+id/btnMul" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Mul" android:layout_weight="1"/>
    <Button android:id="@+id/btnDiv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Div" android:layout_weight="1"/>
</LinearLayout>

MainActivity.java

import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

EditText et1, et2;
TextView tvResult;
Button btnAdd, btnSub, btnMul, btnDiv;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    et1 = findViewById(R.id.et1);
    et2 = findViewById(R.id.et2);
    tvResult = findViewById(R.id.tvResult);
    btnAdd = findViewById(R.id.btnAdd);
    btnSub = findViewById(R.id.btnSub);
    btnMul = findViewById(R.id.btnMul);
    btnDiv = findViewById(R.id.btnDiv);

    btnAdd.setOnClickListener(this);
    btnSub.setOnClickListener(this);
    btnMul.setOnClickListener(this);
    btnDiv.setOnClickListener(this);
}

@Override
public void onClick(View v) {
    String num1Str = et1.getText().toString();
    String num2Str = et2.getText().toString();

    if(num1Str.isEmpty() || num2Str.isEmpty()){
        Toast.makeText(this, "Please enter numbers", Toast.LENGTH_SHORT).show();
        return;
    }

    double num1 = Double.parseDouble(num1Str);
    double num2 = Double.parseDouble(num2Str);
    double res = 0;

    try {
        int id = v.getId();
        if (id == R.id.btnAdd) res = num1 + num2;
        else if (id == R.id.btnSub) res = num1 - num2;
        else if (id == R.id.btnMul) res = num1 * num2;
        else if (id == R.id.btnDiv) {
            if(num2 == 0) throw new ArithmeticException("Div by Zero");
            res = num1 / num2;
        }
        tvResult.setText("Result: " + res);
    } catch (Exception e) {
        Toast.makeText(this, "Error: " + e.getMessage(), Toast.LENGTH_SHORT).show();
    }
}

}

Assignment 2: Currency Converter Files required: activity_main.xml, MainActivity.java

res/layout/activity_main.xml

XML

<EditText
    android:id="@+id/etAmount"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Enter Amount"
    android:inputType="numberDecimal"/>

<Spinner
    android:id="@+id/spinnerFrom"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="20dp"/>

<Spinner
    android:id="@+id/spinnerTo"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="20dp"/>

<Button
    android:id="@+id/btnConvert"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Convert"
    android:layout_marginTop="20dp"/>

<TextView
    android:id="@+id/tvResult"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="22sp"
    android:layout_marginTop="20dp"/>

MainActivity.java

import android.os.Bundle; import android.view.View; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

EditText etAmount;
Spinner spFrom, spTo;
Button btnConvert;
TextView tvResult;

// Currencies: INR, USD, EUR, JPY, GBP
String[] currencies = {"INR", "USD", "EUR", "JPY", "GBP"};
// Conversion rates relative to INR (Approx for demo)
// INR, USD (1$=83), EUR (1€=90), JPY (1¥=0.55), GBP (1£=105)
double[] ratesToINR = {1.0, 83.0, 90.0, 0.55, 105.0};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    etAmount = findViewById(R.id.etAmount);
    spFrom = findViewById(R.id.spinnerFrom);
    spTo = findViewById(R.id.spinnerTo);
    btnConvert = findViewById(R.id.btnConvert);
    tvResult = findViewById(R.id.tvResult);

    ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, currencies);
    spFrom.setAdapter(adapter);
    spTo.setAdapter(adapter);

    btnConvert.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(etAmount.getText().toString().isEmpty()) return;

            double amount = Double.parseDouble(etAmount.getText().toString());
            int fromIndex = spFrom.getSelectedItemPosition();
            int toIndex = spTo.getSelectedItemPosition();

            // Logic: Convert 'From' to INR, then INR to 'To'
            double amountInINR = amount * ratesToINR[fromIndex];
            double finalAmount = amountInINR / ratesToINR[toIndex];

            tvResult.setText(String.format("%.2f %s", finalAmount, currencies[toIndex]));
        }
    });
}

Assignment 3: Explicit Intent (Registration Form) - FIXED

  1. res/layout/activity_main.xml (No changes needed, but double-check the IDs match exactly)

XML

<EditText
    android:id="@+id/etName"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Enter Name"/>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Select Gender:"
    android:layout_marginTop="10dp"/>

<RadioGroup
    android:id="@+id/rgGender"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <RadioButton android:id="@+id/rbMale" android:text="Male" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
    <RadioButton android:id="@+id/rbFemale" android:text="Female" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
</RadioGroup>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Select Skills:"
    android:layout_marginTop="10dp"/>

<CheckBox android:id="@+id/cbCoding" android:text="Coding" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
<CheckBox android:id="@+id/cbDesign" android:text="Design" android:layout_width="wrap_content" android:layout_height="wrap_content"/>

<Button
    android:id="@+id/btnSubmit"
    android:text="Submit"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="20dp"/>
2. MainActivity.java (Updated with Safer Logic) Ensure your package name at the top matches your project exactly.

Java

package com.example.explicitintent; // CHANGE THIS to your actual package name

import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity { EditText etName; RadioGroup rgGender; CheckBox cbCoding, cbDesign; Button btnSubmit;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    etName = findViewById(R.id.etName);
    rgGender = findViewById(R.id.rgGender);
    cbCoding = findViewById(R.id.cbCoding);
    cbDesign = findViewById(R.id.cbDesign);
    btnSubmit = findViewById(R.id.btnSubmit);

    btnSubmit.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Validation: Prevent empty name
            if(etName.getText().toString().isEmpty()) {
                Toast.makeText(MainActivity.this, "Please enter name", Toast.LENGTH_SHORT).show();
                return;
            }

            Intent i = new Intent(MainActivity.this, ResultActivity.class);
            
            // 1. Pass Name
            i.putExtra("name", etName.getText().toString());
            
            // 2. Pass Gender (Safe Check)
            int selectedId = rgGender.getCheckedRadioButtonId();
            if (selectedId != -1) {
                RadioButton rb = findViewById(selectedId);
                i.putExtra("gender", rb.getText().toString());
            } else {
                i.putExtra("gender", "Not Selected");
            }

            // 3. Pass Skills
            StringBuilder skills = new StringBuilder();
            if(cbCoding.isChecked()) skills.append("Coding ");
            if(cbDesign.isChecked()) skills.append("Design");
            
            // If nothing checked
            String finalSkills = skills.length() > 0 ? skills.toString() : "None";
            i.putExtra("skills", finalSkills);

            startActivity(i);
        }
    });
}

} 3. AndroidManifest.xml (THE CRITICAL PART) This is where the crash usually happens. You must declare inside the tag.

XML

    <activity android:name=".ResultActivity" /> 
    </application>
4. ResultActivity.java Create a new Java Class named ResultActivity and paste this:

Java

package com.example.explicitintent; // CHANGE THIS to your package name

import android.os.Bundle; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity;

public class ResultActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_result); // Make sure this layout exists

    TextView tvData = findViewById(R.id.tvData);
    
    // Get data safely
    String name = getIntent().getStringExtra("name");
    String gender = getIntent().getStringExtra("gender");
    String skills = getIntent().getStringExtra("skills");

    tvData.setText("Registration Details:\n\nName: " + name + "\nGender: " + gender + "\nSkills: " + skills);
}

} 5. res/layout/activity_result.xml Make sure this file exists in your layout folder.

XML

<TextView
    android:id="@+id/tvData"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="22sp"
    android:textStyle="bold"
    android:text="Loading..."/>
Checklist to fix the crash:

Open AndroidManifest.xml.

Look for the tag.

Ensure is inside it.

Ensure package name at the top of Java files matches your project structure.

Assignment 4: Implicit Intent Files required: activity_main.xml, MainActivity.java

  1. res/layout/activity_main.xml

XML

<EditText android:id="@+id/etUrl" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="https://www.google.com"/>
<Button android:id="@+id/btnBrowser" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Open Browser"/>

<EditText android:id="@+id/etPhone" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Enter Number" android:inputType="phone"/>
<Button android:id="@+id/btnDial" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Dial Number"/>
2. MainActivity.java

Java

package com.example.implicitintent;

import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    EditText etUrl = findViewById(R.id.etUrl);
    Button btnBrowser = findViewById(R.id.btnBrowser);
    EditText etPhone = findViewById(R.id.etPhone);
    Button btnDial = findViewById(R.id.btnDial);

    // 1. Open Browser
    btnBrowser.setOnClickListener(v -> {
        String url = etUrl.getText().toString();
        if (!url.startsWith("http")) url = "http://" + url;
        Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        startActivity(i);
    });

    // 2. Open Dialer
    btnDial.setOnClickListener(v -> {
        String num = etPhone.getText().toString();
        Intent i = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + num));
        startActivity(i);
    });
}

}

  1. AndroidManifest.xml (THE CRITICAL PART) This is where the crash usually happens. You must declare inside the tag.

XML

    <activity android:name=".ResultActivity" /> 
    </application>

Assignment 5: Shared Preferences (Login) Files required: activity_main.xml, MainActivity.java

  1. res/layout/activity_main.xml

XML

<EditText android:id="@+id/etUser" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Username"/>
<EditText android:id="@+id/etPass" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Password" android:inputType="textPassword"/>

<Button android:id="@+id/btnLogin" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Login"/>
<Button android:id="@+id/btnLogout" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Logout" android:enabled="false"/>

<TextView android:id="@+id/tvStatus" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAlignment="center" android:paddingTop="20dp"/>
2. MainActivity.java

Java

package com.example.sharedpref;

import android.content.SharedPreferences; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity { EditText etUser, etPass; Button btnLogin, btnLogout; TextView tvStatus;

SharedPreferences sp;
int attemptCount = 0;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    etUser = findViewById(R.id.etUser);
    etPass = findViewById(R.id.etPass);
    btnLogin = findViewById(R.id.btnLogin);
    btnLogout = findViewById(R.id.btnLogout);
    tvStatus = findViewById(R.id.tvStatus);

    sp = getSharedPreferences("LoginPrefs", MODE_PRIVATE);

    // Check if already logged in
    String savedUser = sp.getString("username", null);
    if(savedUser != null){
        loggedInState(savedUser);
    }

    btnLogin.setOnClickListener(v -> {
        String u = etUser.getText().toString();
        String p = etPass.getText().toString();

        // Hardcoded credential check
        if(u.equals("admin") && p.equals("1234")) {
            SharedPreferences.Editor editor = sp.edit();
            editor.putString("username", u);
            editor.apply();
            loggedInState(u);
        } else {
            attemptCount++;
            Toast.makeText(this, "Wrong Credentials", Toast.LENGTH_SHORT).show();
            if(attemptCount >= 3) {
                btnLogin.setEnabled(false);
                tvStatus.setText("LOCKED: Too many attempts");
            }
        }
    });

    btnLogout.setOnClickListener(v -> {
        SharedPreferences.Editor editor = sp.edit();
        editor.clear();
        editor.apply();
        
        // Reset UI
        etUser.setVisibility(View.VISIBLE);
        etPass.setVisibility(View.VISIBLE);
        btnLogin.setVisibility(View.VISIBLE);
        btnLogout.setEnabled(false);
        tvStatus.setText("Logged Out");
        etUser.setText(""); etPass.setText("");
    });
}

private void loggedInState(String user){
    etUser.setVisibility(View.GONE);
    etPass.setVisibility(View.GONE);
    btnLogin.setVisibility(View.GONE);
    btnLogout.setEnabled(true);
    tvStatus.setText("Welcome, " + user);
}

}

Assignment 6: Notification (Fixed for Android 13+)

  1. AndroidManifest.xml Add the permission tag just before the tag.

XML

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/Theme.AppCompat.Light">
    <activity
        android:name=".MainActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
2. MainActivity.java This version checks if your phone is Android 13+. If it is, it asks for permission. If you click "Allow", the notification will work.

Java

package com.example.notificationapp;

import android.Manifest; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.widget.Button; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import androidx.core.content.ContextCompat;

public class MainActivity extends AppCompatActivity {

private static final String CHANNEL_ID = "my_channel_01";
private static final int PERMISSION_REQUEST_CODE = 101;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // 1. Create the channel immediately
    createNotificationChannel();

    Button btnNotify = findViewById(R.id.btnNotify);
    btnNotify.setOnClickListener(v -> {
        // 2. Check Permission for Android 13+
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.POST_NOTIFICATIONS}, PERMISSION_REQUEST_CODE);
            } else {
                showNotification();
            }
        } else {
            // Android 12 or lower doesn't need runtime permission
            showNotification();
        }
    });
}

private void showNotification() {
    // Intent to open Google when clicked
    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.google.com"));
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);

    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
            .setSmallIcon(android.R.drawable.ic_dialog_info) // Must use a valid icon
            .setContentTitle("New Alert")
            .setContentText("Tap to open Google")
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setContentIntent(pendingIntent)
            .setAutoCancel(true);

    // Show the notification
    NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
    try {
        notificationManager.notify(1, builder.build());
    } catch (SecurityException e) {
        Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show();
    }
}

private void createNotificationChannel() {
    // Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is new and not in the support library
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        CharSequence name = "My Notification Channel";
        String description = "Channel for app alerts";
        int importance = NotificationManager.IMPORTANCE_DEFAULT;
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
        channel.setDescription(description);
        
        // Register the channel with the system
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
}

} 3. res/layout/activity_main.xml (Simple button layout)

XML

<Button
    android:id="@+id/btnNotify"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Send Notification" />
How to Run/Test: Run the app.

Click the button.

Crucial Step: A dialog will pop up asking "Allow this app to send notifications?". Click Allow.

Click the button again (or it might appear immediately). You should see the icon in the status bar.

Assignment 7: File Storage (Fixed Layout & No Bar)

  1. MainActivity.java

Java

package com.example.filestorage; // CHANGE THIS to your package name

import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStreamReader;

public class MainActivity extends AppCompatActivity {

EditText etInput;
TextView tvDisplay;
String FILE_NAME = "myfile.txt";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // --- HIDE THE TOP BAR ---
    if (getSupportActionBar() != null) {
        getSupportActionBar().hide();
    }

    etInput = findViewById(R.id.etInput);
    tvDisplay = findViewById(R.id.tvDisplay);
    
    // Internal Storage Listeners
    findViewById(R.id.btnSaveInt).setOnClickListener(v -> saveInternal());
    findViewById(R.id.btnReadInt).setOnClickListener(v -> readInternal());

    // External Storage Listeners
    findViewById(R.id.btnSaveExt).setOnClickListener(v -> saveExternal());
    findViewById(R.id.btnReadExt).setOnClickListener(v -> readExternal());
}

// --- Internal Storage ---
private void saveInternal() {
    String data = etInput.getText().toString();
    if(data.isEmpty()) {
        Toast.makeText(this, "Enter text first", Toast.LENGTH_SHORT).show();
        return;
    }
    try {
        FileOutputStream fos = openFileOutput(FILE_NAME, MODE_PRIVATE);
        fos.write(data.getBytes());
        fos.close();
        Toast.makeText(this, "Saved to Internal", Toast.LENGTH_SHORT).show();
        etInput.setText(""); // Clear input
    } catch (Exception e) { e.printStackTrace(); }
}

private void readInternal() {
    try {
        FileInputStream fis = openFileInput(FILE_NAME);
        BufferedReader br = new BufferedReader(new InputStreamReader(fis));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) sb.append(line);
        tvDisplay.setText("Internal Content:\n" + sb.toString());
        fis.close();
    } catch (Exception e) { 
        tvDisplay.setText("No file found in Internal Storage");
    }
}

// --- External Storage ---
private void saveExternal() {
    String data = etInput.getText().toString();
    if(data.isEmpty()) {
        Toast.makeText(this, "Enter text first", Toast.LENGTH_SHORT).show();
        return;
    }
    try {
        // getExternalFilesDir(null) doesn't require extra permissions in Manifest for newer Android
        File file = new File(getExternalFilesDir(null), FILE_NAME);
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(data.getBytes());
        fos.close();
        Toast.makeText(this, "Saved to External", Toast.LENGTH_SHORT).show();
        etInput.setText("");
    } catch (Exception e) { e.printStackTrace(); }
}

private void readExternal() {
    try {
        File file = new File(getExternalFilesDir(null), FILE_NAME);
        FileInputStream fis = new FileInputStream(file);
        BufferedReader br = new BufferedReader(new InputStreamReader(fis));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) sb.append(line);
        tvDisplay.setText("External Content:\n" + sb.toString());
        fis.close();
    } catch (Exception e) { 
        tvDisplay.setText("No file found in External Storage");
    }
}

} 2. res/layout/activity_main.xml (Added ScrollView so buttons are never hidden)

XML

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="20dp"
    android:gravity="center_horizontal">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="File Storage Demo"
        android:textSize="24sp"
        android:textStyle="bold"
        android:layout_marginBottom="20dp"/>

    <EditText
        android:id="@+id/etInput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter text here..."
        android:background="#E0E0E0"
        android:padding="15dp"
        android:layout_marginBottom="20dp"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Internal Storage (Private)"
        android:textStyle="bold"
        android:layout_marginTop="10dp"/>
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:weightSum="2">
        
        <Button
            android:id="@+id/btnSaveInt"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Save"
            android:layout_marginEnd="5dp"/>
        
        <Button
            android:id="@+id/btnReadInt"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Read"
            android:layout_marginStart="5dp"/>
    </LinearLayout>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="External Storage (Public)"
        android:textStyle="bold"
        android:layout_marginTop="20dp"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:weightSum="2">

        <Button
            android:id="@+id/btnSaveExt"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Save"
            android:layout_marginEnd="5dp"/>

        <Button
            android:id="@+id/btnReadExt"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Read"
            android:layout_marginStart="5dp"/>
    </LinearLayout>

    <TextView
        android:id="@+id/tvDisplay"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:textSize="18sp"
        android:textAlignment="center"
        android:text="Result will appear here..."/>

</LinearLayout>

Assignment 8: SQLite Database Goal: CRUD operations for a Student Database. Structure: DBHelper.java (Database Logic) + MainActivity.java (UI Logic).

  1. DBHelper.java (Create this class)

Java

package com.example.sqlitedemo;

import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper;

public class DBHelper extends SQLiteOpenHelper {

public DBHelper(Context context) {
    super(context, "StudentDB.db", null, 1);
}

@Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL("create table Student(id TEXT primary key, name TEXT, marks TEXT)");
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("drop table if exists Student");
    onCreate(db);
}

public boolean insertData(String id, String name, String marks) {
    SQLiteDatabase db = this.getWritableDatabase();
    ContentValues cv = new ContentValues();
    cv.put("id", id);
    cv.put("name", name);
    cv.put("marks", marks);
    long result = db.insert("Student", null, cv);
    return result != -1;
}

public boolean updateData(String id, String name, String marks) {
    SQLiteDatabase db = this.getWritableDatabase();
    ContentValues cv = new ContentValues();
    cv.put("name", name);
    cv.put("marks", marks);
    Cursor cursor = db.rawQuery("select * from Student where id = ?", new String[]{id});
    if (cursor.getCount() > 0) {
        long result = db.update("Student", cv, "id=?", new String[]{id});
        return result != -1;
    }
    return false;
}

public boolean deleteData(String id) {
    SQLiteDatabase db = this.getWritableDatabase();
    Cursor cursor = db.rawQuery("select * from Student where id = ?", new String[]{id});
    if (cursor.getCount() > 0) {
        long result = db.delete("Student", "id=?", new String[]{id});
        return result != -1;
    }
    return false;
}

public Cursor getData() {
    SQLiteDatabase db = this.getWritableDatabase();
    return db.rawQuery("select * from Student", null);
}

} 2. MainActivity.java

Java

package com.example.sqlitedemo;

import android.database.Cursor; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity { EditText etId, etName, etMarks; Button btnAdd, btnUpdate, btnDelete, btnView; DBHelper DB;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    etId = findViewById(R.id.etId);
    etName = findViewById(R.id.etName);
    etMarks = findViewById(R.id.etMarks);
    
    btnAdd = findViewById(R.id.btnAdd);
    btnUpdate = findViewById(R.id.btnUpdate);
    btnDelete = findViewById(R.id.btnDelete);
    btnView = findViewById(R.id.btnView);
    
    DB = new DBHelper(this);

    btnAdd.setOnClickListener(v -> {
        String id = etId.getText().toString();
        String name = etName.getText().toString();
        String marks = etMarks.getText().toString();

        if(DB.insertData(id, name, marks))
            Toast.makeText(this, "Inserted", Toast.LENGTH_SHORT).show();
        else
            Toast.makeText(this, "Failed", Toast.LENGTH_SHORT).show();
    });

    btnUpdate.setOnClickListener(v -> {
        String id = etId.getText().toString();
        String name = etName.getText().toString();
        String marks = etMarks.getText().toString();

        if(DB.updateData(id, name, marks))
            Toast.makeText(this, "Updated", Toast.LENGTH_SHORT).show();
        else
            Toast.makeText(this, "No ID Found", Toast.LENGTH_SHORT).show();
    });

    btnDelete.setOnClickListener(v -> {
        String id = etId.getText().toString();
        if(DB.deleteData(id))
            Toast.makeText(this, "Deleted", Toast.LENGTH_SHORT).show();
        else
            Toast.makeText(this, "No ID Found", Toast.LENGTH_SHORT).show();
    });

    btnView.setOnClickListener(v -> {
        Cursor res = DB.getData();
        if(res.getCount() == 0) {
            Toast.makeText(this, "No Entry Exists", Toast.LENGTH_SHORT).show();
            return;
        }
        StringBuffer buffer = new StringBuffer();
        while(res.moveToNext()){
            buffer.append("ID :"+res.getString(0)+"\n");
            buffer.append("Name :"+res.getString(1)+"\n");
            buffer.append("Marks :"+res.getString(2)+"\n\n");
        }
        
        new AlertDialog.Builder(this)
            .setCancelable(true)
            .setTitle("Entries")
            .setMessage(buffer.toString())
            .show();
    });
}

} 3. res/layout/activity_main.xml

XML

<EditText android:id="@+id/etId" android:hint="ID" android:layout_width="match_parent" android:layout_height="wrap_content"/>
<EditText android:id="@+id/etName" android:hint="Name" android:layout_width="match_parent" android:layout_height="wrap_content"/>
<EditText android:id="@+id/etMarks" android:hint="Marks" android:layout_width="match_parent" android:layout_height="wrap_content"/>

<Button android:id="@+id/btnAdd" android:text="Insert" android:layout_width="match_parent" android:layout_height="wrap_content"/>
<Button android:id="@+id/btnUpdate" android:text="Update" android:layout_width="match_parent" android:layout_height="wrap_content"/>
<Button android:id="@+id/btnDelete" android:text="Delete" android:layout_width="match_parent" android:layout_height="wrap_content"/>
<Button android:id="@+id/btnView" android:text="View All" android:layout_width="match_parent" android:layout_height="wrap_content"/>

Assignment 8: SQLite Database (Fixed Layout & No Bar)

  1. DBHelper.java (This file handles the database logic. Create a new Java class named DBHelper and paste this.)

Java

package com.example.sqlitedemo; // CHANGE THIS to your package name

import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper;

public class DBHelper extends SQLiteOpenHelper {

public DBHelper(Context context) {
    super(context, "StudentDB.db", null, 1);
}

@Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL("create table Student(id TEXT primary key, name TEXT, marks TEXT)");
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("drop table if exists Student");
    onCreate(db);
}

public boolean insertData(String id, String name, String marks) {
    SQLiteDatabase db = this.getWritableDatabase();
    ContentValues cv = new ContentValues();
    cv.put("id", id);
    cv.put("name", name);
    cv.put("marks", marks);
    long result = db.insert("Student", null, cv);
    return result != -1; // returns true if insert is successful
}

public boolean updateData(String id, String name, String marks) {
    SQLiteDatabase db = this.getWritableDatabase();
    ContentValues cv = new ContentValues();
    cv.put("name", name);
    cv.put("marks", marks);
    Cursor cursor = db.rawQuery("select * from Student where id = ?", new String[]{id});
    if (cursor.getCount() > 0) {
        long result = db.update("Student", cv, "id=?", new String[]{id});
        return result != -1;
    }
    return false;
}

public boolean deleteData(String id) {
    SQLiteDatabase db = this.getWritableDatabase();
    Cursor cursor = db.rawQuery("select * from Student where id = ?", new String[]{id});
    if (cursor.getCount() > 0) {
        long result = db.delete("Student", "id=?", new String[]{id});
        return result != -1;
    }
    return false;
}

public Cursor getData() {
    SQLiteDatabase db = this.getWritableDatabase();
    return db.rawQuery("select * from Student", null);
}

} 2. MainActivity.java (Added code to hide the top bar)

Java

package com.example.sqlitedemo; // CHANGE THIS to your package name

import android.database.Cursor; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity { EditText etId, etName, etMarks; Button btnAdd, btnUpdate, btnDelete, btnView; DBHelper DB;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // --- FIX: HIDE THE TOP BAR ---
    if (getSupportActionBar() != null) {
        getSupportActionBar().hide();
    }

    etId = findViewById(R.id.etId);
    etName = findViewById(R.id.etName);
    etMarks = findViewById(R.id.etMarks);
    
    btnAdd = findViewById(R.id.btnAdd);
    btnUpdate = findViewById(R.id.btnUpdate);
    btnDelete = findViewById(R.id.btnDelete);
    btnView = findViewById(R.id.btnView);
    
    DB = new DBHelper(this);

    btnAdd.setOnClickListener(v -> {
        String id = etId.getText().toString();
        String name = etName.getText().toString();
        String marks = etMarks.getText().toString();

        if(id.isEmpty()) {
             Toast.makeText(this, "Enter ID", Toast.LENGTH_SHORT).show();
             return;
        }

        if(DB.insertData(id, name, marks)) {
            Toast.makeText(this, "Inserted Successfully", Toast.LENGTH_SHORT).show();
            clearFields();
        } else {
            Toast.makeText(this, "Insert Failed (ID might exist)", Toast.LENGTH_SHORT).show();
        }
    });

    btnUpdate.setOnClickListener(v -> {
        String id = etId.getText().toString();
        String name = etName.getText().toString();
        String marks = etMarks.getText().toString();

        if(DB.updateData(id, name, marks)) {
            Toast.makeText(this, "Updated Successfully", Toast.LENGTH_SHORT).show();
            clearFields();
        } else {
            Toast.makeText(this, "ID not found", Toast.LENGTH_SHORT).show();
        }
    });

    btnDelete.setOnClickListener(v -> {
        String id = etId.getText().toString();
        if(DB.deleteData(id)) {
            Toast.makeText(this, "Deleted Successfully", Toast.LENGTH_SHORT).show();
            clearFields();
        } else {
            Toast.makeText(this, "ID not found", Toast.LENGTH_SHORT).show();
        }
    });

    btnView.setOnClickListener(v -> {
        Cursor res = DB.getData();
        if(res.getCount() == 0) {
            Toast.makeText(this, "No Data Found", Toast.LENGTH_SHORT).show();
            return;
        }
        StringBuffer buffer = new StringBuffer();
        while(res.moveToNext()){
            buffer.append("ID : " + res.getString(0) + "\n");
            buffer.append("Name : " + res.getString(1) + "\n");
            buffer.append("Marks : " + res.getString(2) + "\n\n");
        }
        
        // Show data in a pop-up dialog
        new AlertDialog.Builder(this)
            .setCancelable(true)
            .setTitle("Student Records")
            .setMessage(buffer.toString())
            .setPositiveButton("OK", null)
            .show();
    });
}

private void clearFields() {
    etId.setText("");
    etName.setText("");
    etMarks.setText("");
}

} 3. res/layout/activity_main.xml (Added ScrollView so all 4 buttons are reachable)

XML

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="20dp"
    android:gravity="center_horizontal">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Student Database"
        android:textSize="24sp"
        android:textStyle="bold"
        android:layout_marginBottom="20dp"/>

    <EditText
        android:id="@+id/etId"
        android:hint="Enter Student ID"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="number"
        android:layout_marginBottom="10dp"/>

    <EditText
        android:id="@+id/etName"
        android:hint="Enter Student Name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textPersonName"
        android:layout_marginBottom="10dp"/>

    <EditText
        android:id="@+id/etMarks"
        android:hint="Enter Marks"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="numberDecimal"
        android:layout_marginBottom="20dp"/>

    <Button
        android:id="@+id/btnAdd"
        android:text="Insert Data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <Button
        android:id="@+id/btnUpdate"
        android:text="Update Data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <Button
        android:id="@+id/btnDelete"
        android:text="Delete Data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <Button
        android:id="@+id/btnView"
        android:text="View All Data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:backgroundTint="#4CAF50"/> </LinearLayout>

Assignment 9: Firebase Realtime Database.

CRITICAL PREREQUISITE: Before running this code, you must connect your Android Studio project to Firebase:

Go to Tools > Firebase.

Select Realtime Database > Get Started.

Click Connect to Firebase (Sign in to Google).

Click Add the Realtime Database SDK to your app (Accept Changes).

Important: Go to your Firebase Console (website) > Build > Realtime Database > Rules and set .read and .write to true (Test Mode).

Assignment 9: Employee Management (Firebase)

  1. AndroidManifest.xml (Add Internet permission)

XML

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/Theme.AppCompat.Light">
    <activity
        android:name=".MainActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
2. Employee.java (Create this new Java class for data structure)

Java

package com.example.firebasedemo; // Check Package Name

public class Employee { String id; String name; String role;

// Empty constructor is required for Firebase
public Employee() {
}

public Employee(String id, String name, String role) {
    this.id = id;
    this.name = name;
    this.role = role;
}

public String getName() { return name; }
public String getRole() { return role; }

} 3. MainActivity.java (Includes fix to hide top bar)

Java

package com.example.firebasedemo; // Check Package Name

import android.os.Bundle; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity;

// Firebase Imports import com.google.firebase.database.DataSnapshot; import com.google.firebase.database.DatabaseError; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.database.ValueEventListener;

public class MainActivity extends AppCompatActivity {

EditText etName, etRole;
TextView tvData;
DatabaseReference dbRef;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // --- HIDE TOP BAR ---
    if (getSupportActionBar() != null) {
        getSupportActionBar().hide();
    }

    etName = findViewById(R.id.etName);
    etRole = findViewById(R.id.etRole);
    tvData = findViewById(R.id.tvData);
    
    // Initialize Firebase
    // "Employees" is the name of the folder in the database
    dbRef = FirebaseDatabase.getInstance().getReference("Employees");

    // 1. INSERT DATA
    findViewById(R.id.btnAdd).setOnClickListener(v -> {
        String name = etName.getText().toString();
        String role = etRole.getText().toString();
        
        if(name.isEmpty() || role.isEmpty()){
            Toast.makeText(this, "Please fill all fields", Toast.LENGTH_SHORT).show();
            return;
        }

        // Generate unique key
        String id = dbRef.push().getKey();
        
        Employee emp = new Employee(id, name, role);
        
        // Save to Firebase
        dbRef.child(id).setValue(emp)
             .addOnSuccessListener(aVoid -> {
                 Toast.makeText(this, "Employee Added", Toast.LENGTH_SHORT).show();
                 etName.setText("");
                 etRole.setText("");
             })
             .addOnFailureListener(e -> {
                 Toast.makeText(this, "Failed: " + e.getMessage(), Toast.LENGTH_SHORT).show();
             });
    });

    // 2. READ DATA (Real-time Listener)
    dbRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            StringBuilder sb = new StringBuilder();
            sb.append("--- Employee List ---\n\n");
            
            // Iterate through all children in "Employees" node
            for(DataSnapshot ds : snapshot.getChildren()){
                Employee emp = ds.getValue(Employee.class);
                if(emp != null) {
                    sb.append("Name: ").append(emp.getName()).append("\n");
                    sb.append("Role: ").append(emp.getRole()).append("\n");
                    sb.append("----------------\n");
                }
            }
            tvData.setText(sb.toString());
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {
            Toast.makeText(MainActivity.this, "Error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
        }
    });
}

} 4. res/layout/activity_main.xml (Uses ScrollView to ensure everything is visible)

XML

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="20dp"
    android:gravity="center_horizontal">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Firebase Employee App"
        android:textSize="24sp"
        android:textStyle="bold"
        android:layout_marginBottom="30dp"/>

    <EditText
        android:id="@+id/etName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter Employee Name"
        android:inputType="textPersonName"
        android:background="#F0F0F0"
        android:padding="15dp"
        android:layout_marginBottom="10dp"/>

    <EditText
        android:id="@+id/etRole"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter Job Role"
        android:inputType="text"
        android:background="#F0F0F0"
        android:padding="15dp"
        android:layout_marginBottom="20dp"/>

    <Button
        android:id="@+id/btnAdd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Add To Database"
        android:backgroundTint="#FF5722"
        android:textColor="#FFFFFF"/>

    <TextView
        android:id="@+id/tvData"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:textSize="16sp"
        android:text="Loading Data..."
        android:background="#FAFAFA"
        android:padding="10dp"/>

</LinearLayout>

Assignment 9 (Firebase Employee App) with full Add, View, Update, and Delete functionality.

Follow these steps exactly in this order.

Phase 1: Firebase Setup (Do this first) Connect Project: Go to Tools > Firebase > Realtime Database.

Click Connect to Firebase.

Click Add the Realtime Database SDK to your app.

Set Permissions (Crucial):

Go to Firebase Console.

Open your project > Realtime Database > Rules.

Change false to true and click Publish:

JSON

{ "rules": { ".read": true, ".write": true } } Phase 2: The Android Code Step 1: Add Permission File: manifests/AndroidManifest.xml Add the internet permission line exactly above the tag.

XML

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/Theme.AppCompat.Light">
    <activity
        android:name=".MainActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
Step 2: Create Model Class File: Right-click package folder > New > Java Class > Name it Employee.

Java

package com.example.firebasedemo; // CHECK YOUR PACKAGE NAME

public class Employee { String id; String name; String role;

// Empty constructor is required for Firebase
public Employee() {
}

public Employee(String id, String name, String role) {
    this.id = id;
    this.name = name;
    this.role = role;
}

public String getId() { return id; }
public String getName() { return name; }
public String getRole() { return role; }

// This controls what text is shown in the ListView
@Override
public String toString() {
    return name + " (" + role + ")";
}

} Step 3: Create Layout (Fixes 'Cannot resolve symbol' error) File: res/layout/activity_main.xml Copy all of this code and replace the content of the file.

XML

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Employee Manager"
    android:textSize="24sp"
    android:textStyle="bold"
    android:gravity="center"
    android:layout_marginBottom="20dp"
    android:textColor="#333333"/>

<EditText
    android:id="@+id/etName"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Enter Name"
    android:background="#FFFFFF"
    android:padding="12dp"
    android:layout_marginBottom="10dp"/>

<EditText
    android:id="@+id/etRole"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Enter Role"
    android:background="#FFFFFF"
    android:padding="12dp"
    android:layout_marginBottom="20dp"/>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:weightSum="3"
    android:layout_marginBottom="10dp">

    <Button
        android:id="@+id/btnAdd"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="Add"
        android:backgroundTint="#4CAF50"
        android:layout_marginEnd="5dp"/>

    <Button
        android:id="@+id/btnUpdate"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="Update"
        android:backgroundTint="#2196F3"
        android:layout_marginEnd="5dp"/>

    <Button
        android:id="@+id/btnDelete"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="Delete"
        android:backgroundTint="#F44336"/>
</LinearLayout>

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Tap any item below to Select/Edit:"
    android:textStyle="italic"
    android:gravity="center"
    android:layout_marginBottom="5dp"/>

<ListView
    android:id="@+id/listView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFFFF"/>
Step 4: The Main Logic File: MainActivity.java

Java

package com.example.firebasedemo; // CHECK YOUR PACKAGE NAME

import android.os.Bundle; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import android.widget.Toast;

import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity;

import com.google.firebase.database.DataSnapshot; import com.google.firebase.database.DatabaseError; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.database.ValueEventListener;

import java.util.ArrayList; import java.util.List;

public class MainActivity extends AppCompatActivity {

EditText etName, etRole;
Button btnAdd, btnUpdate, btnDelete;
ListView listView;

DatabaseReference dbRef;
List<Employee> employeeList;
ArrayAdapter<Employee> adapter;

String selectedId = null; // Stores ID of the employee we clicked on

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Hide the Action Bar
    if (getSupportActionBar() != null) getSupportActionBar().hide();

    // 1. Initialize Views
    etName = findViewById(R.id.etName);
    etRole = findViewById(R.id.etRole);
    btnAdd = findViewById(R.id.btnAdd);
    btnUpdate = findViewById(R.id.btnUpdate);
    btnDelete = findViewById(R.id.btnDelete);
    listView = findViewById(R.id.listView);

    // 2. Setup List and Adapter
    employeeList = new ArrayList<>();
    adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, employeeList);
    listView.setAdapter(adapter);

    // 3. Connect to Database
    dbRef = FirebaseDatabase.getInstance().getReference("Employees");

    // --- ADD BUTTON ---
    btnAdd.setOnClickListener(v -> {
        String name = etName.getText().toString();
        String role = etRole.getText().toString();

        if (name.isEmpty() || role.isEmpty()) return;

        String id = dbRef.push().getKey(); // Create new ID
        Employee emp = new Employee(id, name, role);
        
        dbRef.child(id).setValue(emp);
        Toast.makeText(this, "Added", Toast.LENGTH_SHORT).show();
        clearInputs();
    });

    // --- LIST ITEM CLICK (Select for Update/Delete) ---
    listView.setOnItemClickListener((parent, view, position, id) -> {
        Employee selectedEmp = employeeList.get(position);
        
        // Fill boxes with data
        etName.setText(selectedEmp.getName());
        etRole.setText(selectedEmp.getRole());
        
        // Save ID for later use
        selectedId = selectedEmp.getId();
        
        Toast.makeText(this, "Selected: " + selectedEmp.getName(), Toast.LENGTH_SHORT).show();
    });

    // --- UPDATE BUTTON ---
    btnUpdate.setOnClickListener(v -> {
        if (selectedId == null) {
            Toast.makeText(this, "Select item first", Toast.LENGTH_SHORT).show();
            return;
        }
        String name = etName.getText().toString();
        String role = etRole.getText().toString();
        
        Employee emp = new Employee(selectedId, name, role);
        dbRef.child(selectedId).setValue(emp); // Overwrite data
        
        Toast.makeText(this, "Updated", Toast.LENGTH_SHORT).show();
        clearInputs();
    });

    // --- DELETE BUTTON ---
    btnDelete.setOnClickListener(v -> {
        if (selectedId == null) {
            Toast.makeText(this, "Select item first", Toast.LENGTH_SHORT).show();
            return;
        }
        dbRef.child(selectedId).removeValue(); // Delete data
        
        Toast.makeText(this, "Deleted", Toast.LENGTH_SHORT).show();
        clearInputs();
    });

    // --- REALTIME SYNC (View) ---
    dbRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            employeeList.clear();
            for (DataSnapshot ds : snapshot.getChildren()) {
                Employee emp = ds.getValue(Employee.class);
                employeeList.add(emp);
            }
            adapter.notifyDataSetChanged();
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {
        }
    });
}

private void clearInputs() {
    etName.setText("");
    etRole.setText("");
    selectedId = null;
}

} Phase 3: Testing Run the app.

Add: Type "Alex" and "Manager", click Add. (It appears in the list).

Select: Tap on "Alex" in the list. The text boxes will fill up.

Update: Change "Manager" to "Director", click Update. (List updates automatically).

Delete: Tap on "Alex", click Delete. (Item disappears).

Assignment 10: Image Animation & Processing Requirement: Add an image named sample.jpg (or png) to res/drawable/ folder.

  1. res/layout/activity_main.xml

XML

<ImageView
    android:id="@+id/imageView"
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:src="@drawable/sample" 
    android:scaleType="centerCrop"/>

<LinearLayout android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content">
    <Button android:id="@+id/btnRotate" android:text="Rotate" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
    <Button android:id="@+id/btnZoom" android:text="Zoom" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
    <Button android:id="@+id/btnGrey" android:text="Greyscale" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
</LinearLayout>
2. MainActivity.java

Java

package com.example.imagedemo;

import android.animation.ObjectAnimator; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.drawable.BitmapDrawable; import android.os.Bundle; import android.widget.Button; import android.widget.ImageView; import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity { ImageView img;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    img = findViewById(R.id.imageView);

    // 1. Animation: Rotate
    findViewById(R.id.btnRotate).setOnClickListener(v -> {
        ObjectAnimator anim = ObjectAnimator.ofFloat(img, "rotation", 0f, 360f);
        anim.setDuration(1000);
        anim.start();
    });

    // 2. Animation: Zoom (Scale)
    findViewById(R.id.btnZoom).setOnClickListener(v -> {
        ObjectAnimator scaleX = ObjectAnimator.ofFloat(img, "scaleX", 1f, 1.5f);
        ObjectAnimator scaleY = ObjectAnimator.ofFloat(img, "scaleY", 1f, 1.5f);
        scaleX.setDuration(1000).start();
        scaleY.setDuration(1000).start();
    });

    // 3. Processing: Greyscale (Pixel manipulation)
    findViewById(R.id.btnGrey).setOnClickListener(v -> {
        BitmapDrawable drawable = (BitmapDrawable) img.getDrawable();
        Bitmap bitmap = drawable.getBitmap();
        Bitmap newBitmap = toGrayscale(bitmap);
        img.setImageBitmap(newBitmap);
    });
}

private Bitmap toGrayscale(Bitmap bmpOriginal) {
    int width, height;
    height = bmpOriginal.getHeight();
    width = bmpOriginal.getWidth();
    Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);

    for (int i = 0; i < width; i++) {
        for (int j = 0; j < height; j++) {
            int pixel = bmpOriginal.getPixel(i, j);
            int r = Color.red(pixel);
            int g = Color.green(pixel);
            int b = Color.blue(pixel);
            // Standard Greyscale formula
            int gray = (int) (0.299 * r + 0.587 * g + 0.114 * b);
            bmpGrayscale.setPixel(i, j, Color.rgb(gray, gray, gray));
        }
    }
    return bmpGrayscale;
}

}

Here are Assignments 11, 12, and 13 (Android). I have applied the fix (Hiding the Top Bar and using ScrollView) to all of them so they work on small screens.

I will provide the Flutter Assignments (14–17) in the next message to keep this organized.

Assignment 11: Audio & Video Player Pre-requisites:

Create a folder: res > raw (Right-click res -> New -> Android Resource Directory -> Select raw).

Paste an audio file named audio.mp3 and a video file named video.mp4 into res/raw. (If you don't have them, the app will crash).

  1. res/layout/activity_main.xml

XML

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="20dp"
    android:gravity="center_horizontal">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Media Player"
        android:textSize="24sp"
        android:textStyle="bold"
        android:layout_marginBottom="30dp"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Audio Player"
        android:textStyle="bold"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:gravity="center"
        android:layout_marginBottom="30dp">

        <Button android:id="@+id/btnPlay" android:text="Play" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
        <Button android:id="@+id/btnPause" android:text="Pause" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
        <Button android:id="@+id/btnStop" android:text="Stop" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
    </LinearLayout>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Video Player"
        android:textStyle="bold"
        android:layout_marginBottom="10dp"/>

    <VideoView
        android:id="@+id/videoView"
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:layout_gravity="center"/>

</LinearLayout>
2. MainActivity.java

Java

package com.example.mediaplayer; // CHECK PACKAGE NAME

import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.widget.Button; import android.widget.MediaController; import android.widget.VideoView; import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

MediaPlayer mp;
VideoView vv;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (getSupportActionBar() != null) getSupportActionBar().hide();

    // --- AUDIO SETUP ---
    // Ensure 'audio.mp3' exists in res/raw
    mp = MediaPlayer.create(this, R.raw.audio);

    Button btnPlay = findViewById(R.id.btnPlay);
    Button btnPause = findViewById(R.id.btnPause);
    Button btnStop = findViewById(R.id.btnStop);

    btnPlay.setOnClickListener(v -> mp.start());
    btnPause.setOnClickListener(v -> mp.pause());
    btnStop.setOnClickListener(v -> {
        mp.stop();
        mp = MediaPlayer.create(this, R.raw.audio); // Reset after stop
    });

    // --- VIDEO SETUP ---
    vv = findViewById(R.id.videoView);
    // Ensure 'video.mp4' exists in res/raw
    String videoPath = "android.resource://" + getPackageName() + "/" + R.raw.video;
    
    Uri uri = Uri.parse(videoPath);
    vv.setVideoURI(uri);

    // Add controls (Play/Pause/Scrub bar) to the video
    MediaController mediaController = new MediaController(this);
    vv.setMediaController(mediaController);
    mediaController.setAnchorView(vv);
}

} Assignment 12: GPS Location Pre-requisites:

Add permissions to AndroidManifest.xml.

Enable GPS on your phone/emulator before testing.

  1. AndroidManifest.xml

XML

<manifest ... >

<application ...>
    ...
</application>
2. res/layout/activity_main.xml

XML

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="20dp"
    android:gravity="center">

    <Button
        android:id="@+id/btnGetLoc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Get Current Location"
        android:backgroundTint="#FF6200EB"/>

    <TextView
        android:id="@+id/tvLat"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="Latitude: "
        android:textSize="18sp"/>

    <TextView
        android:id="@+id/tvLong"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="Longitude: "
        android:textSize="18sp"/>

    <TextView
        android:id="@+id/tvAddress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="Address: "
        android:textSize="18sp"/>

</LinearLayout>
3. MainActivity.java

Java

package com.example.gpsdemo;

import android.Manifest; import android.content.pm.PackageManager; import android.location.Address; import android.location.Geocoder; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import java.util.List; import java.util.Locale;

public class MainActivity extends AppCompatActivity implements LocationListener {

Button btnGetLoc;
TextView tvLat, tvLong, tvAddress;
LocationManager locationManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    if (getSupportActionBar() != null) getSupportActionBar().hide();

    btnGetLoc = findViewById(R.id.btnGetLoc);
    tvLat = findViewById(R.id.tvLat);
    tvLong = findViewById(R.id.tvLong);
    tvAddress = findViewById(R.id.tvAddress);

    locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

    btnGetLoc.setOnClickListener(v -> getLocation());
}

private void getLocation() {
    // Check Runtime Permission
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 100);
    } else {
        try {
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 5, this);
            Toast.makeText(this, "Fetching Location...", Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

@Override
public void onLocationChanged(@NonNull Location location) {
    tvLat.setText("Latitude: " + location.getLatitude());
    tvLong.setText("Longitude: " + location.getLongitude());

    try {
        Geocoder geocoder = new Geocoder(this, Locale.getDefault());
        List<Address> addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
        if (!addresses.isEmpty()) {
            tvAddress.setText("Address: " + addresses.get(0).getAddressLine(0));
        }
    } catch (Exception e) {
        tvAddress.setText("Address: Could not fetch");
    }
}

// Required empty methods
@Override public void onStatusChanged(String provider, int status, Bundle extras) {}
@Override public void onProviderEnabled(@NonNull String provider) {}
@Override public void onProviderDisabled(@NonNull String provider) {}

}

Assignment 13: REST API (Volley) Goal: Fetch data from a test API (jsonplaceholder.typicode.com). Pre-requisites:

Dependencies: Open build.gradle (Module: app) and add this inside dependencies { ... }: implementation 'com.android.volley:volley:1.2.1' (Then click "Sync Now").

Permission: Add in AndroidManifest.xml.

  1. res/layout/activity_main.xml

XML

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="20dp">

    <Button
        android:id="@+id/btnFetch"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Fetch Data from API" />

    <TextView
        android:id="@+id/tvResult"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="Data will appear here..."
        android:textSize="16sp"/>
</LinearLayout>
2. MainActivity.java

Java

package com.example.restapi;

import android.os.Bundle; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.android.volley.Request; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.JsonArrayRequest; import com.android.volley.toolbox.Volley; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject;

public class MainActivity extends AppCompatActivity {

Button btnFetch;
TextView tvResult;
String url = "https://jsonplaceholder.typicode.com/users";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    if (getSupportActionBar() != null) getSupportActionBar().hide();

    btnFetch = findViewById(R.id.btnFetch);
    tvResult = findViewById(R.id.tvResult);

    btnFetch.setOnClickListener(v -> getData());
}

private void getData() {
    RequestQueue queue = Volley.newRequestQueue(this);

    JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, url, null,
        new Response.Listener<JSONArray>() {
            @Override
            public void onResponse(JSONArray response) {
                StringBuilder sb = new StringBuilder();
                try {
                    for (int i = 0; i < response.length(); i++) {
                        JSONObject user = response.getJSONObject(i);
                        String name = user.getString("name");
                        String email = user.getString("email");
                        sb.append("Name: ").append(name).append("\n");
                        sb.append("Email: ").append(email).append("\n\n");
                    }
                    tvResult.setText(sb.toString());
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        },
        new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Toast.makeText(MainActivity.this, "Error Fetching Data", Toast.LENGTH_SHORT).show();
            }
        });

    queue.add(jsonArrayRequest);
}

}

Assignment 14. This covers exactly what you did to get it running, the final code, and an explanation of how it works for your Viva.

Assignment 14: Flutter BMI Calculator

  1. Project Setup Steps Open Android Studio.

Go to File > New > New Flutter Project.

Project Name: bmi_calculator (lowercase, no spaces).

Platforms (Crucial):

✅ Check: Android.

⬜ Uncheck: iOS, macOS, Web (to prevent errors).

Click Create.

  1. The Code File Location: lib/main.dart

Action: Delete all existing code in that file and paste this:

Dart

import 'package:flutter/material.dart';

// 1. The Entry Point void main() { runApp(const MaterialApp( debugShowCheckedModeBanner: false, home: BmiCalculator(), // Opens our Calculator Screen )); }

// 2. The Main Screen (Stateful because data changes) class BmiCalculator extends StatefulWidget { const BmiCalculator({super.key});

@override State createState() => _BmiCalculatorState(); }

class _BmiCalculatorState extends State { // 3. Controllers to retrieve text from Input Fields final TextEditingController heightController = TextEditingController(); final TextEditingController weightController = TextEditingController();

// Variables to store output double result = 0; String msg = "";

// 4. The Logic Function void calculateBMI() { // Validation: Don't run if empty if(heightController.text.isEmpty || weightController.text.isEmpty) return;

// Get inputs (Parse String to Double)
double h = double.parse(heightController.text) / 100; // Convert cm to meters
double w = double.parse(weightController.text);

// Logic: Weight / (Height * Height)
setState(() {
  result = w / (h * h);
  
  // Categorize result
  if (result < 18.5) {
    msg = "Underweight";
  } else if (result < 25) {
    msg = "Healthy";
  } else {
    msg = "Overweight";
  }
});

}

// 5. The UI Design (Build Method) @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("BMI Calculator"), backgroundColor: Colors.blue),

  // SingleChildScrollView fixes "Pixel Overflow" error on small screens
  body: SingleChildScrollView(
    child: Padding(
      padding: const EdgeInsets.all(20.0),
      child: Column(
        children: [
          // Height Input
          TextField(
            controller: heightController,
            keyboardType: TextInputType.number,
            decoration: const InputDecoration(
              labelText: "Height (cm)",
              border: OutlineInputBorder()
            ),
          ),
          const SizedBox(height: 20), // Spacing
          
          // Weight Input
          TextField(
            controller: weightController,
            keyboardType: TextInputType.number,
            decoration: const InputDecoration(
              labelText: "Weight (kg)",
              border: OutlineInputBorder()
            ),
          ),
          const SizedBox(height: 30),
          
          // Calculate Button
          ElevatedButton(
            onPressed: calculateBMI, 
            child: const Text("Calculate BMI"),
            style: ElevatedButton.styleFrom(minimumSize: const Size(double.infinity, 50)),
          ),
          const SizedBox(height: 30),
          
          // Display Result
          Text(
            "BMI: ${result.toStringAsFixed(2)}", 
            style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold)
          ),
          Text(
            msg, 
            style: TextStyle(
              fontSize: 22, 
              color: msg == "Healthy" ? Colors.green : Colors.red,
              fontWeight: FontWeight.bold
            )
          ),
        ],
      ),
    ),
  ),
);

} } 3. Code Explanation (For Viva) main(): The starting point. It runs MaterialApp, which is the root of a Flutter app.

StatefulWidget: We use this because the screen needs to update (change state) when we calculate the result. If we used StatelessWidget, the result text would never update on the screen.

TextEditingController: These are "listeners" attached to the TextFields. They allow us to read what the user typed (heightController.text).

setState(): This is the most important command. It tells Flutter: "Data has changed! Please redraw the screen immediately." Without this, the variables would update in the background, but the user would still see "0".

SingleChildScrollView: A wrapper that makes the screen scrollable. This prevents the "Yellow/Black error bars" if the keyboard pops up and covers the inputs.

  1. How to Run Ensure your Emulator is selected in the top toolbar.

Click the Green Play Button.

Here is the complete, structured guide for Assignment 15.

Assignment 15: Flutter Registration Form Goal: Create a form with different types of inputs (Text, Radio, Dropdown, Checkbox) and pass that data to a second screen.

  1. Project Setup Steps Option A (Fastest): You can simply overwrite the lib/main.dart file in your existing bmi_calculator project.

Option B (New Project):

File > New > New Flutter Project.

Name: registration_form (lowercase).

Platforms: Check Android only.

Click Create.

  1. The Code File Location: lib/main.dart

Action: Delete everything and paste this code.

Dart

import 'package:flutter/material.dart';

// 1. Entry Point void main() { runApp(const MaterialApp( debugShowCheckedModeBanner: false, home: RegisterPage(), // Start at the Form Screen )); }

// --- SCREEN 1: The Input Form --- class RegisterPage extends StatefulWidget { const RegisterPage({super.key}); @override State createState() => _RegisterPageState(); }

class _RegisterPageState extends State { // Controller for Text Input final TextEditingController nameController = TextEditingController();

// Variables to hold current selection String gender = "Male"; String city = "Mumbai"; bool isCoder = false;

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("Registration"), backgroundColor: Colors.purple), body: SingleChildScrollView( // Prevents keyboard overflow issues padding: const EdgeInsets.all(20), child: Column( children: [ // 1. Text Field TextField( controller: nameController, decoration: const InputDecoration(labelText: "Enter Name", border: OutlineInputBorder()) ), const SizedBox(height: 20),

        // 2. Radio Buttons (Gender)
        const Align(alignment: Alignment.centerLeft, child: Text("Select Gender:", style: TextStyle(fontWeight: FontWeight.bold))),
        Row(
          children: [
            Radio(
              value: "Male", 
              groupValue: gender, 
              onChanged: (val) => setState(() => gender = val.toString())
            ),
            const Text("Male"),
            Radio(
              value: "Female", 
              groupValue: gender, 
              onChanged: (val) => setState(() => gender = val.toString())
            ),
            const Text("Female"),
          ],
        ),
        
        const SizedBox(height: 10),

        // 3. Dropdown Menu (City)
        const Align(alignment: Alignment.centerLeft, child: Text("Select City:", style: TextStyle(fontWeight: FontWeight.bold))),
        DropdownButton<String>(
          value: city,
          isExpanded: true, // Make it full width
          // Map list of strings to DropdownMenuItem widgets
          items: ["Mumbai", "Delhi", "Pune", "Bangalore"].map((String val) {
            return DropdownMenuItem(value: val, child: Text(val));
          }).toList(),
          onChanged: (val) => setState(() => city = val!),
        ),
        
        const SizedBox(height: 10),

        // 4. Checkbox (Skills)
        CheckboxListTile(
          title: const Text("I know Coding"),
          value: isCoder,
          onChanged: (val) => setState(() => isCoder = val!),
          controlAffinity: ListTileControlAffinity.leading, // Checkbox on left
        ),
        
        const SizedBox(height: 30),

        // 5. Submit Button & Navigation
        ElevatedButton(
          style: ElevatedButton.styleFrom(minimumSize: const Size(double.infinity, 50), backgroundColor: Colors.purple),
          onPressed: () {
            // Validation
            if (nameController.text.isEmpty) return;

            // NAVIGATE AND PASS DATA
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => ResultPage(
                name: nameController.text,
                gender: gender,
                city: city,
                isCoder: isCoder,
              )),
            );
          },
          child: const Text("Submit", style: TextStyle(color: Colors.white, fontSize: 18)),
        )
      ],
    ),
  ),
);

} }

// --- SCREEN 2: Result Display --- class ResultPage extends StatelessWidget { // Variables to receive data final String name, gender, city; final bool isCoder;

// Constructor: This is how data enters this screen const ResultPage({ super.key, required this.name, required this.gender, required this.city, required this.isCoder });

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("Submission Details"), backgroundColor: Colors.teal), body: Center( child: Padding( padding: const EdgeInsets.all(20.0), child: Card( elevation: 5, // Shadow effect child: Padding( padding: const EdgeInsets.all(20.0), child: Column( mainAxisSize: MainAxisSize.min, // Wrap content tightly children: [ Text("Name: $name", style: const TextStyle(fontSize: 20)), const SizedBox(height: 10), Text("Gender: $gender", style: const TextStyle(fontSize: 20)), const SizedBox(height: 10), Text("City: $city", style: const TextStyle(fontSize: 20)), const SizedBox(height: 10), Text("Skills: ${isCoder ? "Coder" : "None"}", style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), const SizedBox(height: 20),

              // Go Back Button
              ElevatedButton(
                onPressed: () => Navigator.pop(context), 
                child: const Text("Go Back")
              )
            ],
          ),
        ),
      ),
    ),
  ),
);

} } 3. Code Explanation (For Viva) Navigator.push: This command puts a new screen on top of the current screen (like a stack of cards).

MaterialPageRoute: This handles the animation of sliding the new screen in (standard Android/iOS transition).

Passing Data (The Constructor):

In ResultPage, we defined variables (final String name...) and a Constructor (required this.name...).

When we call ResultPage(...) inside Navigator.push, we are actually creating the screen object and handing it the data before it gets displayed.

Navigator.pop(context): This removes the top screen (ResultPage) and goes back to the previous screen (RegisterPage).

Widgets Used:

Radio: Used groupValue to ensure only one circle is selected at a time.

DropdownButton: Requires a list of items (DropdownMenuItem) and an onChanged function to update the selected value.

  1. How to Run Ensure Emulator is running.

Click the Green Play Button.

Fill out the form and click Submit. You should see the second screen with your details.

ssignment 16: Flutter Database (SQFlite) Goal: Create a Note-taking app where data persists (remains saved) even after you close the app, using a local SQLite database.

  1. Project Setup & Dependencies (CRITICAL) Unlike previous assignments, this one requires external libraries (plugins).

Create New Project: Name it sqflite_demo (lowercase).

Open pubspec.yaml: Find this file in the project folder list on the left.

Add Dependencies: Scroll down to dependencies: and add sqflite and path_provider. It should look exactly like this (indentation matters!):

YAML

dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.2

ADD THESE TWO LINES:

sqflite: ^2.3.0 path_provider: ^2.1.1 Download: Click the "Pub get" button at the top of the screen (or run flutter pub get in terminal).

  1. The Code File Location: lib/main.dart

Action: Delete everything and paste this code.

Dart

import 'package:flutter/material.dart'; // Imports for Database functionality import 'package:sqflite/sqflite.dart'; import 'package:path_provider/path_provider.dart'; import 'dart:io'; import 'package:path/path.dart';

void main() { runApp(const MaterialApp( debugShowCheckedModeBanner: false, home: DatabaseApp(), )); }

class DatabaseApp extends StatefulWidget { const DatabaseApp({super.key}); @override State createState() => _DatabaseAppState(); }

class _DatabaseAppState extends State { final TextEditingController _controller = TextEditingController();

// Variable to hold the database connection Database? _database;

// List to hold the notes fetched from DB List<Map<String, dynamic>> _notes = [];

@override void initState() { super.initState(); _initDatabase(); // Start DB when app launches }

// --- 1. INITIALIZE DATABASE --- Future _initDatabase() async { // Get the safe folder on the phone to store files Directory documentsDirectory = await getApplicationDocumentsDirectory();

// Create path: .../Documents/notes.db
String path = join(documentsDirectory.path, "notes.db");

// Open DB (and create table if it doesn't exist)
_database = await openDatabase(
  path, 
  version: 1, 
  onCreate: (db, version) {
    return db.execute("CREATE TABLE Notes (id INTEGER PRIMARY KEY, content TEXT)");
  }
);

// Load existing notes
_refreshNotes();

}

// --- 2. CREATE (Insert) --- Future _addNote() async { if (_controller.text.isEmpty) return;

await _database?.insert('Notes', {
  'content': _controller.text
});

_controller.clear(); // Clear input box
_refreshNotes();     // Reload list

}

// --- 3. READ (Query) --- Future _refreshNotes() async { // Get all rows from the table final data = await _database?.query('Notes');

setState(() {
  _notes = data ?? [];
});

}

// --- 4. DELETE --- Future _deleteNote(int id) async { await _database?.delete('Notes', where: 'id = ?', whereArgs: [id]); _refreshNotes(); }

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("My Notes (SQLite)"), backgroundColor: Colors.orange), body: Column( children: [ // Input Area Padding( padding: const EdgeInsets.all(15.0), child: Row( children: [ Expanded( child: TextField( controller: _controller, decoration: const InputDecoration( hintText: "Enter a new note", border: OutlineInputBorder() ) ) ), const SizedBox(width: 10), ElevatedButton( onPressed: _addNote, style: ElevatedButton.styleFrom(backgroundColor: Colors.orange), child: const Icon(Icons.add, color: Colors.white), ), ], ), ),

      const Divider(thickness: 2),

      // List of Notes
      Expanded(
        child: ListView.builder(
          itemCount: _notes.length,
          itemBuilder: (context, index) {
            return Card(
              margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
              child: ListTile(
                // Display the content
                title: Text(_notes[index]['content']),
                // Delete Button
                trailing: IconButton(
                  icon: const Icon(Icons.delete, color: Colors.red),
                  onPressed: () => _deleteNote(_notes[index]['id']),
                ),
              ),
            );
          },
        ),
      )
    ],
  ),
);

} } 3. Code Explanation (For Viva) sqflite Plugin: This allows Flutter to talk to the native SQLite database engine inside Android/iOS.

path_provider Plugin: Android phones have specific folders where apps are allowed to save files. We can't just save to "C:/". This plugin finds the correct, safe folder (getApplicationDocumentsDirectory).

async and await: Database operations (opening, writing, reading) are slow compared to drawing the UI.

If we ran them normally, the app would freeze/hang while saving.

await means: "Pause this specific function here, let the app keep running, and come back when the database is done."

Future: This is the return type for async functions. It's like a "Promise" that a result will arrive later.

onCreate: This only runs once—the very first time the app is installed and run. This is where we write the SQL CREATE TABLE command.

  1. How to Run Stop the app if it is currently running (Red Square button).

Run the app again (Green Play button) to ensure the new dependencies are loaded.

Test:

Type "Buy Milk" and click Add (+).

Type "Call Mom" and click Add (+).

Close the app completely (Stop button).

Run it again.

Result: The notes should still be there! (This proves the database works).

Great job getting the database assignment working! That was the hardest one.

Here is the Final Assignment (Assignment 17): Flutter REST API.

Goal: Fetch data from the internet (a list of fake users) and display it in a list.

Assignment 17: Flutter REST API Step 1: Add the Dependency (Crucial) We need a library called http to make network requests.

Open pubspec.yaml.

Scroll to dependencies:.

Add http: ^1.1.0 under flutter:.

Important: You can remove sqflite and path_provider if you want, or just add http below them.

It should look like this:

YAML

dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.2

ADD THIS LINE:

http: ^1.1.0 Click Pub get (or run flutter pub get in terminal).

Step 2: The Code File Location: lib/main.dart

Action: Delete everything and paste this code.

Dart

import 'package:flutter/material.dart'; import 'dart:convert'; // To convert JSON text to Lists/Maps import 'package:http/http.dart' as http; // To make network requests

void main() { runApp(const MaterialApp( debugShowCheckedModeBanner: false, home: ApiPage(), )); }

class ApiPage extends StatefulWidget { const ApiPage({super.key}); @override State createState() => _ApiPageState(); }

class _ApiPageState extends State { // List to store the fetched data List users = [];

// Boolean to track if we are currently loading bool isLoading = false;

@override void initState() { super.initState(); fetchUsers(); // Auto-load data when app starts }

// --- THE API LOGIC --- Future fetchUsers() async { setState(() { isLoading = true; // Show loading spinner });

// 1. Make the Network Request
// We use a test API that gives free fake data
final url = Uri.parse('https://jsonplaceholder.typicode.com/users');
final response = await http.get(url);

// 2. Check if successful (200 OK)
if (response.statusCode == 200) {
  setState(() {
    // 3. Decode the JSON string into a Dart List
    users = json.decode(response.body);
    isLoading = false; // Hide spinner
  });
} else {
  setState(() => isLoading = false);
  throw Exception('Failed to load users');
}

}

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("REST API Call"), backgroundColor: Colors.indigo), body: isLoading ? const Center(child: CircularProgressIndicator()) // Show Spinner if loading : ListView.builder( // Show List if data is ready itemCount: users.length, itemBuilder: (context, index) { final user = users[index]; return Card( margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), elevation: 3, child: ListTile( // Circle with first letter of name leading: CircleAvatar( backgroundColor: Colors.indigo, child: Text(user['name'][0], style: const TextStyle(color: Colors.white)), ), title: Text(user['name'], style: const TextStyle(fontWeight: FontWeight.bold)), subtitle: Text(user['email']), trailing: const Icon(Icons.arrow_forward_ios, size: 16), ), ); }, ), ); } } Step 3: Code Explanation (For Viva) http.get(): This sends a request to the server asking for data (like typing a URL in a browser).

async / await: Network calls take time (milliseconds or seconds). await pauses the code until the data arrives so the app doesn't crash.

json.decode(): The internet sends data as a long String (JSON). This function converts that String into a Dart List so we can access user['name'] or user['email'].

isLoading: This is a simple flag.

When true: We show a CircularProgressIndicator (spinner).

When false: We show the ListView.

initState(): This function runs automatically once when the screen loads. We call fetchUsers() here so the user sees data immediately without pressing a button.

Step 4: Run It Make sure your Emulator has an Internet Connection (usually it shares your computer's Wi-Fi).

Click Run.

You should briefly see a spinning circle, and then a list of names (Leanne Graham, Ervin Howell, etc.).

Viva:

This is a comprehensive set of Viva Preparation Notes based on the assignments you uploaded. Since there are 17 assignments covering Android (Java) and Flutter, I have divided this into logical parts to ensure high detail.

Here is Part 1, covering Android Basics, Intents, Storage, and System Components (Assignments 1–7).

Assignment 1: Calculator

Goal: Create a basic calculator handling Addition, Subtraction, Multiplication, and Division.

Key Concepts:

Event Handling: Using OnClickListener to detect button presses.

String Manipulation: Concatenating strings to form numbers and parsing them using Double.parseDouble.

Logic: The code uses boolean flags (isAddition, isSubtraction) to track which operator was pressed.

Code Highlight:

The calculation logic splits the string based on the operator (e.g., expression.split("\+")) to separate the two numbers.

Input Validation: It checks for division by zero.

Viva Questions:

Q: Why do we use Double.parseDouble()?

A: TextFields/TextViews return Strings. We must convert them to doubles to perform arithmetic.

Q: Why do we need try-catch in the calculation block?

A: To handle exceptions like invalid formats or division by zero, preventing the app from crashing.

Q: What is R.id?

A: It is a resource ID class generated effectively to identify views (like buttons and textviews) in the Java code.

Assignment 2: Currency Converter

Goal: Convert amounts between 5 currencies (INR, USD, EUR, JPY, GBP) using a spinner.

Key Concepts:

Spinner: A dropdown menu in Android. Requires an ArrayAdapter to populate data.

2D Array: The logic uses a 2D double[][] array to store conversion rates relative to one another.

Code Highlight:

conversionRates[fromIndex][toIndex] retrieves the specific rate based on the spinner positions.

Viva Questions:

Q: What is an Adapter in Android?

A: An Adapter acts as a bridge between the UI component (Spinner/ListView) and the underlying data source (Array/List).

Q: How do you get the selected item from a Spinner?

A: Using spinner.getSelectedItemPosition() or spinner.getSelectedItem().toString().

Assignment 3: Explicit Intent (Registration Form)

Goal: Pass complex data (Strings, Booleans, Integers) from one Activity to another.

Key Concepts:

Explicit Intent: Used to start a specific component (Activity) within the same app.

Bundle/Extras: Data is attached to the intent using putExtra.

UI Components: Using RadioGroup for single choice , CheckBox for multiple choices, SeekBar for range, and Switch.

Code Highlight:

Sender: intent.putExtra("key", value);

Receiver: getIntent().getStringExtra("key"); or getBooleanExtra("key", false);.

Viva Questions:

Q: What is the difference between Explicit and Implicit Intents?

A: Explicit starts a specific class (Activity A -> Activity B). Implicit requests an action (Open Webpage) and lets the system find the best app.

Q: What happens if you don't provide a default value in getIntExtra?

A: It is mandatory to provide a default value (e.g., 0) to prevent errors if the key doesn't exist.

Assignment 4: Implicit Intent

Goal: Interact with other applications (Browser, SMS, Dialer, Other Apps).

Key Concepts:

URI Parsing: Formatting strings into URIs (e.g., 12345, smsto:12345, http://...).

Intent Actions:

Intent.ACTION_VIEW: Open a URL.

Intent.ACTION_SENDTO: Send SMS/Email to specific person.

Intent.ACTION_DIAL: Open dialer.

Intent.ACTION_SEND: Share content to any compatible app.

Code Highlight:

The "Receiver App" uses an intent-filter with in the Manifest to accept implicit intents.

Viva Questions:

Q: What is an Intent Filter?

A: It defines the capabilities of a component (Activity), telling the Android system what kind of implicit intents it can handle.

Q: Difference between ACTION_DIAL and ACTION_CALL?

A: DIAL opens the keypad with the number typed in. CALL initiates the call immediately (requires permission).

Assignment 5: Shared Preferences

Goal: Create a Login system that remembers the username and handles security (wrong attempts).

Key Concepts:

SharedPreferences: Used to store small amounts of primitive data (Key-Value pairs) in an XML file.

Mode Private: File is only accessible by the calling application.

Logic: Tracks counter for wrong attempts. Disables login button after 3 failures.

Code Highlight:

Writing: editor.putString("user", val); editor.commit();.

Reading: sp.getString("user", "");.

File Path: Stored at /data/data/package_name/shared_prefs/.

Viva Questions:

Q: commit() vs apply()?

A: commit() writes data synchronously (blocks main thread, returns boolean). apply() writes asynchronously (faster, void return).

Q: Is SharedPreferences secure for storing passwords?

A: No, because it's a simple XML file. For real apps, use EncryptedSharedPreferences or Keystore.

Assignment 6: Notification

Goal: Trigger a notification that opens a website when clicked.

Key Concepts:

Notification Channel (Android 8.0+): Essential for notifications to appear. Groups notifications by type.

NotificationManager: System service to issue notifications.

PendingIntent: Wraps a regular intent (ACTION_VIEW for website) to be executed later when the user clicks the notification.

Code Highlight:

Requires permission: .

setAutoCancel(true) ensures the notification disappears after clicking.

Viva Questions:

Q: What is a PendingIntent?

A: It is a token given to another application (like the Notification Manager) allowing it to execute your intent with your app's permissions at a later time.

Q: Why is a Notification Channel required?

A: Starting Android Oreo, channels allow users to customize settings (sound, vibration) for specific categories of notifications within an app.

Assignment 7: File Storage (Internal & External)

Goal: Save and retrieve text files from Internal Storage (private) and External Storage (public/SD card).

Key Concepts:

Internal Storage: openFileOutput and openFileInput. Private to the app. Deleted if app is uninstalled.

External Storage: Checks Environment.getExternalStorageState() to see if media is mounted. Uses standard Java File, FileInputStream, and FileOutputStream.

Code Highlight:

Internal Path: /data/data/package_name/files/.

External Path: /sdcard/Android/data/package_name/files/.

Uses InputStreamReader and BufferedReader to read text line by line.

Viva Questions:

Q: Difference between Internal and External storage?

A: Internal is always available and private. External might be removable (SD card) and permissions are managed differently.

Q: Why do we use MODE_PRIVATE?

A: To ensure other apps cannot access the file created by this app.

Would you like me to proceed to Part 2 (Databases: SQLite & Firebase, Audio/Video, and GPS)?

yes

Here is Part 2 of the Viva Preparation Notes, covering Advanced Android topics: Databases (SQLite & Firebase), Media, Graphics, Location, and Networking (Assignments 8–13).

Assignment 8: SQLite Database Goal: Implement a local database for a Student Management System with CRUD (Create, Read, Update, Delete) operations.

Key Concepts:

SQLiteOpenHelper: A helper class to manage database creation and version management.

ContentValues: A key-value store used to insert or update rows in the database table.

Cursor: An interface that provides random read-write access to the result set returned by a database query.

Code Highlight:

Creating Table: db.execSQL("CREATE TABLE ...") inside the onCreate method.

Inserting: db.insert(TAB_NAME, null, cv) where cv holds the data.

Reading: db.rawQuery("SELECT * FROM ...", null) returns a Cursor.

Viva Questions:

Q: What is the difference between getWritableDatabase() and getReadableDatabase()?

A: getWritableDatabase() opens the database for reading and writing. getReadableDatabase() opens it for reading only (and will fail if disk is full, whereas writable might throw an error immediately).

Q: Why do we need the moveToNext() method in a Cursor?

A: The Cursor starts before the first record. moveToNext() moves it to the first row (and subsequent rows) so data can be read.

Q: What happens if you don't close the Cursor (c.close())?

A: It can lead to memory leaks and reduce application performance.

Assignment 9: Firebase Realtime Database Goal: Create a cloud-based Employee management system that syncs data in real-time.

Key Concepts:

NoSQL Database: Firebase stores data as a JSON tree, not tables/rows like SQLite.

DatabaseReference: Represents a specific location in your Database and is used for reading or writing data to that location.

Asynchronous: Data retrieval happens in the background using listeners.

Code Highlight:

Push ID: dbRef.push().getKey() generates a unique, time-based ID for new records.

Permissions: Requires internet permission and google-services.json file.

Listener: ValueEventListener with onDataChange is used to read data whenever it changes on the server.

Viva Questions:

Q: What is the google-services.json file?

A: It is a configuration file downloaded from the Firebase Console that connects your specific Android app to your Firebase project resources.

Q: How is Firebase different from SQLite?

A: SQLite is local (offline) and relational (SQL). Firebase is cloud-based (online), real-time, and NoSQL (JSON).

Q: What does dbRef.child(id).setValue(emp) do?

A: It writes the emp object to the specific path defined by id, overwriting any existing data at that path.

Assignment 10: Image Animation & Processing Goal: Perform animations (Translate, Rotate, Scale, Fade) and pixel manipulation (Invert, Monochrome) on an image.

Key Concepts:

ObjectAnimator: A subclass of ValueAnimator that provides support for animating properties on target objects (like View.ALPHA or rotation).

Bitmap: A representation of an image that allows direct access to pixel data.

Pixel Manipulation: extracting ARGB (Alpha, Red, Green, Blue) values from a pixel integer.

Code Highlight:

Animation: ObjectAnimator.ofFloat(img, "rotation", 0f, 270f).

Greyscale Formula: (int)(0.299R + 0.587G + 0.114*B) is the standard luminosity formula for converting color to greyscale.

Inverting: 255 - Color.red(pixel) inverts the color channel.

Viva Questions:

Q: What is the difference between a Drawable and a Bitmap?

A: A Drawable is a general abstraction for "something that can be drawn." A Bitmap is a specific type of image storage containing actual pixel data.

Q: Why use AnimatorSet?

A: It allows you to play multiple animations together (simultaneously) or sequentially.

Assignment 11: Audio & Video Player Goal: Play multimedia files using Android's media classes.

Key Concepts:

MediaPlayer: The primary API for playing sound and audio.

VideoView: A specialized View wrapper that handles both the video display surface and the media playback.

MediaController: A view containing media controls (play, pause, seek bar) to control a video.

Code Highlight:

Audio: MediaPlayer.create(context, R.raw.sample) initializes the player.

Video: vv.setVideoURI(uri) sets the source, and vv.start() begins playback.

Viva Questions:

Q: Where do you store local audio/video files in Android Studio?

A: In the res/raw folder. This folder is for raw assets that are not compiled into binary XML.

Q: Why should you call mp.release()?

A: To free up system resources (memory and hardware codecs) when the media player is no longer needed.

Assignment 12: GPS Location Goal: Retrieve and display the user's current Latitude, Longitude, and Physical Address.

Key Concepts:

LocationManager: System service that provides access to the system location services.

Geocoder: A class for handling geocoding (coordinate to address) and reverse geocoding.

Permissions: Requires ACCESS_FINE_LOCATION (GPS) and ACCESS_COARSE_LOCATION (Network) in Manifest.

Code Highlight:

checkSelfPermission is critical to handle runtime permissions (mandatory since Android 6.0).

manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, ...) requests periodic updates.

Viva Questions:

Q: What is the difference between Fine and Coarse location?

A: Fine uses GPS (precise). Coarse uses WiFi/Cell Towers (approximate, battery efficient).

Q: What is Geocoding?

A: Converting a street address into latitude/longitude coordinates. This assignment uses Reverse Geocoding (Lat/Long to Address).

Assignment 13: REST API (Fetching Data) Goal: Fetch JSON data from a web URL using three different libraries: Volley, OkHttp, and Retrofit.

Key Concepts:

REST API: Representational State Transfer. It allows apps to communicate with servers using HTTP methods (GET, POST).

JSON Parsing: Converting the String response from the server into usable Java objects (JSONObject/JSONArray).

Libraries Comparison:

Volley: Google's library. Good for small, fast requests. Uses RequestQueue.

OkHttp: Efficient HTTP client. Handles connection pooling. Uses client.newCall(req).enqueue.

Retrofit: Type-safe HTTP client. Uses Interfaces and Annotations (@GET) to define endpoints. Automatically converts JSON to Java Objects (POJOs) using GSON.

Viva Questions:

Q: Which permission is required for API calls?

A: android.permission.INTERNET.

Q: Why is Retrofit considered "Type-safe"?

A: It maps the API directly to Java/Kotlin interfaces and classes, ensuring that the data types match at compile time, reducing runtime errors.

Q: What is the role of GSON?

A: It is a serialization/deserialization library that converts JSON strings into Java Objects and vice-versa.

Would you like me to proceed to Part 3 (Flutter Development: Basics, Forms, Databases, and APIs)?

yes

Here is Part 3 of the Viva Preparation Notes, covering the transition to Flutter Development (Assignments 14–17).

Assignment 14: Flutter BMI Calculator Goal: Create a Flutter app to calculate Body Mass Index (BMI).

Key Concepts:

StatefulWidget: Used here because the result (s) changes based on user input, requiring the UI to redraw (setState).

TextEditingController: Used to manage and retrieve text from TextField widgets.

setState: The method that tells the Flutter framework to rebuild the widget tree because some data has changed.

Code Highlight (Dart/Flutter):

double.parse(textwcon.text) ?? 0; handles conversion from String to Double, using the null-aware operator (?? 0) to provide a default value.

TextInputType.number in TextField ensures the correct keyboard pops up.

Viva Questions:

Q: What is the difference between a StatelessWidget and a StatefulWidget?

A: Stateless widgets have no mutable state (their properties are immutable). Stateful widgets have a mutable state that can change over the lifetime of the widget, triggering UI updates via setState().

Q: What is the role of the build method?

A: The build method is responsible for returning a widget tree—a description of the UI—based on the current state and configuration.

Q: What is Hot Reload in Flutter?

A: A development feature that injects updated source code files into the running Dart Virtual Machine (VM) without restarting the app or losing the current state.

Assignment 15: Flutter Registration Form Goal: Pass data between two screens (Registration and Result) using various input widgets.

Key Concepts:

Navigation (Navigator.push): Used to move from the main page to the ResultPage.

Widget Types:

TextField (for Name)

RadioListTile (for Gender)

DropdownButton (for City selection)

CheckboxListTile (for Languages)

SwitchListTile (for changing the background color/theme).

Constructor (in ResultPage): The data (name, gender, etc.) is passed to the next screen via the ResultPage's constructor.

Code Highlight:

Navigator.push(context, MaterialPageRoute(builder: (context) => ResultPage(...))) is the standard way to transition to a new screen.

The SwitchListTile uses setState to toggle the _darkbkgrd boolean, which immediately changes the Scaffold's backgroundColor.

Viva Questions:

Q: How do you pass data between screens in Flutter?

A: By passing the data to the constructor of the destination Widget (as done in ResultPage).

Q: What is a Scaffold?

A: It is a framework that provides basic structure (App Bar, Body, Floating Action Button, Drawers, etc.) for a mobile screen.

Q: What are MaterialApp and CupertinoApp?

A: They are the root widgets that define the app's overall structure, themes, and navigation, providing Google's Material Design and Apple's Cupertino (iOS) look and feel, respectively.

Assignment 16: Flutter SQFlite Database Goal: Implement local CRUD operations using the sqflite plugin.

Key Concepts:

SQFlite: A Flutter plugin that provides access to SQLite databases on Android and iOS.

path_provider: Plugin used to find the correct platform-specific directory (application documents) to store the database file.

Async/Await: All database operations are asynchronous (Future) and must be handled using await or .then().

Code Highlight:

Database Creation: Uses openDatabase(path, version: 1, onCreate: _onCreate).

Insertion: db.insert(_tableName, row). Data is passed as a Dart Map<String, dynamic>.

Reading: db.query(_tableName) returns a List<Map<String, dynamic>>.

Viva Questions:

Q: Why are database operations async?

A: Because they involve I/O operations (reading/writing to disk), which can take time. Making them async prevents the database calls from blocking the UI thread (preventing "jank").

Q: How is data stored and retrieved from SQFlite?

A: Data is stored and retrieved as Dart Maps (Map<String, dynamic>), where keys correspond to column names.

Q: What is a Dart Future?

A: An object representing a potential value or error that will be available at some time in the future. It's similar to a Java Promise.

Assignment 17: Flutter REST API Program Goal: Fetch JSON data from an external API and display it in a ListView.

Key Concepts:

http Package: Used for making network requests (GET, POST, etc.).

dart:convert: Used for decoding the JSON string response into Dart objects (json.decode(str)).

Model Class (POJO/Data Class): A Dart class (Employee) that mirrors the structure of the JSON data for type safety and easy access.

FutureBuilder or initState + Visibility: Used to manage the UI state while waiting for the network data to load. (This assignment uses initState and a Visibility widget with a CircularProgressIndicator replacement.)

Code Highlight:

Fetching: final response = await http.get(Uri.parse(url));.

Mapping: List.from(json.decode(response.body).map((x) => Employee.fromJson(x))) converts the raw JSON list into a list of Employee objects.

pubspec.yaml: This is where external dependencies like http are declared.

Viva Questions:

Q: How do you handle JSON data in Flutter?

A: Use the http package for fetching and the dart:convert library to decode the JSON string into Dart objects, typically mapped to a Model Class.

Q: What is the purpose of initState?

A: It is called once when a StatefulWidget is inserted into the widget tree. It is typically used to initialize state variables and start asynchronous data fetching (like API calls).

Q: Why is the CircularProgressIndicator used with Visibility?

A: It is a common pattern to show a loading indicator (CircularProgressIndicator) while the asynchronous data fetch is in progress (isLoaded is false) and display the actual content (ListView) once data is available (isLoaded is true).

Summary of All Assignments Assignment Topic Core Technology Key Concept 1 Calculator Android (Java) OnClickListener, Double.parseDouble, Input Validation 2 Currency Converter Android (Java) Spinner, ArrayAdapter, 2D Array Logic 3 Explicit Intent Android (Java) Intent.putExtra, Data Passing, SeekBar, CheckBox 4 Implicit Intent Android (Java) Intent.ACTION_VIEW/SENDTO/DIAL, Uri.parse, Intent-Filter 5 Shared Preferences Android (Java) SharedPreferences, MODE_PRIVATE, Intruder Logic 6 Notification Android (Java) NotificationChannel, PendingIntent, NotificationCompat.Builder 7 File Storage Android (Java) Internal (openFileOutput), External (Environment.getExternalStorageState) 8 SQLite Database Android (Java) SQLiteOpenHelper, ContentValues, Cursor, CRUD Operations 9 Firebase RTDB Android (Java) DatabaseReference, NoSQL, ValueEventListener, Real-time updates 10 Image Processing Android (Java) ObjectAnimator, Bitmap, Pixel Manipulation (ARGB), Greyscale formula 11 Audio/Video Player Android (Java) MediaPlayer, VideoView, MediaController, res/raw 12 GPS Location Android (Java) LocationManager, Geocoder, Runtime Permissions (ACCESS_FINE_LOCATION) 13 REST API Fetch Android (Java) Volley / OkHttp / Retrofit, JSON Parsing, INTERNET Permission 14 BMI Calculator Flutter (Dart) StatefulWidget, TextEditingController, setState, Basic Layout 15 Registration Form Flutter (Dart) Navigator.push, Passing Data via Constructor, Various Input Widgets 16 SQFlite Database Flutter (Dart) sqflite, path_provider, Future, Async/Await CRUD 17 Flutter REST API Flutter (Dart) http package, Model Class (fromJson), initState, Visibility (Loading) I have now gone through all 17 assignments and provided detailed viva notes for each. Please let me know if you have specific questions on any of the assignments or concepts!

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2025 Microsoft