ProgrammierenAi ToolsTests

Kann ChatGPT (OpenAI) eine Android App schreiben?

Könnt ihr euch vorstellen, dass ChatGPT alleine komplette Android Apps schreiben könnte? Ich zumindest nicht, daher probiere ich es einfach mal aus. Und ich will es ChatGPT richtig schwer machen! Ich will den Code nämlich nicht in 0815 Java haben, sondern die brandneue Supersprache Flutter von Google benutzen.

So wird der Versuch aufgebaut

Ich möchte den Versuch starten, eine App komplett von ChatGPT so simpel wie möglich gestalten zu lassen. Ich werde nur das Projekt erstellen, also keine Variablen oder ähnliches vorab definieren. So könnte theoretisch jeder Leser nach der Installation eines beliebigen Editors (ca. ~3 Minuten) am selben Punkt weitermachen wie ich gerade.

Als Sourcecode benutzen wir Flutter. Flutter ermöglicht Entwicklern, die mit der Programmiersprache Dart arbeiten möchten, atemberaubende Cross-Platform-Apps zu erstellen. Das bedeutet, dass Ihr Programm ohne größere Anpassungen auf viele verschiedene Plattformen anbieten könnt, ohne den Code anpassen zu müssen. Ich werde keine Voraussetzungen aktualisieren, was normalerweise bei Flutter üblich ist, sobald man ein wenig mehr damit macht.

Diese Apps will ich haben

Wie oben schon erwähnt soll die App komplett alleine von ChatGPT gebaut werden. Google spuckt für die meisten eine riesige Anzahl an Anleitungsmöglichkeiten aus, die meistens dennoch veraltet sind! Ich möchte also nichts mit einer Datenbank dahinter haben, was mit Nacharbeit von mir verbunden ist. Daher halte ich die folgenden Projekte für sinnvoll, denen ich auch ChatGPT zutrauen könnte:

  • Eine Termin-Buchungs-App (appointment app tutorial android – Ungefähr 4.420.000 Ergebnisse)
  • Todo-App (todo app tutorial android – Ungefähr 267.000.000 Ergebnisse)
  • Taschenrechner (calculator tutorial android – Ungefähr 27.400.000 Ergebnisse)

Ich würde fast behaupten, dass die oben genannten Ideen bereits nach einem Monat Programmiererfahrung möglich wären. Mal schauen ob ChatGPT unsere Flutter App zusammen bekommt.

Die Ausgabe von ChatGPT

Ich frage also Chat GPT folgendes:

write me a basic flutter appointment sourcecode app

Das Ergebnis:

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

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

class AppointmentApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Appointment App',
      home: AppointmentList(),
    );
  }
}

class AppointmentList extends StatefulWidget {
  @override
  _AppointmentListState createState() => _AppointmentListState();
}

class _AppointmentListState extends State<AppointmentList> {
  final _firestore = Firestore.instance;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Appointments'),
      ),
      body: StreamBuilder<QuerySnapshot>(
        stream: _firestore.collection('appointments').snapshots(),
        builder: (context, snapshot) {
          if (!snapshot.hasData) {
            return Center(
              child: CircularProgressIndicator(),
            );
          }
          final appointments = snapshot.data.documents;
          List<Widget> appointmentWidgets = [];
          for (var appointment in appointments) {
            final appointmentName = appointment.data['name'];
            final appointmentTime = appointment.data['time'];
            final appointmentWidget = ListTile(
              title: Text(appointmentName),
              subtitle: Text(appointmentTime),
              onLongPress: () {
                _showDialog(context, appointment.documentID);
              },
            );
            appointmentWidgets.add(appointmentWidget);
          }
          return ListView(
            children: appointmentWidgets,
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          _createAppointment(context);
        },
        child: Icon(Icons.add),
      ),
    );
  }

  void _createAppointment(BuildContext context) async {
    final appointment = await showDialog<Map<String, dynamic>>(
        context: context,
        builder: (context) {
          return AppointmentDialog();
        });
    if (appointment != null) {
      _firestore
          .collection('appointments')
          .add(appointment)
          .then((value) => Navigator.pop(context));
    }
  }

  void _showDialog(BuildContext context, String documentID) {
    showDialog(
        context: context,
        builder: (context) {
          return AlertDialog(
            title: Text('Delete Appointment?'),
            actions: <Widget>[
              FlatButton(
                child: Text('Cancel'),
                onPressed: () => Navigator.pop(context),
              ),
              FlatButton(
                child: Text('Delete'),
                onPressed: () {
                  _deleteAppointment(documentID);
                  Navigator.pop(context);
                },
              )
            ],
          );
        });

Copy Paste in den Editor und ich hab einen Sack voller Fehler weil die Plugins nicht mehr so verwendet werden. Viele der Funktionen sind „deprecated“ also veraltet! Ein Anfänger würde relativ schnell merken, dass er die App lieber selber schreiben lernen sollte.

ChatGPT kann Android nicht
So wird die App niemals laufen. Ich muss quasi alles umschreiben!

Hier nun die Anfrage für die Todo App die wir bauen möchten:

write me a flutter todo app

import 'package:flutter/material.dart';

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

class TodoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Todo App',
      home: TodoList(),
    );
  }
}

class TodoList extends StatefulWidget {
  @override
  _TodoListState createState() => _TodoListState();
}

class _TodoListState extends State<TodoList> {
  List<String> _todoItems = [];

  void _addTodoItem(String task) {
    if(task.length > 0) {
      setState(() {
        _todoItems.add(task);
      });
    }
  }

  void _removeTodoItem(int index) {
    setState(() {
      _todoItems.removeAt(index);
    });
  }

  void _promptRemoveTodoItem(int index) {
    showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
              title: Text('Mark "${_todoItems[index]}" as done?'),
              actions: <Widget>[
                FlatButton(
                  child: Text('CANCEL'),
                  onPressed: () => Navigator.of(context).pop(),
                ),
                FlatButton(
                  child: Text('MARK AS DONE'),
                  onPressed: () {
                    _removeTodoItem(index);
                    Navigator.of(context).pop();
                  },
                )
              ]
          );
        }
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Todo List'),
      ),
      body: _buildTodoList(),
      floatingActionButton: FloatingActionButton(
        onPressed: _pushAddTodoScreen,
        tooltip: 'Add task',
        child: Icon(Icons.add),
      ),
    );
  }

  Widget _buildTodoList() {
    return ListView.builder(
      itemBuilder: (context, index) {
        if(index < _todoItems.length) {
          return _buildTodoItem(_todoItems[index], index);
        }
      },
    );
  }

  Widget _buildTodoItem(String todoText, int index) {
    return ListTile(
      title: Text(todoText),
      onTap: () => _promptRemoveTodoItem(index),
    );
  }

  void _pushAddTodoScreen() {
    Navigator.of(context).push(
        MaterialPageRoute(
        builder: (context) {
      return Scaffold(
          appBar: AppBar(
          title: Text('Add a new task'),
    ),
    body: TextField(
    autofocus: true,
    onSubmitted: (val

    ) {
    _addTodoItem(val);
    Navigator.pop(context); // Close the add todo screen
    },
      decoration: InputDecoration(
        hintText: 'Enter something to do...',
        contentPadding: const EdgeInsets.all(16.0),
      ),
    ),
      );
        }
        )
    );
  }
}

Der Quellcode sieht schon deutlich besser aus. Es gibt keine Fehler die kritisch sind, ich kann also die App sofort starten ohne etwas ändern zu müssen.

Das war doch mal ein voller Erfolg. Die App starten, ist leicht benutzbar und erfüllt unsere Grundfunktionen. Sehr gut!

Nun probieren wir mal eine Taschenrechner App aus. Solch eine App wird gerne verwendet um Neulinge gewisse Grund Rechenoperationen beim Programmieren beizubringen.

Chat GPT haut uns nun den folgenden Taschenrechner Soure-Code für Flutter raus:

import 'package:flutter/material.dart';

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

class CalculatorApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Calculator App',
      home: Calculator(),
    );
  }
}

class Calculator extends StatefulWidget {
  @override
  _CalculatorState createState() => _CalculatorState();
}

class _CalculatorState extends State<Calculator> {
  String _output = "0";
  String _output1 = "";
  double num1 = 0.0;
  double num2 = 0.0;
  String operand = "";

  buttonPressed(String buttonText) {
    if (buttonText == "CLEAR") {
      _output = "0";
      _output1 = "";
      num1 = 0.0;
      num2 = 0.0;
      operand = "";
    } else if (buttonText == "+" ||
        buttonText == "-" ||
        buttonText == "/" ||
        buttonText == "X") {
      num1 = double.parse(_output);
      _output1 = _output1 + _output + buttonText;
      operand = buttonText;
      _output = "0";
    } else if (buttonText == ".") {
      if (_output.contains(".")) {
        print("Already contains a decimal");
        return;
      } else {
        _output = _output + buttonText;
      }
    } else if (buttonText == "=") {
      num2 = double.parse(_output);
      if (operand == "+") {
        _output = (num1 + num2).toString();
      }
      if (operand == "-") {
        _output = (num1 - num2).toString();
      }
      if (operand == "X") {
        _output = (num1 * num2).toString();
      }
      if (operand == "/") {
        _output = (num1 / num2).toString();
      }
      num1 = 0.0;
      num2 = 0.0;
      operand = "";
    } else {
      _output = _output + buttonText;
    }
    print(_output);
  }

  Widget buildButton(String buttonText) {
    return Expanded(
      child: ElevatedButton(
        child: Text(
          buttonText,
          style: TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
        ),
        onPressed: () => buttonPressed(buttonText),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Calculator'),
        ),
        body: Container(
            child: Column(children: <Widget>[
              Container(
                  alignment: Alignment.centerRight,
                  padding: EdgeInsets.symmetric(
                    vertical: 24.0,
                    horizontal: 12.0,
                  ),
                  child: Text(
                    _output1 + _output,
                    style: TextStyle(
                      fontSize: 48.0,
                      fontWeight: FontWeight.bold,
                    ),
                  )),
              Expanded(
                child: Divider(),
              ),
              Column(
                children: [
                  Row(
                    children: [
                      buildButton("7"),
                      buildButton("8"),
                      buildButton("9"),
                      buildButton("/"),
                    ],
                  ),
                  Row(
                    children: [
                      buildButton("4"),
                      buildButton("5"),
                      buildButton("6"),
                      buildButton("X"),
                    ],
                  ),
                  Row(
                    children: [
                      buildButton("1"),
                      buildButton("2"),
                      buildButton("3"),
                      buildButton("-"),
                    ],
                  ),
                  Row(
                    children: [
                      buildButton("."),
                      buildButton("0"),
                      buildButton("00"),
                      buildButton("+"),
                    ],
                  ),
                  Row(
                    children: [
                      buildButton("CLEAR"),
                      buildButton("="),
                    ],
                  )
                ],
              )
            ])));
  }
}

Auch hier sind veraltete Funktionen verwendet worden, diese sind aber noch innerhalb in der Toleranz und auch hier kein Fehler! Starten wir die App mal und probieren wir eine Beispielsrechnung direkt aus.

Auch hier funktioniert der Sourcecode, allerdings gibt es einen Fehler mit der Abfrage, die wir tätigen. Entsprechend gibt uns der Taschenrechner visuell keine Antwort auf unsere Rechenfrage. Das ist echt blöd. Ich habe darauf hin den Debugger aktiviert, was für einen Anfänger vermutlich schon zu viel wäre.

In dem Debugger sieht man das die Rechnung scheinbar doch funktioniert, und sogar fehlerfrei! Auch Punkt vor Strichrechnungen ist kein Problem. Aber ohne visuelle Rückmeldung bringt mir der Taschenrechner leider auch nichts.

Die Bewertung

Ich habe mir heute die Grund Apps eines jeden Entwicklers komplett nur von ChatGPT ausgeben lassen. Die Apps haben größtenteils funktioniert, waren allerdings oft mit veralteten Funktionen gefüllt, die nicht mehr funktionieren. Durch viel experimentieren konnte ich die Apps zum Laufen kriegen, aber das war diesmal kein Ziel von uns.

Kleine Randnotiz:

Als ich den Sourcecode durch einen Plagiat Prüfer durchjagte, wurde mir ein Wert von Durchschnittlich 20% wiedergegeben. Das ist völlig in Ordnung!

Kodeaffe

Leidenschaftlicher Informatiker. Mit einem C64 angefangen und nun in der Welt der AI angekommen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert