Zum Forum springen
Benachrichtigungen
Alles löschen

Programmieren lernen - How to be a coder

153 Beiträge
42 Benutzer
142 Reactions
26.3 K Ansichten
swizz
Beigetreten: 02.03.2006

@BjoernBoba
Dein Beitrag geht glaube ich über meinen Horizont hinaus. Vermutlich ist das für meine Zwecke auch zu kompliziert. Die JSON-Datei um die es bei mir geht, ist nur 14 kb groß.

Firebase von Google habe ich mir mal angeschaut. Das finde ich eigentlich ziemlich cool vom Prinzip her, da bin ich aber an der Umsetzung gescheitert. Außerdem müssen da glaube ich alle Teilnehmer, die Zugangsdaten besitzen, oder?

Das mit den Push-Notifications schaue ich mir dann auch noch mal an.

Aktuell habe ich es so gemacht, dass die JSON-Datei im Client gespeichert wird und man per Button aktualisiert. Das reicht erstmal für meine Zwecke, allerdings ist das nicht wirklich schön.

Jetzt habe ich noch eine Frage. Ich habe es hinbekommen, dass ich in meiner Admin-App die Daten auf einen FTP-Server kopiere. Allerdings klappt das nur in meinem Virtual-Device. In der App auf dem Handy bekomme ich diese Fehlermeldung:

07-19 18:43:30.481 5643-6605/de.mc4735.copa_admin W/System.err: java.net.ConnectException: failed to connect to .......2001:8d8:1000:9071:766a:5e0a:2459:b815 (port 21) from /:: (port 46593): connect failed: ECONNREFUSED (Connection refused)

Für mich wirkt es so, als hätte die App auf dem Handy keine Berechtigung ins Internet zu gehen. Stimmt das so?

In den Einstellungen steht auch, dass für die App keine Berechtigung erforderlich wären.

Komischerweise ist das bei der Client-App genauso, die schafft es aber die Daten vom Server zu laden.

Wird bei der Berechtigung für das Internet vielleicht irgendwie zwischen Upload und Download unterschieden?


Antwort
Zitat
bumblebeebee
Beigetreten: 06.06.2006

Hast du wirklich nen FTP Server auf dem du Dateien ablegst und abrufst? Da gibt es natürlich Unterschiede zwischen Lese- und Schreibrechen.

"State of the Art" ist aber folgendes: Du hast einen HTTP Server, der GET und POST Requests verarbeiten kann. Das kann ein einfaches PHP Skript sein, geht aber auch in jeder anderen relevanten Programmiersprache. Für Java z.B. mit dem Spring Framework: https://spring.io/guides/gs/serving-web-content/

Um Daten auf den Server zu bekommen macht dein HTTP Client in der App einen POST Request in dessen Body die Daten sind. Eine Methode auf dem Server nimmt den POST entgegen und speichert die Daten irgendwo.
Um Daten abzurufen macht der Client einen GET Request. Eine Methode auf dem Server nimmt den GET entgegen und schickt die Daten im Response.

Als Client finde ich Retrofit ganz cool https://square.github.io/retrofit/ oder halt Volley von Google https://developer.android.com/training/volley/

Um automatisch Requests aus der App zu versenden brauchst du irgendeinen Scheduler oder Job, der das alle paar Minuten macht. Gibts mehrere Möglichkeiten: https://medium.com/hypertrack/scheduling-tasks-in-android-made-easy-231ca8178e38


Antwort
Zitat
swizz
Beigetreten: 02.03.2006

Original von bumblebeebee
Hast du wirklich nen FTP Server auf dem du Dateien ablegst und abrufst? Da gibt es natürlich Unterschiede zwischen Lese- und Schreibrechen.

So meinte ich das nicht. Ich meinte die Recht in Android die eine App hat. Ich habe bisher die Berechtigung nur in der Datei Manifest.xml eingetragen. Meine Client-App kann die Daten runterlasen, meine Admin-App kann aber irgendwie keine hochladen. Mittlerweile glaube ich aber, dass der FTP-Server der App aus irgendwelchen Gründen die Verbindung verweigert, wenn sie auf einem realen Handy installiert ist.

Ich habe einen FTP-Server auf dem ich Daten mit meiner Admin-App in einem Ordner ablege. Der Ordner ist so eingerichtet, dass man die darin enthaltenen Dateien dann öffentlich über einen Browser auslesen kann.

Den Upload auf dem Server mache ich mit diesem Code:

Spoiler

package de.mc4735.copa_admin;

import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.json.JSONObject;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Arrays;

public class upload_event extends AsyncTask<String, Void, String> {
Context context;

public upload_event(Context context) {
this.context = context;
}

@Override
protected void onPreExecute() {
}

@Override
protected String doInBackground(String... params) {
String TAG = getClass().getName().toString();
FTPClient con = null;
try
{Log.i(TAG,"2");
con = new FTPClient();
con.connect(„Serveradresse“);
Log.i(TAG,"3");
if (con.login(„Nutzer“, „Passwort“))
{ Log.i("Con","Login erfolgreich");
con.enterLocalPassiveMode(); // important!
con.setFileType(FTP.BINARY_FILE_TYPE);
Log.i(TAG,"4");
FileInputStream in = new FileInputStream("/data/data/de.mc4735.copa_admin/copa/"+ params[0] +".json");

con.storeFile(„../../„ + params[0] +".json", in);
con.logout();
con.disconnect();
}
}
catch (Exception e)
{
e.printStackTrace();
}
Log.i(TAG,"5");

String fertig = "fertig";
return fertig;
}

@Override
protected void onPostExecute(String fertig) {
super.onPostExecute(fertig);
}

@Override
protected void onProgressUpdate(Void... values) {
}
}

Den Abruf der Daten mache ich dann, indem ich über die URL die Daten über readURL einlese. Das mache ich so, weil die Client-App irgendwann mal in den App-Store soll und ich da keine Zugangsdaten drin haben will.

Vom Grundprinzip habe ich es auch so hinbekommen, wie ich es mir vorstelle.

Mein Problem ist, dass es nicht funktioniert die Daten auf dem FTP-Server zu speichern, wenn ich die App auf einem physischen Handy installiere. Wenn ich es auf einem virtuellen Device von Android Studio probiere, dann klappt es genau so, wie ich es gerne haben will.


Antwort
Zitat
bumblebeebee
Beigetreten: 06.06.2006

OK. Mit dem apache ftp client habe ich noch nie gearbeitet, kenne mich da also nicht mit aus.
Wo läuft denn der FTP Server? Ist das ein "richtiger" Server im Netz oder dein lokaler Rechner?

Die Fehlermeldung ist leider nichtssagend. Gibts denn nen Stacktrace, den du posten könntest?
Sonst müsstest du dich mal durch die doInBackground Methode durchdebuggen.

Auch wenn du jetzt schon viel Zeit in den Ansatz mit dem FTP Server gesteckt hast, würde ich dir immernoch raten einen REST Webservice aufzusetzen (also http get und post). Ist wesentlich flexibler und weiterentwickelbar. Vielleicht willst du später mal die Daten in eine Datenbank statt einer Datei speichern...


Antwort
Zitat
swizz
Beigetreten: 02.03.2006

Die Daten liegen auf einem echten Server. Das Webpaket ist Unlimited Plus von 1 und 1.

Das mit dem Stacktrace schaue ich mir später noch mal an, wenn ich wieder zu Hause bin.

Mir ist bewusst, dass ich hier ziemlich rumstümpere. Ich würde es allerdings gerne jetzt so zu Ende bringen, weil ich damit schon viel zu viel Zeit für ein Hobby versenke, aber auch weiß, dass es mir keine Ruhe lässt, bevor ich es nicht halbwegs fertig habe.

Auf lange Sicht, werde ich mir das mit dem Rest Webservice sicher noch mal anschauen.


Antwort
Zitat
swizz
Beigetreten: 02.03.2006

Ich habe meine App jetzt ungefähr so hinbekommen, wie ich sie mir vorgestellt habe. Dabei ist mir Folgendes aufgefallen.

Ich habe in der Manifest.xml die Berechtigung für die Internetnutzung eingetragen.

<uses-permission android:name="android.permission.INTERNET" />

Wenn ich die App jetzt auf meinem Handy installiere, dann kann ich auch aufs Internet zugreifen. Wenn ich mir allerdings in den Einstellungen die App-Info anschaue, dann steht da, dass sie kein Datenvolumen verbraucht und keine Berechtigungen erforderlich sind. Woran liegt das?

Normalerweise geht ja ein Dialog auf, wo man den Berechtigungen einzeln zustimmen muss.


Antwort
Zitat
swizz
Beigetreten: 02.03.2006

Ich habe mich jetzt doch mal mit Google-Firebase auseinandergesetzt um Pushnachrichten verschicken zu können. Ich habe es jetzt auch soweit hinbekommen, dass ich die Nachrichten erfolgreich verschicke.

Ich würde es jetzt gerne noch schaffen, dass ich die Nachrichten über meine Admin-App verschicke.

Hier steht erklärt, wie das geht.

// The topic name can be optionally prefixed with "/topics/".
String topic = "highScores";

// See documentation on defining a message payload.
Message message = Message.builder()
    .putData("score", "850")
    .putData("time", "2:45")
    .setTopic(topic)
    .build();

// Send a message to the devices subscribed to the provided topic.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);

Wenn ich diese Code verwende habe ich das Problem, dass Androidstudio in der Zeile mit "Message.builder()" die Fehlermeldung "Can't resolve method 'builder()'".

Hat jemand eine Idee, woran das liegen könnte? Das ist der Orginalcode von der Googleseite. Im Internet finde ich leider zur Klasse Message.


Antwort
Zitat
Nerrik
Beigetreten: 12.09.2006

Bin eher bei c/c++, aber würde sagen das du auch die entsprechenden Klassen / Pakete zu der "builder funktion" importieren musst siehe https://www.programiz.com/java-programming/packages-import

oder https://beginnersbook.com/2013/03/packages-in-java/

denke du hast da einfach einen import vergessen


Antwort
Zitat
swizz
Beigetreten: 02.03.2006

Danke für die Antwort. Daran lag es glaube ich nicht, da ich es mit allen Paketen versucht habe, die Android dafür vorgeschlagen hat.

Ich weiß nicht mehr genau was ich gemacht habe, aber mittlerweile habe ich es irgendwie anders hinbekommen und bin mit dem Projekt fertig.


Antwort
Zitat
swizz
Beigetreten: 02.03.2006

Original von bumblebeebee
Als Client finde ich Retrofit ganz cool https://square.github.io/retrofit/ oder halt Volley von Google https://developer.android.com/training/volley/

Ich habe mich ein bisschen durch die Anleitung gearbeitet und es geschafft mit Volley Daten von einer BTC-API runter zu laden.

Bisher habe ich es so gemacht, dass ich die kompletten Informationen die da von der API angegeben werden runter geladen habe und mir dann daraus geholt habe, was ich brauche.

Geht es auch irgendwie, dass man schon im Request angeben kann, welchen Teil man haben möchte? Bisher habe ich das leider noch nicht rausgefunden. Eigentlich muss es ja gehen, weil es sonst bei größeren Datenmengen völlig ineffizient wäre.

Kann ich mit Volley auch APIs abfragen, die einen Key und einen Secretkey haben? Zum Beispiel wenn ich bei Bitstamp eine API einrichte?


Antwort
Zitat
flowIIpoker
Beigetreten: 14.02.2007

dein request ist doch nicht interpretierbar oder versteh ich da was falsch


Antwort
Zitat
swizz
Beigetreten: 02.03.2006
    button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Instantiate the RequestQueue.

                Context context = getApplicationContext();
                RequestQueue queue = Volley.newRequestQueue(context);
                String url =" https://blockexplorer.com/api/addr/"; 
                String wallet[] =tv.getText().toString().split(":");
                // Request a string response from the provided URL.
                JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
                        (Request.Method.GET, url+wallet[1], null, new Response.Listener<JSONObject>() {

                            @Override
                            public void onResponse(JSONObject response) {
                                try {
                                    tv2.setText("Adress: " + response.get("addrStr").toString());
                                    tv3.setText("Adress: " + response.get("balance").toString());
                                    tv4.setText("Adress: " + response.get("balanceSat").toString());
                                    tv5.setText("Adress: " + response.get("totalSent").toString());
                                    tv6.setText("Adress: " + response.getJSONArray("transactions").get(1).toString());
                                } catch (JSONException e) {
                                    e.printStackTrace();
                                    tv2.setText("Error1:");
                                }
                            }
                        }, new Response.ErrorListener() {

                            @Override
                            public void onErrorResponse(VolleyError error) {
                                tv2.setText("Error2:");

                            }
                        });

War vielleicht etwas ungenau formuliert.

So wie da sieht mein Codeschnipsel aus, mit dem ich den Request mache.

Ich lade da ja alles was die API anbietet in ein Json-Objekt und hole mir da dann die einzelnen Werte aus diesem Objekt raus.

Eigentlich wäre es doch viel sinnvoller, dass ich irgendwie ins Request schreibe was genau ich brauche, oder?

Wenn ich jetzt zum Beispiel nur die Balance haben will, dann macht es doch eigentlich wenig Sinn, dass ich sämtliche Daten runterlasse. Dann wäre es doch gut, wenn ich irgendwie "GetBalance" ins Request schreiben könnte, oder?


Antwort
Zitat
swizz
Beigetreten: 02.03.2006

Noch mal eine Frage. Ich erstelle Arbeitsblätter häufig mit Latex und TIKZ und habe mir da mittlerweile relativ viele Aufgabenformate erstellt. Ich spiele mit dem Gedanken, da eine einfache Lernapp draus zu machen.

Gibt es bei der Erstellung von Android die Möglichkeit TIKZ zum zeichnen zu verwenden bzw. gibt es irgendwas, was eine ähnliche Funktion erfüllt?


Antwort
Zitat