0% found this document useful (0 votes)
5 views36 pages

Sample Page Test

The document outlines a comprehensive solution for an Android Route Card Management System, detailing the technical stack, core modules, and implementation specifics including Firebase integration and XML layouts. It includes Java class structures for authentication and route card management, along with features for QR code generation and Excel export. The system is designed to facilitate user authentication, route card management, and reporting functionalities.

Uploaded by

rowdygamer72002
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views36 pages

Sample Page Test

The document outlines a comprehensive solution for an Android Route Card Management System, detailing the technical stack, core modules, and implementation specifics including Firebase integration and XML layouts. It includes Java class structures for authentication and route card management, along with features for QR code generation and Excel export. The system is designed to facilitate user authentication, route card management, and reporting functionalities.

Uploaded by

rowdygamer72002
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

# Android Route Card Management System

I'll outline a comprehensive solution for your Route Card Management System project with all
the requested features. This will include XML layouts, Java code structure, Firebase
integration, and implementation details for each requirement.

## Project Structure Overview

### 1. Technical Stack


- **Frontend**: Android Studio (Java/Kotlin)
- **Backend**: Firebase (Authentication, Realtime Database, Storage)
- **QR Code**: ZXing library
- **Charts**: MPAndroidChart library
- **Excel Export**: Apache POI or JExcelAPI
- **PDF Export**: iTextPDF or Android PDF Writer

### 2. Core Modules


1. Authentication Module
2. Route Card Management Module
3. QR Code Module
4. Reporting Module
5. Company Profile Module
6. Settings Module

## Implementation Details
### 1. Firebase Database Structure

```java
// Firebase Realtime Database Structure
{
"users": {
"userId1": {
"name": "User Name",
"email": "[email protected]",
"role": "admin/user"
}
},
"route_cards": {
"cardId1": {
"card_number": "RC001",
"part_name": "Part A",
"part_no": "P001",
"planned_qty": 1000,
"customer_name": "Customer X",
"raw_material": {
"supplier": "Supplier A",
"rm_grade": "Grade 1",
"weight": 50.5,
"received_date": "2024-03-15"
},
"processes": [
{
"process_name": "Cutting",
"date": "2024-03-16",
"machine_no": "M001",
"prod_qty": 950,
"rej_qty": 50,
"operator": "Operator 1"
}
],
"status": "in_progress",
"created_by": "userId1",
"created_at": "2024-03-15T10:00:00",
"updated_at": "2024-03-16T15:30:00"
}
},
"company_profile": {
"name": "SIVA PRESS COMPONENTS",
"address": "Company Address",
"contact": "1234567890",
"events": {
"eventId1": {
"title": "Annual Day",
"date": "2024-01-15",
"photos": ["url1", "url2"],
"videos": ["url3"]
}
}
}
}
```

### 2. XML Layouts

#### activity_login.xml
```xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">

<ImageView
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="32dp"
android:layout_marginBottom="32dp"
android:src="@drawable/company_logo"/>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Email"
android:inputType="textEmailAddress"/>
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Password"
android:inputType="textPassword"/>
</com.google.android.material.textfield.TextInputLayout>

<Button
android:id="@+id/btnLogin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="Login"/>

<TextView
android:id="@+id/tvForgotPassword"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Forgot Password?"
android:textColor="@color/colorPrimary"/>

<TextView
android:id="@+id/tvRegister"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="16dp"
android:text="Don't have an account? Register"
android:textColor="@color/colorPrimary"/>
</LinearLayout>
```

#### activity_route_card_form.xml
```xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

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

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="PLANNING"
android:textSize="18sp"
android:textStyle="bold"/>

<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etRouteCardNo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Route card No."/>
</com.google.android.material.textfield.TextInputLayout>

<!-- Add all other fields from the Excel sheet similarly -->
<!-- Part Name, Part No, Planned Qty, Customer Name -->

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="RAW MATERIAL"
android:textSize="18sp"
android:textStyle="bold"/>

<!-- Raw Material fields -->

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="INTERNAL PROCESS"
android:textSize="18sp"
android:textStyle="bold"/>

<Button
android:id="@+id/btnAddProcess"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:text="Add Process"/>

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvProcesses"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"/>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<Button
android:id="@+id/btnSave"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="4dp"
android:text="Save"/>

<Button
android:id="@+id/btnGenerateQR"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="4dp"
android:text="Generate QR"/>
</LinearLayout>
</LinearLayout>
</ScrollView>
```

### 3. Java Classes

#### AuthActivity.java
```java
public class AuthActivity extends AppCompatActivity {
private EditText etEmail, etPassword;
private Button btnLogin;
private TextView tvForgotPassword, tvRegister;
private FirebaseAuth mAuth;

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

mAuth = FirebaseAuth.getInstance();

etEmail = findViewById(R.id.etEmail);
etPassword = findViewById(R.id.etPassword);
btnLogin = findViewById(R.id.btnLogin);
tvForgotPassword = findViewById(R.id.tvForgotPassword);
tvRegister = findViewById(R.id.tvRegister);

btnLogin.setOnClickListener(v -> loginUser());


tvForgotPassword.setOnClickListener(v -> resetPassword());
tvRegister.setOnClickListener(v -> startActivity(new Intent(this, RegisterActivity.class)));
}

private void loginUser() {


String email = etEmail.getText().toString().trim();
String password = etPassword.getText().toString().trim();

if (email.isEmpty() || password.isEmpty()) {
Toast.makeText(this, "Please fill all fields", Toast.LENGTH_SHORT).show();
return;
}

mAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
checkPinOrFingerprint();
} else {
Toast.makeText(this, "Authentication failed: " + task.getException(),
Toast.LENGTH_SHORT).show();
}
});
}

private void checkPinOrFingerprint() {


// Implement fingerprint or PIN verification
// After successful verification:
startActivity(new Intent(this, MainActivity.class));
finish();
}

private void resetPassword() {


String email = etEmail.getText().toString().trim();
if (email.isEmpty()) {
Toast.makeText(this, "Enter your email first", Toast.LENGTH_SHORT).show();
return;
}

mAuth.sendPasswordResetEmail(email)
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
Toast.makeText(this, "Reset link sent to email", Toast.LENGTH_SHORT).show();
}
});
}
}
```

#### RouteCardActivity.java
```java
public class RouteCardActivity extends AppCompatActivity {
private EditText etRouteCardNo, etPartName, etPartNo, etPlannedQty;
private RecyclerView rvProcesses;
private ProcessAdapter processAdapter;
private List<Process> processList = new ArrayList<>();
private DatabaseReference dbRef;
private String routeCardId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_route_card_form);

dbRef = FirebaseDatabase.getInstance().getReference("route_cards");

// Initialize all views


initViews();

// Check if editing existing card


if (getIntent().hasExtra("route_card_id")) {
routeCardId = getIntent().getStringExtra("route_card_id");
loadRouteCardData();
} else {
routeCardId = dbRef.push().getKey();
}

findViewById(R.id.btnAddProcess).setOnClickListener(v -> showAddProcessDialog());


findViewById(R.id.btnSave).setOnClickListener(v -> saveRouteCard());
findViewById(R.id.btnGenerateQR).setOnClickListener(v -> generateQRCode());
}

private void initViews() {


etRouteCardNo = findViewById(R.id.etRouteCardNo);
etPartName = findViewById(R.id.etPartName);
etPartNo = findViewById(R.id.etPartNo);
etPlannedQty = findViewById(R.id.etPlannedQty);
rvProcesses = findViewById(R.id.rvProcesses);

processAdapter = new ProcessAdapter(processList, this);


rvProcesses.setLayoutManager(new LinearLayoutManager(this));
rvProcesses.setAdapter(processAdapter);
}

private void loadRouteCardData() {


dbRef.child(routeCardId).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
RouteCard routeCard = snapshot.getValue(RouteCard.class);
if (routeCard != null) {
etRouteCardNo.setText(routeCard.getCardNumber());
etPartName.setText(routeCard.getPartName());
etPartNo.setText(routeCard.getPartNo());
etPlannedQty.setText(String.valueOf(routeCard.getPlannedQty()));

if (routeCard.getProcesses() != null) {
processList.clear();
processList.addAll(routeCard.getProcesses());
processAdapter.notifyDataSetChanged();
}
}
}

@Override
public void onCancelled(@NonNull DatabaseError error) {
Toast.makeText(RouteCardActivity.this, "Failed to load data",
Toast.LENGTH_SHORT).show();
}
});
}

private void showAddProcessDialog() {


AlertDialog.Builder builder = new AlertDialog.Builder(this);
View view = getLayoutInflater().inflate(R.layout.dialog_process, null);

EditText etProcessName = view.findViewById(R.id.etProcessName);


EditText etMachineNo = view.findViewById(R.id.etMachineNo);
EditText etProdQty = view.findViewById(R.id.etProdQty);
EditText etRejQty = view.findViewById(R.id.etRejQty);
EditText etOperator = view.findViewById(R.id.etOperator);

builder.setView(view)
.setTitle("Add Process")
.setPositiveButton("Add", (dialog, which) -> {
Process process = new Process();
process.setProcessName(etProcessName.getText().toString());
process.setMachineNo(etMachineNo.getText().toString());
process.setProdQty(Integer.parseInt(etProdQty.getText().toString()));
process.setRejQty(Integer.parseInt(etRejQty.getText().toString()));
process.setOperator(etOperator.getText().toString());
process.setDate(new SimpleDateFormat("yyyy-MM-dd",
Locale.getDefault()).format(new Date()));

processList.add(process);
processAdapter.notifyDataSetChanged();
})
.setNegativeButton("Cancel", null)
.create()
.show();
}

private void saveRouteCard() {


RouteCard routeCard = new RouteCard();
routeCard.setCardId(routeCardId);
routeCard.setCardNumber(etRouteCardNo.getText().toString());
routeCard.setPartName(etPartName.getText().toString());
routeCard.setPartNo(etPartNo.getText().toString());
routeCard.setPlannedQty(Integer.parseInt(etPlannedQty.getText().toString()));
routeCard.setProcesses(processList);
routeCard.setUpdatedAt(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss",
Locale.getDefault()).format(new Date()));

dbRef.child(routeCardId).setValue(routeCard)
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
Toast.makeText(this, "Route card saved successfully",
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Failed to save route card", Toast.LENGTH_SHORT).show();
}
});
}

private void generateQRCode() {


// Generate QR code with route card ID
MultiFormatWriter writer = new MultiFormatWriter();
try {
BitMatrix bitMatrix = writer.encode(routeCardId, BarcodeFormat.QR_CODE, 400, 400);
BarcodeEncoder encoder = new BarcodeEncoder();
Bitmap bitmap = encoder.createBitmap(bitMatrix);

// Show QR code in dialog


AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(getLayoutInflater().inflate(R.layout.dialog_qr_code, null))
.setPositiveButton("Save", (dialog, which) -> saveQRCodeImage(bitmap))
.setNegativeButton("Share", (dialog, which) -> shareQRCode(bitmap))
.create()
.show();
} catch (WriterException e) {
e.printStackTrace();
}
}

private void saveQRCodeImage(Bitmap bitmap) {


// Save QR code to device storage
}

private void shareQRCode(Bitmap bitmap) {


// Share QR code via intent
}
}
```

### 4. Excel Export Implementation

#### ExcelExporter.java
```java
public class ExcelExporter {
public static void exportRouteCardToExcel(Context context, RouteCard routeCard) {
try {
// Create workbook
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("Route Card");

// Create header style


HSSFCellStyle headerStyle = workbook.createCellStyle();
HSSFFont headerFont = workbook.createFont();
headerFont.setBold(true);
headerStyle.setFont(headerFont);

// Add company header


createMergedCell(sheet, 0, 0, 0, 2, "SIVA PRESS COMPONENTS", headerStyle);
createMergedCell(sheet, 1, 0, 1, 2, "JOB ROUTE CARD", headerStyle);

// Add document info


createCell(sheet, 0, 18, "DOC.NO.", headerStyle);
createCell(sheet, 0, 20, "SPC/PROD/R/01", null);

// Add planning section


createCell(sheet, 3, 1, "PLANNING", headerStyle);
createCell(sheet, 3, 2, "Route card No.", null);
createCell(sheet, 3, 8, "Date.", null);
createCell(sheet, 3, 12, "Planned Qty", null);
createCell(sheet, 3, 17, "Customer Name:", null);

// Add route card data


createCell(sheet, 4, 1, "Part Name:", null);
createCell(sheet, 4, 9, "Part No", null);

// Continue adding all sections from the Excel template...

// Save the workbook


String fileName = "RouteCard_" + routeCard.getCardNumber() + ".xls";
File file = new File(context.getExternalFilesDir(null), fileName);
FileOutputStream out = new FileOutputStream(file);
workbook.write(out);
out.close();

// Notify user
Toast.makeText(context, "Excel exported to " + file.getPath(),
Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(context, "Export failed: " + e.getMessage(),
Toast.LENGTH_SHORT).show();
}
}

private static void createCell(HSSFSheet sheet, int rowNum, int colNum, String value,
HSSFCellStyle style) {
HSSFRow row = sheet.getRow(rowNum) != null ? sheet.getRow(rowNum) :
sheet.createRow(rowNum);
HSSFCell cell = row.createCell(colNum);
cell.setCellValue(value);
if (style != null) {
cell.setCellStyle(style);
}
}

private static void createMergedCell(HSSFSheet sheet, int rowNum, int colStart, int rowEnd,
int colEnd, String value, HSSFCellStyle style) {
CellRangeAddress region = new CellRangeAddress(rowNum, rowEnd, colStart, colEnd);
sheet.addMergedRegion(region);

HSSFRow row = sheet.getRow(rowNum) != null ? sheet.getRow(rowNum) :


sheet.createRow(rowNum);
HSSFCell cell = row.createCell(colStart);
cell.setCellValue(value);
if (style != null) {
cell.setCellStyle(style);
}
}
}
```

### 5. QR Code Implementation

#### QRCodeGenerator.java
```java
public class QRCodeGenerator {
public static Bitmap generateQRCode(String content) {
try {
BitMatrix bitMatrix = new MultiFormatWriter().encode(
content,
BarcodeFormat.QR_CODE,
512,
512,
Collections.singletonMap(EncodeHintType.MARGIN, 1)
);

int width = bitMatrix.getWidth();


int height = bitMatrix.getHeight();
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);

for (int x = 0; x < width; x++) {


for (int y = 0; y < height; y++) {
bitmap.setPixel(x, y, bitMatrix.get(x, y) ? Color.BLACK : Color.WHITE);
}
}

return bitmap;
} catch (WriterException e) {
e.printStackTrace();
return null;
}
}

public static void saveQRCode(Context context, Bitmap qrCode, String fileName) {


try {
FileOutputStream out = new FileOutputStream(new
File(context.getExternalFilesDir(null), fileName));
qrCode.compress(Bitmap.CompressFormat.PNG, 100, out);
out.close();

// Update gallery
MediaScannerConnection.scanFile(
context,
new String[]{file.getAbsolutePath()},
new String[]{"image/png"},
null
);
} catch (Exception e) {
e.printStackTrace();
}
}
}
```

### 6. Dashboard with Charts


#### DashboardActivity.java
```java
public class DashboardActivity extends AppCompatActivity {
private PieChart pieChart;
private DatabaseReference dbRef;

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

pieChart = findViewById(R.id.pieChart);
dbRef = FirebaseDatabase.getInstance().getReference("route_cards");

setupPieChart();
loadRouteCardStats();
}

private void setupPieChart() {


pieChart.setUsePercentValues(true);
pieChart.getDescription().setEnabled(false);
pieChart.setExtraOffsets(5, 10, 5, 5);
pieChart.setDragDecelerationFrictionCoef(0.95f);
pieChart.setDrawHoleEnabled(true);
pieChart.setHoleColor(Color.WHITE);
pieChart.setTransparentCircleRadius(61f);

Legend l = pieChart.getLegend();
l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM);
l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT);
l.setOrientation(Legend.LegendOrientation.HORIZONTAL);
l.setDrawInside(false);
l.setXEntrySpace(7f);
l.setYEntrySpace(0f);
l.setYOffset(0f);
}

private void loadRouteCardStats() {


dbRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
int total = 0, completed = 0, inProgress = 0, notStarted = 0;

for (DataSnapshot cardSnapshot : snapshot.getChildren()) {


RouteCard card = cardSnapshot.getValue(RouteCard.class);
if (card != null) {
total++;
switch (card.getStatus()) {
case "completed": completed++; break;
case "in_progress": inProgress++; break;
default: notStarted++; break;
}
}
}

updatePieChart(total, completed, inProgress, notStarted);


}

@Override
public void onCancelled(@NonNull DatabaseError error) {
Toast.makeText(DashboardActivity.this, "Failed to load stats",
Toast.LENGTH_SHORT).show();
}
});
}

private void updatePieChart(int total, int completed, int inProgress, int notStarted) {
ArrayList<PieEntry> entries = new ArrayList<>();
entries.add(new PieEntry(completed, "Completed"));
entries.add(new PieEntry(inProgress, "In Progress"));
entries.add(new PieEntry(notStarted, "Not Started"));

PieDataSet dataSet = new PieDataSet(entries, "Route Cards Status");


dataSet.setSliceSpace(3f);
dataSet.setSelectionShift(5f);
ArrayList<Integer> colors = new ArrayList<>();
colors.add(Color.parseColor("#4CAF50")); // Green
colors.add(Color.parseColor("#FFC107")); // Amber
colors.add(Color.parseColor("#F44336")); // Red
dataSet.setColors(colors);

PieData data = new PieData(dataSet);


data.setValueTextSize(11f);
data.setValueTextColor(Color.WHITE);

pieChart.setData(data);
pieChart.invalidate();
}
}
```

## Additional Features Implementation

### 1. Fingerprint/PIN Authentication

```java
public class BiometricAuthHelper {
private static final String PREFS_NAME = "auth_prefs";
private static final String PIN_KEY = "user_pin";
public static void setupBiometricAuth(Activity activity, BiometricAuthCallback callback) {
BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
.setTitle("Biometric Authentication")
.setSubtitle("Log in using your biometric credential")
.setNegativeButtonText("Use PIN")
.build();

BiometricPrompt biometricPrompt = new BiometricPrompt(activity,


ContextCompat.getMainExecutor(activity),
new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationSucceeded(@NonNull
BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
callback.onSuccess();
}

@Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
callback.onFailure();
}
});

biometricPrompt.authenticate(promptInfo);
}
public static void setupPinAuth(Activity activity, String pin) {
SharedPreferences prefs = activity.getSharedPreferences(PREFS_NAME,
Context.MODE_PRIVATE);
if (pin == null) {
// Verify existing PIN
showPinDialog(activity, prefs.getString(PIN_KEY, null), false);
} else {
// Set new PIN
prefs.edit().putString(PIN_KEY, pin).apply();
}
}

private static void showPinDialog(Activity activity, String correctPin, boolean isSetup) {


PinDialog dialog = new PinDialog(activity, correctPin, isSetup);
dialog.show();
}

public interface BiometricAuthCallback {


void onSuccess();
void onFailure();
}
}
```

### 2. Dark/Light Theme Implementation


```java
public class ThemeUtils {
private static final String PREFS_NAME = "theme_prefs";
private static final String THEME_KEY = "app_theme";

public static void applyTheme(Activity activity) {


SharedPreferences prefs = activity.getSharedPreferences(PREFS_NAME,
Context.MODE_PRIVATE);
boolean isDark = prefs.getBoolean(THEME_KEY, false);

if (isDark) {
activity.setTheme(R.style.AppTheme_Dark);
} else {
activity.setTheme(R.style.AppTheme_Light);
}
}

public static void toggleTheme(Activity activity) {


SharedPreferences prefs = activity.getSharedPreferences(PREFS_NAME,
Context.MODE_PRIVATE);
boolean isDark = prefs.getBoolean(THEME_KEY, false);
prefs.edit().putBoolean(THEME_KEY, !isDark).apply();

activity.recreate();
}
}
```

### 3. Data Backup Implementation

```java
public class BackupManager {
public static void backupData(Context context, BackupCallback callback) {
// Get all route cards from Firebase
DatabaseReference dbRef =
FirebaseDatabase.getInstance().getReference("route_cards");
dbRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
List<RouteCard> routeCards = new ArrayList<>();
for (DataSnapshot cardSnapshot : snapshot.getChildren()) {
RouteCard card = cardSnapshot.getValue(RouteCard.class);
if (card != null) {
routeCards.add(card);
}
}

// Create JSON backup


Gson gson = new Gson();
String json = gson.toJson(routeCards);
// Save to file
String fileName = "route_cards_backup_" +
new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new
Date()) + ".json";

try {
File file = new File(context.getExternalFilesDir(null), fileName);
FileWriter writer = new FileWriter(file);
writer.write(json);
writer.close();

callback.onBackupComplete(file.getAbsolutePath());
} catch (IOException e) {
callback.onBackupFailed(e.getMessage());
}
}

@Override
public void onCancelled(@NonNull DatabaseError error) {
callback.onBackupFailed(error.getMessage());
}
});
}

public static void restoreData(Context context, Uri backupUri, BackupCallback callback) {


try {
InputStream inputStream = context.getContentResolver().openInputStream(backupUri);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder stringBuilder = new StringBuilder();
String line;

while ((line = reader.readLine()) != null) {


stringBuilder.append(line);
}

String json = stringBuilder.toString();


Gson gson = new Gson();
Type type = new TypeToken<List<RouteCard>>(){}.getType();
List<RouteCard> routeCards = gson.fromJson(json, type);

// Upload to Firebase
DatabaseReference dbRef =
FirebaseDatabase.getInstance().getReference("route_cards");
for (RouteCard card : routeCards) {
dbRef.child(card.getCardId()).setValue(card);
}

callback.onRestoreComplete();
} catch (Exception e) {
callback.onRestoreFailed(e.getMessage());
}
}
public interface BackupCallback {
void onBackupComplete(String filePath);
void onBackupFailed(String error);
void onRestoreComplete();
void onRestoreFailed(String error);
}
}
```

## Final Implementation Notes

1. **Firebase Integration**:
- Set up Firebase Authentication for login/register
- Configure Realtime Database for route card storage
- Use Firebase Storage for company media (photos/videos)

2. **UI/UX Considerations**:
- Implement Material Design components for premium look
- Add animations for smooth transitions
- Ensure responsive layout for different screen sizes

3. **Security**:
- Implement proper Firebase security rules
- Encrypt sensitive data before storage
- Validate all user inputs

4. **Testing**:
- Test on various Android versions
- Verify Excel export/import functionality
- Test QR code generation and scanning

5. **Performance**:
- Optimize database queries
- Implement pagination for large datasets
- Cache frequently accessed data

This comprehensive implementation covers all your requirements for the Route Card
Management System, providing a robust solution for manual data entry with all the requested
features.

You might also like