Programmentwicklung - Vorgehensweise

  • Hallo zusammen,


    ich beginne gerade zwangsläufig mit der Programmierung von Android Apps. Ich studiere Elektrotechnik und muss in meinem Praktikum eine Anwendung für Android realisieren. Mein Problem ist, das ich leider in meiner Uni nie eine Vorlesung zu Java hatte und somit völlig neu in diesem Gebiet bin. Ich habe allerdings einige Kenntnisse im Bereich C und C++ sowie Assembler, das heißt das Programmieren ist mir nicht ganz neu.


    Ich habe mir nun ein Buch zu Java durchgelesen um mich damit vertraut zu machen - allerdings ist die Realisierung eines richtigen Projektes doch noch was anderes als der typische Uni Kram ;)


    So viel mal zur Vorgeschichte.


    Ich stehe nun davor, wie ich mit meinem Projekt starte und möchte daher kurz die Funktion beschreiben.


    Im Prinzip geht es darum, das die App sich über einen Login an einem Server anmelden soll, dort Datensätze ( SQL Datenbank ) herunterladen soll und diese auf dem Display darstellen soll.


    Das klingt nun sicher für viele hier trivial, aber für einen Anfänger wie mich ist das schon eine Aufgabe ;)


    Könnt ihr mir ein paar Tips diesbezüglich geben, wie man am besten an ein solches Problem rangeht und welche Möglichkeiten es dafür gibt?


    Mir fehlt leider einfach die praktische Erfahrung um zu wissen, wie man am Besten an so etwas herangeht - besten Dank schonmal.


    Beste Grüße

  • Guten Morgen Chris,


    gleich vorab: zum SQL Server und dessen Abfrage kann ich dir leider keine Lösung nennen. Ich stehe nämlich vor genau dem gleichen Problem. :)
    Daher hänge ich mich an deine Anfrage an. Auch ich habe vor, eine App zu schreiben die Daten vom SQL Server abruft (per WLAN im gleichen Netz) und anzeigt.


    Wenn du allgemeine Anregung haben willst, dann kannst du dir mal das Tutorial anschauen: "thenewboston ". Der Ersteller des Tutorials zeigt sehr viele Techniken. Die fertige App kannst du dir kostenlos im Market herunterladen um mal zu schauen: Google Play
    Genau diese App wird im Tutorial angefertigt. Er fängt auch ganz locker an und sagt ausdrücklich, dass man keine Java Kenntnisse braucht. Er versucht wirklich es ganz einfach zu erklären. Ein Beispiel zu Datenbanken (SQLite) findest du wenn du die App startest unter dem Punkt "SQLite Example". Wie man einen externen SQL Server anbindet wird leider nicht erklärt.


    Wie man auf einen SQL Server zugreift wird hoffentlich jemand aus dem Forum hier klären können.


    Gruß Philipp

  • Hi Chris-Pi,


    erstmal Willkommen im Forum :D


    Nun zu deiner Frage:
    An deiner Stelle würde ich nicht direkt vom App die SQL-Datenbank zugreifen. Wenn du die Möglichkeit hast, "stell" zum Beispiel ein PHP-Script davor. Dieses nimmt die Anfragen entgegen, validiert sie und gibt dann die Datensätze im XML oder JSON-Format an den Client zurück. Die Antwort kannst du dann auf dem Client auswerten und dann darstellen.


    Dieses Vorgehen hat zum einen den Vorteil das auf dem Server noch einmal geprüft werden kann, ob die Datensätzen die in die DB geschrieben werden auch wirklich so sind wie sie sein sollen. Und zum anderen kannst du so sehr einfach steuern das nur Daten in die DB geschrieben werden die auch vollständig sinn. Das wäre zum beispiel der Fall falls deine UTMS-Verbindung abreist wenn du durch einen Tunnel fährst.


    Tuts die dir vielleicht weiter helfen könnten:


    Android HTTP Access - Tutorial - Vogella
    Auslesen eines RSS-Feeds(XML)
    JSON in Android - Tutorial - Vogella


    Hoffe das bringt dich ein wenig weiter, falls nicht frag einfach nochmal :D



    Mfg Titus

  • Hallo an Euch Zwei,


    erst einmal vielen Dank für eure Antworten die mir schonmal sehr weitergeholfen haben. Leider kann ich den YT Link noch nicht öffnen da ich mein Praktikum in China absolviere und mein Proxy sich heute noch nicht so wirklich gemeldet hat, aber sobald es geht, schaue ich rein.


    Danke auch für den Tipp mit dem PHP, ich werde mich mal einlesen und versuchen es so zu realisieren.


    Mal eine Frage, da ich wie gesagt ein absoluter Anfänger bin.


    Wie funktioniert das mit dem PHP Skript? Lauscht das an einem definierten Port und sendet/empfängt dann die Informationen wenn die entsprechenden Anfragen kommen?


    Ansonsten hier mal mein jetziger Stand - natürlich erstmal alles Bastellösung ;)


    - Startseite Activity als Login zur Eingabe von User und Pass mit OK und Cancel
    - Bei Cancel erfolgt aufruf von finish()
    - bei OK wird Überprüft wie der Netzwerk Status ist und bei Zugriff auf das Netzwerk die HTTP Anfrage ausgelöst ( siehe Guide Vogella )
    - bei nichtvorhandenem Netzwerk wird eine zweite Activity gestartet, mit einem Text-Element und einem Button zum bestätigen -> dieser Verlinkt wieder auf den Login bereich


    Das ist sicher alles noch nicht das goldene vom Ei und kann alles noch angepasst werden - erstmal muss das Funktionale passen. Ich würde mich jetzt mal mit dem PHP / SQL Skript und der Verbindung dieser auseinander setzen oder sollte ich was anderes noch beachten?


    Ich danke schonmal,


    Beste Grüße

  • Guten Morgen Titus,


    ich lese sehr interessiert mit :)
    Aus deiner Antwort lese ich, dass es möglich ist die Lösung ohne vorgelagerten Webserver zu realisieren - das interessiert mich stark. Ich will nur lesend zugreifen und sichere dies durch die SQL Permissions. Leider konnte ich dazu außer diesem Schnipsel bisher keinen Ansatz finden.




    Hast du zufällig eine Seite auf Lager die das Vorgehen beschreibt? Google war leider abgesehen von PHP und ASP.net Lösungen mit Basic4Android und anderen wilden Geschichten nicht mein Freund. Eine Realisierung in der App selber direkt zum Server wäre echt super.


    Viele Grüße
    Philipp

  • HI,


    Geolevel_de:


    Geht der Code oder gibt es eine Fehlermeldung?
    Zwecks Tuts hab ich leider nur diese Seite aber irgendwie sieht das verdächtig nach deinem Code aus. Also ist es wahrscheinlich nix neues für dich.
    Sry aber ich mach in der Regel den Weg wie oben beschrieben.


    Chris-Pi:

    Zitat

    Wie funktioniert das mit dem PHP Skript? Lauscht das an einem definierten Port und sendet/empfängt dann die Informationen wenn die entsprechenden Anfragen kommen?


    Nein so kompliziert ist es nicht, du rufst das Script automatisch auf wenn du die URL aufrufst.
    Beispiel:
    http://www.das-ist-meine-url.de/stript_für_DB.php


    Zitat

    - bei nichtvorhandenem Netzwerk wird eine zweite Activity gestartet, mit einem Text-Element und einem Button zum bestätigen -> dieser Verlinkt wieder auf den Login bereich


    mach doch einfach ein Alert bzw einen Dialog -> dieser geht bei nicht vorhandener Netzwerkverbindung auf und sagt dem User er soll gefälligst das I-Net wieder anmachen.


    Mfg TItus

  • Hallo Titus,


    vielen Dank für den Link! Bisher hatte ich nur den Quelltext in einem Forum gefunden. Die ersten beiden Steps waren da aber nicht zu lesen - drum ging es wohl nicht :)


    Code
    1. First of all you need a JDBC driver library for SQL Server. As we know android library has only SQLite database driver. So first download an open source JDBC driver from this http://jtds.sourceforge.net/ site (I downloaded the Linux version).
    
    
    2. Then import the jar file into your Android app.(jtds-1.2.5.jar).


    Vielen Dank nochmals! Ich denke das bringt mich weiter!


    Gruß Philipp

  • Hallo titus,


    Danke für deine Informationen - das bringt mich wirklich sehr weiter.


    Ich habe die letzten Tage erstmal einen Apache Server + Datenbank und das php File angelegt - der Abruf der Daten über das php File funktioniert schonmal - *puuh*


    Nun geht es mehr oder weniger daran, die Datenübertragung zu realisieren über JSON - ich habe vieles gelesen und das Prinzip ist mir ein wenig bewusst geworden - mal schauen wie das mit der Umsetzung funktioniert. Ich werde mich mal daran versuchen und ggf. nochmal um Hilfe bitten, was das angeht.


    Habe aber trotzdem mal wieder eine Frage - bezüglich eines Login - User/Pass und der Realisierung - auch wenn es sicher Anwendungsabhängig ist.


    Ist es richtig, das man diese an das php File sendet und dieses in einer seperaten DB einen Vergleich durchführt und dann ggf. Zugriff / Nicht Zugriff regelt, das heißt in einer DB wo ledeglich User/Pass Informationen enthalten sind?




    Oder wie macht man sowas?


    Grüße

  • Hallo,


    ich nochmal. Ich habe heute noch ein wenig gebastelt und mithilfe von einem guten Tutorial einiges hinbekommen. Das Tutorial findet man hier - den Quelltext habe ich auch so übernommen und nachvollziehen können, soweit es ging.


    http://www.androidhive.info/20…ith-php-mysql-and-sqlite/



    Ich habe nun nur ein Problem - wie auch in den Comments dort schon beschrieben benötigt man wohl diese Auslagerung in einen seperaten Thread für die HTTP Anfrage.


    Leider gestaltet sich das als ein wenig schwierig wie ich finde. Das was ich bei Google dazu finde, ist mir leider etwas zu Hoch, da die meisten doch schon sehr mit Android dort vertraut sind.


    Wie realisiert man das den in so einem Fall am besten?


    Ich bin leider wirklich Ahnungslos.


    Beste Grüße

  • Hallo nochmal,


    so ich habe wieder mal ein wenig gebastelt, und so langsam - Stück für Stück verstehe ich ein paar von den Dingen, die da so stehen.


    Ich habe mithilfe der geposteten Links ein wenig was basteln können, konnte es sogar zum Großteil nachvollziehen, was für mich als Programmier-Neuling nich ganz einfach war. Habe den Code noch ein wenig angepasst und die einzelnen Abschnitte in mehrere Klasse aufgeteilt und stehe nun vor neuen Problemen:


    Hier mal das, was ich bisher so gemacht habe:


    Wollte übrigens das ganze in die vorgeshenen Code-Boxen schreiben, aber da wird mein Quellcode jedesmal unlesbar verschoeben, daher jetzt leider nur so.


    - Meine Activity Class erzeugt beim Aufrufen ein Objekt um die HTTP Anfrage zu erstellen in einer seperaten Klasse und ruft zugehörige Methode auf


    --------------------------------------------------------------------------------------------------------------------------------------------------



    public class ActivityData extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_activity_data);

    ConnectionHttp ConnectionHttp_Instanz = new ConnectionHttp (this);

    ConnectionHttp_Instanz.getData();


    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_activity_data, menu);
    return true;

    }

    }
    -------------------------------------------------------------------------------------------------------------------------------------------------


    Diese Klasse realisiert die Verbindung, habe ich so von dem Tutorial übernommen und ein wenig angepasst. Wichtig ist ja hier der Aufruf für den Hintergrundprozess durch Erzeugung eines "ReadData" objektes.


    -------------------------------------------------------------------------------------------------------------------------------------------------



    public class ConnectionHttp {

    private final String TAG = ActivityLogin.class.getSimpleName();
    private final String url = "http://192.168.1.107/test1.php";

    // Konstruktor

    public ConnectionHttp(Activity activityData)
    {
    activity = activityData;
    }
    // Activity Member fuer aktuelle GUI -> AcitivityData -> notwendig fuer Meldungen auf GUI
    private Activity activity;


    // HTTP

    public void getData()
    {

    //der HttpClient dient dazu die Anfrage an den Server zu stellen
    HttpClient client = new DefaultHttpClient();


    //Art der Anfrage
    HttpGet httpGet = new HttpGet(url);


    //Antwort des Severs
    HttpResponse response = null;


    try {
    //ausführen der Anfrage
    response = client.execute(httpGet);


    } catch (ClientProtocolException e) {
    Log.e(TAG,"Falsches Protokol " + " " + e.getMessage());
    } catch (IOException e) {
    Log.e(TAG,"URL ist falsch, URL:"+ url + " " + e.getMessage());
    }


    //Kontrolle ob bei ausführen der Anfrage ein Fehler aufgetreten ist
    if(response != null){


    //Status der Abfrage
    StatusLine statusLine = response.getStatusLine();


    //Statuscode 200 => Die Anfrage wurde erfolgreich bearbeitet und das Ergebnis der Anfrage wird in der Antwort übertragen
    if(statusLine.getStatusCode() == 200) {


    //Ergebnis der Anfrage
    HttpEntity entity = response.getEntity();


    try {
    //Start des Hintergrundprozess um zu parsen -> neue ReadData Instanz erzeugen
    // Übergabe der derzeitigen GUI als activity
    new ReadData(activity).execute(entity.getContent());


    } catch (IllegalStateException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    else{
    Toast.makeText(activity,"Der Server antwortet mit anderen Statuscode als 200. Statuscode: "+statusLine.getStatusCode(), Toast.LENGTH_SHORT).show();
    }
    }
    else{
    Toast.makeText(activity,"Keine Internetverbindung.", Toast.LENGTH_SHORT).show();
    }
    }


    }


    -------------------------------------------------------------------------------------------------------------------------------------------------



    Jetzt kommt ja die eigentliche Verarbeitung des InputStreams, insofern ich das Richtig verstanden habe.


    -------------------------------------------------------------------------------------------------------------------------------------------------



    public class ReadData extends AsyncTask<InputStream, Void, Void> {



    // Anzeige das vom Server geladen wird


    private ProgressDialog dialog;
    private String TestString;
    private Activity activity1;


    // Konstruktor
    public ReadData(Activity activity)
    {
    dialog = new ProgressDialog(activity);
    activity1 = activity;
    }


    // wird VOR onInBackground ausgeführt


    protected void onPreExecute()
    {
    // einrichten des Wartedialogs
    this.dialog.setTitle("Bitte warten!");
    this.dialog.setMessage("Daten werden geladen");
    this.dialog.show();
    }


    // Aktion im Hintergrund


    protected Void doInBackground(InputStream... inputStreams)
    {
    // Hier Aktion fuer Hintergrund
    return null;
    }


    // Aktion NACH Ausführung


    protected void onPostExecute(Void result)


    {
    // Dialog beenden
    if (dialog.isShowing()) {
    dialog.dismiss();
    }
    // Write to Text
    }
    }


    -------------------------------------------------------------------------------------------------------------------------------------------------


    Das ist erstmal was ich bisher so habe, sicher ist das weit ab von gutem Programmierstil und kann sicher tausend mal besser gemacht werden, aber ich bin froh, erstmal soweit gekommen zu sein - in der Hoffnung das es irgendwann mal funktioniert.


    Mein Problem ist jetzt, ich wollte erstmal versuchen, einen einfachen String von einem php Dokument zu laden und mir anzeigen zu lassen, um einfach mal überprüfen zu lassen, ob die Verbindung überhaupt klappt - leider komme ich da nicht ganz weiter.


    Meine Idee war jetzt, das ich den Inputstream in einen String wandeln muss um diesen dann z.B. auf einem TextView auszugeben, ist das Richtig?


    Ich habe da auch schonmal ein wenig rumprobiert und ein paar Sachen zu im Internet gefunden, leider bin ich daran gescheitert, wie ich diesen String, der dann entsteht, auf ein TextView in der Acitivty schreibe?


    Ich wollte eigentlich eine Methode in der Activity erzeugen und dieser den String übergeben, leider weiss ich aber nicht, wie die Instanz der Activity heißt um diese Methode anzusprechen, daher habe ich versucht die Activity im Konstruktor immer zu übergeben, um von der Klasse "ReadData" aus, das TextView anzusprechen, das funktionierte aber auch nicht.


    Wäre daher schön zu wissen, wie das jetzt genau Funktioniert, von einer Klasse außerhalb der Activity die TextView anzusprechen?


    Wenn das schonmal funktionieren würde, wäre ich schon sehr froh um mich dann um das weitere zu kümmern, wie den Parser etc. - aber eins nach dem anderen, möchte ja auch lernen was ich hier tue.



    Eine paar weitere Fragen noch:


    - protected Void doInBackground(InputStream... inputStreams)



    Ich verstehe noch nicht ganz, wie InputStream funktioniert - bzw, wie die Daten dort gespeichert sind. Welche Länge haben die Datenfelder bzw. wie ist es gespeichert?


    Wie sieht eine sinnvolle weiterverarbeitung aus?


    - AsyncTask<InputStream, Void, Void>


    Ich verstehe leider nicht und habe dazu auch nich gefunden, was die Parameter hinter dem Klassennamen bedeuten? Ich habe so eine Syntax leider noch nie gesehen.



    Tut mir leid, für die sicher vielen Anfänglichen-Fragen, aber so heißt das Forum ja auch. Danke falls sich jemand die Zeit nehmen würde, einem Anfänger das ganze ein wenig näher zu erklären.


    Beste Grüße

  • Ein sehr gutes Tutorial zum Thema HTTP Request (z.B. STring von PHP Seite laden) findest du hier


    http://www.androidhive.info/20…oid-making-http-requests/



    Ich finde die Tutorialreihe recht gut, das Sie immer ausgefeilter wird.
    Momentan willst du nur einen String lesen, wenn du aber demnächst Daten zwischen APP und Server hin und her schieben willst, dann
    findest du dort auch eine Erweiterung des HTTP Beispiels und bekommst erklärt wie man zB. POST/GET Request absetzt und die Rückantwort per JSON formatiert bzw. JSON in der App richtig verarbeitet.


    Wie gesagt da lohnt sich ein Blick auf jeden Fall.


    ------------------------------------------------------------
    Falls du gerade keine Lust auf viel Lesestoff hast, hier die QuicknDirty Variante .> http-> String (text steht am Ende in Page)




    --------------------------------------------------------------------------------------------------


    Wäre daher schön zu wissen, wie das jetzt genau Funktioniert, von einer
    Klasse außerhalb der Activity die TextView anzusprechen?


    -> heisses Eisen,
    normalerweise machst du das innerhalb deiner Activity, weil du nie wissen kannst ob die Activity bereits/noch existiert .


    in der oncreate Methode suchst du dir in deiner Activity per findbyView den entsprechenden Textview und speicherst Ihn in einer Variable.
    -> dann rufst du deine ReadData routine auf (per Asynctask)(die kann extern in einer Klasse liegen und liefert Dir halt nur die Daten zurück -> kein Zugriff auf UI Elemente -> und diese Rückgabewerte baust du in deinen Textview ein.


    -> und den Textview immer schön gegen Null testen, -> somit vermeidest du Nullpointerexceptions, falls die Activity schon wieder weg ist.


    if (meintextview != Null){
    mache schöne sachen
    }

  • Funktioniert - wunderbar - zumindest den String auslesen und anzeigen in einem Dialog.


    Ich habe jetzt auch ein wenig mehr den Sinn der Parameter von Asynctask verstanden, klasse!


    Das einzige was ich noch nicht ganz verstehe, wie ich dann das Resultat zurückgeben kann, also an die Activity.


    Das mit der Variablen und der TextView habe ich auch soweit schon - nur wie jetzt auf den String zugreifen?


    Besten Dank an dich, das war wirklich sehr hilfreich!


    Beste Grüße

  • Wie gesagt, am besten ist wenn du die Aufgaben mit dem Asynctask aus deiner Activity heraus aufrufst, dann hast du ja im Teil von "postExecute" komplett Zugriff auf UI Elemente deine Activity und kannst sie mit Daten befüllen.


    NAMEDEINERACTIVITY.VARIABLENNAME = meinWert;


    ------------- Wichtig dabei nur der Test ob die UI Elemente noch existieren (gg NULL)


    Angenommen, du lädst deinen RSS Feed aus Neuseeland, und das dauert Ewig , der User hat keine Lust mehr und verlässt deine App bzw. wechselt zu einer anderen Activity dann gibt es halt den Zugriff auf nicht mehr existierende Vars.


    -------------------------------------------------------------------------------------------------------------------------------



    Sicher kann man das auch noch mit Handlern lösen aber das ist nicht so mein Thema, da weiss bestimmt jmd anderes Bescheid.

  • Danke für die Info - mittlerweile habe ich das Hinbekommen.


    Ich habe nun ein neues Problem und zwar die Daten in der Liste darzustellen. Ich habe mich schon sehr gründlich mit der ListView befasst, da es doch sehr viele Tutorials gibt, aber ich bekomme es nicht hin.


    Code
    ArrayList<HashMap<String, String>> deviceList;


    Dort habe ich meine Daten gespeichert und möchte diese nun in einer Liste abspeichern und anzeigen.


    In meiner ListActivity rufe ich dazu folgendes auf


    Code
    ListAdapter adapter = new DeviceListAdapter(ActivityDevice.this, R.layout.device_list_row, deviceList);setListAdapter(adapter);



    Die Klasse DeviceListAdapter sieht wie folgt aus


    ******************************************************



    public class DeviceListAdapter extends ArrayAdapter<ArrayList<HashMap<String, String>>> {

    private final Context context;
    private ArrayList<HashMap<String, String>> deviceList;


    // Konstruktor

    public DeviceListAdapter(Context context, int layoutResourceId, ArrayList<HashMap<String, String>> deviceList) {
    super(context, layoutResourceId);
    this.context = context;
    this.deviceList = deviceList;

    }

    // getView() von ArrayAdapter überschreiben

    @Override
    public View getView(int position, View convertView, ViewGroup parent)

    {

    // Farben als KONST aus RGB Farbtabelle mit Format 0xFF[FARBCODE]

    final int RED = 0xFFFF0000;
    final int GREEN = 0xFF00FF00;


    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View rowView = inflater.inflate(R.layout.device_list_row, parent, false);

    // Referenz auf Text und Bild

    TextView deviceName = (TextView) rowView.findViewById(R.id.textViewListDeviceName);
    TextView deviceProducer = (TextView) rowView.findViewById(R.id.textViewListDeviceProducer);
    TextView deviceModell = (TextView) rowView.findViewById(R.id.textViewListDeviceModell);
    TextView deviceStatus = (TextView) rowView.findViewById(R.id.textViewListDeviceStatus);
    ImageView deviceImage = (ImageView) rowView.findViewById(R.id.deviceImage);


    // Daten schreiben in Liste



    return rowView;

    }


    }
    ************************************************


    In der Methode getView() müssen ja jetzt die Daten aus der ArrayList in die Liste eingetragen werden.


    Wie kann man das anstellen?


    Ich kann mir vorstellen, das man dort eine For Schleife nutzen muss und irgendwie das Array durchgehen muss, leider fehlt mir aber die Umsetzung.


    Habt ihr ein paar Tipps für mich?


    Besten Dank

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!