Datenaustausch zwischen zwei Activities

  • Antworten:37
patrickk83
  • Forum-Beiträge: 93

06.04.2020, 19:14:21 via Website

Hallo Leute!

Ich habe eine Test-App mit Hilfe eines Tutorials in Android Studio erstellt, mit der die aktuellen GPS-Daten abgefragt und ausgegeben werden. Soweit so gut. Diese Daten würde ich nun gerne umwandeln. Für das Umwandeln habe ich ein fertiges Java-Programm gefunden welches genau die erforderlichen Berechnungen durchführt. Den Java-Code hätte ich gerne als eigene Activity wobei dann die Werte "lat" und "lon" in der MainActivity an diese Activity mit dem Java-Code übergeben werden sollen. Dort sollen die beiden Werte für die Umwandlung in den "Maidenhead Locator" verwendet und anschließend dieser Wert wieder an die MainActivity übergeben werden.
Bei meiner lang zurückliegenden C++-Ausbildung war leider kurz nach dem Start mit OOP Schluss und jetzt blicke ich nicht mehr ganz durch.
Was mich auch noch etwas verwirrt, sind die beiden Methoden mit gleichem Namen in der "CoordtoLoc-Klasse".
Vielleicht kann mir ja hier jemand bei diesem kleinen Problem helfen.

MainActivity:

public class MainActivity extends AppCompatActivity{

Button btnGetLoc;

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

    btnGetLoc = (Button) findViewById(R.id.btnGetLoc);
    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 123);

    btnGetLoc.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            GPStracker g = new GPStracker(getApplicationContext());
            Location l = g.getLocation();

            if(l != null){
                double lat = l.getLatitude();
                double lon = l.getLongitude();
                Toast.makeText(getApplicationContext(), "LAT: "+lat+ "\n LON: "+lon, Toast.LENGTH_LONG).show();
            }
        }
    });
}

}

GPS-Activity:

public class GPStracker implements LocationListener {

Context context;

public Location getLocation(){

    if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        Toast.makeText(context, "Permission denied", Toast.LENGTH_SHORT).show();
        return null;
    }
    LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    boolean isGPSEnabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);

    if(isGPSEnabled){
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 6000, 10, this);
        Location l = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        return l;
    }
    else {
        Toast.makeText(context, "Please enable GPS", Toast.LENGTH_LONG).show();
    }
    return null;
}

public GPStracker(Context c){
context = c;
}

}

Hier der Java Code:

public class Location {

String latlon;
String maidenhead;

public Location(String p1, String p2) {
float lat = -100.0f;
float lon = 0.0f;
try {
lat = Float.parseFloat(p1);
lon = Float.parseFloat(p2);

  maidenhead = latLonToGridSquare(lat, lon);
} catch (Exception e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
}

}

public Location(float lat, float lon) {
try {
maidenhead = latLonToGridSquare(lat, lon);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

private void gridSquareToLatLon(String grid) {

}

public String latLonToGridSquare(float lat, float lon) throws Exception{
float adjLat,adjLon;
char GLat,GLon;
String nLat,nLon;
char gLat,gLon;
float rLat,rLon;
String U = "ABCDEFGHIJKLMNOPQRSTUVWX";
String L = U.toLowerCase();

// support Chris Veness 2002-2012 LatLon library and
// other objects with lat/lon properties
// properties could be getter functions, numbers, or strings


if (Float.isNaN(lat)) throw new Exception("lat is NaN");
if (Float.isNaN(lon)) throw new Exception("lon is NaN");
if (Math.abs(lat) == 90.0) throw new Exception("grid squares invalid at N/S poles");
if (Math.abs(lat) > 90) throw new Exception("invalid latitude: "+lat);
if (Math.abs(lon) > 180) throw new Exception("invalid longitude: "+lon);


adjLat = lat + 90;
adjLon = lon + 180;
GLat = U.charAt((int) (adjLat/10));
GLon = U.charAt((int) (adjLon/20));
nLat = ""+(int)(adjLat % 10);
nLon = ""+(int)((adjLon/2) % 10);
rLat = (adjLat - (int)(adjLat)) * 60;
rLon = (adjLon - 2*(int)(adjLon/2)) *60;
gLat = L.charAt((int)(rLat/2.5));
gLon = L.charAt((int)(rLon/5));
String locator = ""+GLon+GLat+nLon+nLat+gLon+gLat;
return locator;

}
}

Antworten
swa00
  • Forum-Beiträge: 3.704

06.04.2020, 19:48:21 via Website

Hallo,

ich habe mir erlaubt , deinen Code quer zu lesen.

Ehrlich gesagt, ist dieser in der Struktur grausam und macht es wirklich schwer.
herauszufinden , was wo genau passiert :-)
Der hat auch nichts mir sauberen OOP zu tun und die Permissions-Abfragen sind
da, wo sie eigentlich auch nicht hin gehören :-)

Ergo : Für Android ein wenig ungeeignet und wenig klassenorientiert ausgelagert.

Deshalb beschränke ich mich auf deinen Topic :

Datenaustausch zwischen zwei Activities

Dies bewerkstelligt man mit Intents, Listener, oder Broadcasts

Liebe Grüße - Stefan
[ App - Entwicklung ]

patrickk83

Antworten
patrickk83
  • Forum-Beiträge: 93

06.04.2020, 20:00:19 via Website

Das habe ich mir beinahe gedacht :-)

Daher ist es für mich auch so schwierig das Ganze zu verstehen. Ich habe immer auf klar verständliche Variablendeklarationen gesetzt und auch die Struktur halbwegs durchdacht und sauber gehalten.

Antworten
Jokel
  • Forum-Beiträge: 1.527

06.04.2020, 20:08:37 via Website

Hallo auch ich habe mir erlaubt deinen Code zu überfliegen.
Alles richtig was bis jetzt gesagt wurde.

Das Was du als GPS Activity bezeichnest ist keine Aptivity sondern eine Klasse die ein Interfase importiert aber nicht von Activity erbt.

Mit einer Avtivity hat das nichts zu tun.

In der Activity erstellst du von jeder Klasse eine Instanz und greifst darauf zu.

Ein Intent wird dir hier nicht viel bringen denn du hast alles in der Activity.
Du hast keine zwei Activitys Datenaustausch mit Intent ist somit nicht sinnvoll.

— geändert am 06.04.2020, 20:09:29

swa00patrickk83

Antworten
patrickk83
  • Forum-Beiträge: 93

06.04.2020, 20:13:35 via Website

Wie würde eine sinvolle Abänderung aussehen?

Antworten
swa00
  • Forum-Beiträge: 3.704

06.04.2020, 20:32:54 via Website

Jörg (Jokel), mach du bitte weiter - muss noch ein projekt fertig bekommen - thx

Liebe Grüße - Stefan
[ App - Entwicklung ]

Antworten
Jokel
  • Forum-Beiträge: 1.527

06.04.2020, 20:48:06 via Website

In der MainActivty willst du auf zwei Methoden zugreifen die es nicht gibt.

double lat = l.getLatitude();
double lon = l.getLongitude();

"L" soll ein Objekt von Location sein nur wo hast du davon eine Instanz erstellt? Auch die beiden Methoden gibt es nicht in der Kasse.
Du willst in der GPS Klasse ein Objekt von Location in der Methode „getLocation()“ zurück geben nur hast du gar keins.

Ich glaube es ist besser du suchst dir ein besseres Tutorial in dem gezeigt wird wie du das mit den Lister für den LocationManager machst.

— geändert am 06.04.2020, 21:10:51

patrickk83

Antworten
Jokel
  • Forum-Beiträge: 1.527

06.04.2020, 20:54:33 via Website

Was mich auch noch etwas verwirrt, sind die beiden Methoden mit gleichem Namen in der "CoordtoLoc-Klasse".

Das sind zwei Konstruktor mit unterschiedlichen Parameter.
Eine überladene Methode. Nennt man das bei OOP .
Ein Konstruktor wird beim Instanziieren der Kasse aufgerufen der wird bei dir gar nicht benutzt. Hast somit gar keine Instanz Objekt davon.

https://www.androdocs.com/java/getting-current-location-latitude-longitude-in-android-using-java.html

— geändert am 06.04.2020, 21:09:21

patrickk83

Antworten
patrickk83
  • Forum-Beiträge: 93

06.04.2020, 21:12:16 via Website

Es wird langsam aber sicher etwas heller... Habe eine gute Seite gefunden auf der (für mich zumindest) verständlich das Grundlegende vermittelt wird.

Kannst du ein Tut empfehlen? Auf yt weiss man leider vorher nie ob das Gezeigte auch brauchbar/korrekt ist. Habe wegen dem GPS ohnehin mehrere Tutorials durch bzw. nachgemacht...

Das Komische ist nur, dass meine aktuellen Koordinaten trotzdem korrekt mit der Toast-Message angezeigt werden :-)

Antworten
Jokel
  • Forum-Beiträge: 1.527

06.04.2020, 21:23:22 via Website

nein habe ich jetz leider nicht bei der Hand.

wenn der Toast richtig kommt. hasst du uns den gesamten Code gegeben?

und wenn es geht wo ist den eigentlich dein Problem.

Ps.
Das der Toast geht ist auch nicht so verwunderlich denn „Location“ ist eine Klasse von Android. Da du diese bestimmt bei dem Imports hast wird auch die benutzt. Und nicht deine.
Und da gibt es auch die beiden Methoden.

https://developer.android.com/reference/android/location/Location

und der Manager gibt dir auch das richtige Objekt zurück.
Habe es leider auch erst jetzt gesehen. Sorry

Location l = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);

— geändert am 06.04.2020, 21:36:56

Antworten
patrickk83
  • Forum-Beiträge: 93

06.04.2020, 21:28:41 via Website

Es ist der ganze Code, ja (ohne den imports natürlich).
Naja, das Problem war/ist das grundlegende Verständnis. Jetzt habe ich in der Zwischenzeit mal wenigstens verstanden was der Unterschied zwischen Konstruktor und Methode ist :-) Ich werde mal den Beitrag aus deinem Link durcharbeiten und mich dann wieder kurz melden wenn ich darf.

Antworten
Jokel
  • Forum-Beiträge: 1.527

06.04.2020, 21:37:35 via Website

Ja Ok

Antworten
patrickk83
  • Forum-Beiträge: 93

07.04.2020, 10:00:00 via Website

Guten Morgen,

habe jetzt einiges gelesen. Also die App für die "Current location" funktioniert mal. Jetzt möchte ich diese mit einem Button erweitern der bei click die Werte der Variablen "lat" und "lon" an die Methode CoordToLoc(String p1, String p2) übergibt. Diese sollen dort dann umgewandelt werden und anschlileßend wieder in einem Textview ausgegeben werden.

MainActivity.java:
public class MainActivity extends AppCompatActivity {

int PERMISSION_ID = 44;
FusedLocationProviderClient mFusedLocationClient;
TextView latTextView, lonTextView;

Button btGetLocator;

private double lat;
private double lon;

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

    btGetLocator = (Button)findViewById(R.id.btnGetLoc);

    latTextView = findViewById(R.id.latTextView);
    lonTextView = findViewById(R.id.lonTextView);
    mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

    getLastLocation();

    CoortToLoc objCoord = new CoordToLoc(double, double);

    //On Button click
    btGetLocator.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            objCoord.CoordToLoc(lat, lon);
            Toast.makeText(getApplicationContext(), "LAT: "+lat+ "\n LON: "+lon, Toast.LENGTH_LONG).show();
        }
    });
}

@SuppressLint("MissingPermission")
private void getLastLocation() {
    if (checkPermissions()) {
        if (isLocationEnabled()) {
            mFusedLocationClient.getLastLocation().addOnCompleteListener(
                    new OnCompleteListener<Location>() {
                        @Override
                        public void onComplete(@NonNull Task<Location> task) {
                            Location location = task.getResult();
                            if (location == null) {
                                requestNewLocationData();
                            } else {
                                lat = location.getLatitude();
                                lon = location.getLongitude();
                                //latTextView.setText(location.getLatitude() + "");
                                //lonTextView.setText(location.getLongitude() + "");
                                latTextView.setText("Latitude: "+lat);
                                lonTextView.setText("Longitude: "+lon);
                            }
                        }
                    }
            );
        } else {
            Toast.makeText(this, "Turn on location", Toast.LENGTH_LONG).show();
            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            startActivity(intent);
        }
    } else {
        requestPermissions();
    }
}


@SuppressLint("MissingPermission")
private void requestNewLocationData() {

    LocationRequest mLocationRequest = new LocationRequest();
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequest.setInterval(0);
    mLocationRequest.setFastestInterval(0);
    mLocationRequest.setNumUpdates(1);

    mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
    mFusedLocationClient.requestLocationUpdates(
            mLocationRequest, mLocationCallback,
            Looper.myLooper()
    );

}

private LocationCallback mLocationCallback = new LocationCallback() {
    @Override
    public void onLocationResult(LocationResult locationResult) {
        Location mLastLocation = locationResult.getLastLocation();
        latTextView.setText(mLastLocation.getLatitude() + "");
        lonTextView.setText(mLastLocation.getLongitude() + "");
    }
};

private boolean checkPermissions() {
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
        return true;
    }
    return false;
}

private void requestPermissions() {
    ActivityCompat.requestPermissions(
            this,
            new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},
            PERMISSION_ID
    );
}

private boolean isLocationEnabled() {
    LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(
            LocationManager.NETWORK_PROVIDER
    );
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == PERMISSION_ID) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            getLastLocation();
        }
    }
}

@Override
public void onResume() {
    super.onResume();
    if (checkPermissions()) {
        getLastLocation();
    }

}

}

CoordToLoc.java:

package com.example.gpstest;

public class CoordToLoc extends MainActivity{

    String maidenhead;

    public CoordToLoc(String p1, String p2) {

        float lat = -100.0f;
        float lon = 0.0f;

        try {
            lat = Float.parseFloat(p1);
            lon = Float.parseFloat(p2);

            maidenhead = latLonToGridSquare(lat, lon);
        }
        catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public CoordToLoc(float lat, float lon) {
        try {
            maidenhead = latLonToGridSquare(lat, lon);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    /*
    private void gridSquareToLatLon(String grid) {

    }*/

    public String latLonToGridSquare(float lat, float lon) throws Exception{
        float adjLat,adjLon;
        char GLat,GLon;
        String nLat,nLon;
        char gLat,gLon;
        float rLat,rLon;
        String U = "ABCDEFGHIJKLMNOPQRSTUVWX";
        String L = U.toLowerCase();

        // support Chris Veness 2002-2012 LatLon library and
        // other objects with lat/lon properties
        // properties could be getter functions, numbers, or strings


        if (Float.isNaN(lat)) throw new Exception("lat is NaN");
        if (Float.isNaN(lon)) throw new Exception("lon is NaN");
        if (Math.abs(lat) == 90.0) throw new Exception("grid squares invalid at N/S poles");
        if (Math.abs(lat) > 90) throw new Exception("invalid latitude: "+lat);
        if (Math.abs(lon) > 180) throw new Exception("invalid longitude: "+lon);


        adjLat = lat + 90;
        adjLon = lon + 180;
        GLat = U.charAt((int) (adjLat/10));
        GLon = U.charAt((int) (adjLon/20));
        nLat = ""+(int)(adjLat % 10);
        nLon = ""+(int)((adjLon/2) % 10);
        rLat = (adjLat - (int)(adjLat)) * 60;
        rLon = (adjLon - 2*(int)(adjLon/2)) *60;
        gLat = L.charAt((int)(rLat/2.5));
        gLon = L.charAt((int)(rLon/5));
        String locator = ""+GLon+GLat+nLon+nLat+gLon+gLat;
        return locator;
    }

}

Wenn ich das jetzt richtig verstehe so ist in der CoordToLoc.java eine Klasse mit Namen CoordToLoc enthalten. In dieser Klasse befinden sich zwei Konstruktoren. Benötigen würde ich in meinem Fall den zweiten:

public CoordToLoc(float lat, float lon) {
        try {
            maidenhead = latLonToGridSquare(lat, lon);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

Ich müsste also die beiden Werte für lat und lon in der MainActivity an diesen Konstruktor übergeben.
Benötige ich da jetzt ein Intent? Wenn alles in der MainActivity stehen würde so könnte ich doch ein Objekt der Klasse CoortToLoc erzeugen und dann den Konstruktor inkl. übergebenen Werten aufrufen:

CoordToLoc objCTL = new CoordToLoc(float, float); //vor onCreate()
//Button-Click Listener:

objCTL.CoordToLoc(lat, lon);
//Ausgabe mit einem Toast
Toast ---> Der locator den ich benötige sollte in der variable "maidenhead" gespeichert sein?!

Bitte um weitere Hilfe

Antworten
Ludy
  • Admin
  • Forum-Beiträge: 7.957

07.04.2020, 10:43:35 via App

Hallo Patrick,

herzlich willkommen hier im Forum (*)

wegen der permission Verwaltung kannst du hier in meinem Projekt schauen: https://github.com/Ludy87/AndroidPIT/tree/master/LocalLocation

Gruß Ludy (App Entwickler)

Mein Beitrag hat dir geholfen? Lass doch ein "Danke" da.☺

☕ Buy Me A Coffee ☕

Lebensmittelwarnung-App

✨Meine Wunschliste✨

📲Telegram NextPit News📲

patrickk83

Antworten
patrickk83
  • Forum-Beiträge: 93

07.04.2020, 10:50:09 via Website

Die Abfragen mit den permissions habe ich halbwegs verstanden. Was ich nicht richtig verstehe ist der Datenaustausch zwischen MainActivity und dem Code in der Datei CoordToLoc.java. Letzteres ist ja keine Activity sondern nur eine Klasse mit einer Methode mit mathematischen Berechnungen. Einerseits möchte ich an diese Methode zwei Werte übergeben und andererseits möchte ich das Ergebnis der Berechnung in der MainActivity weiterverwenden (in diesem Fall in einem TextView).

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

07.04.2020, 12:05:49 via Website

Eine Klasse liefert dir das Werkzeug für z.b. Berechnungen.

Und wenn du dich ein wenig über Objektorientierung und Klassen etc. eingelesen hast, wüsstest du folgendes:

  • Eine Klasse ist "Vorlage" für ein Objekt und enthält Code für Berechnugen, Ausgaben etc.
  • Ein Objekt ist eine Instanz der Klasse, also eine Entität in der dann auch Daten gehalten werden können
  • I.d.r können belibig viele Objekte erstellt werden.
  • Eingaben werden über Parameter der Methoden übergeben
  • Rückgabewerte sind über Methoden definierbar und auch weiter benutzbar

Also Parameter für Methodeninputs hast du ja schon. Ausgaben gehen so:

public ausgabetyp (z.b. String, int,...) Methondenname(Parameter...){
//methodencode
return myValue; //Berechneten Wert zurückgeben, typ muss dem definieren Rückgabetyp entsprechen
}
Genauer schaust du dir aber bitte nach: https://www.tutorialspoint.com/java/java_object_classes.htm
Wir können dir hier nicht die kompletten Java Grunladen vermitteln sondern nur konkrete Fragen beantworten

LG Pascal //It's not a bug, it's a feature. :) ;)

Jokel

Antworten
patrickk83
  • Forum-Beiträge: 93

07.04.2020, 12:31:52 via Website

Das verstehe ich soweit. Ich weiss aber nicht wie ich nun einen Wert aus dem konkreten Beispiel an den Konstruktor übergebe. Nehmen wir mal die Variablen "lat" und "lon" vom typ double aus der MainActivity. Diese möchte ich an den Konstruktor CoordToLoc der zwei Werte erwartet, übergeben. Wie muss ich das in der MainActivity korrekt eingeben?
Meine Vorgehensweise wäre:
- Objekt der Klasse CoordToLoc vor der onCreate() erstellen: CoordToLoc objCOL = new CoordtoLoc (float, float);
- innerhalb des onClickListeners des Buttons: objCOL.CoordToLoc(float lat, float lon);
- Berechnung in einem TextView in der MainActivity anzeigen: locTextView.setText("Locator: ",+objCOL.maidenhead);

CoordToLoc objCOL = new CoordtoLoc (float, float); bringt allerdings ein ".class expected"

— geändert am 07.04.2020, 12:50:34

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

07.04.2020, 12:52:24 via Website

CoordToLoc objCOL = new CoordtoLoc (float, float);

Nein, float ist ein Datentyp, als Parameter muss aber eine Variable rein.

Also eher:

CoordToLoc objCOL = new CoordtoLoc (lat, lon); //Weil lat/lon in MainActitivy definiert 

//wenn du es richtig machst brauchst du hier keine Parameter mehr, weil schon im Konstruktor

objCOL.CoordToLoc(); 

Jetzt brauchst du noch einen Rückgabewert als String, den musst du in der Klasse zwischenspeichern, da die Location per Listener rein kommt.

Was ist dann die konkrete Frage?
Wie ein Rückgabewert funktioniert weißt du, dann versuch es mal, wenn du nicht weiter kommst, sag bescheid.

LG Pascal //It's not a bug, it's a feature. :) ;)

patrickk83

Antworten
Jokel
  • Forum-Beiträge: 1.527

07.04.2020, 15:13:53 via Website

Objekt der Klasse CoordToLoc vor der onCreate() erstellen: CoordToLoc objCOL = new CoordtoLoc (float, float);

nein die Objekt Variable im Klassen Rumpf.
das etstelle des Objekte mit new in der onCrate.
ein Konstruktor hat keinen Rückgabe wert das ist die Intanz.

Eine Rückgabe über eine Methode getter, setter die du über die Instanz in der main aufrufst.
Wenn du in dem Listner ein neues Objekt erstellst ist das ein anderes als da was du in der onCreate erstellt hast.

mit dem "new" wird immer der Konstruktor aufgerufen und immer ein neues Objekt erstelt das eine weiß von dem anderen nichts.
das geht so nicht .
Erstelle dir getter und setter Methoden in der Kasse um auf Inhalte Member von ausen zuzugreifen.

Pascal P.patrickk83

Antworten
Jokel
  • Forum-Beiträge: 1.527

07.04.2020, 15:49:22 via Website

Hallo habe gerade in deinen letzten Code gesehen das deine zweite Klasse der Versuch ist eine activity zu werden.
Denn du erbst da von mainactivity.
Warum das?
Somit bekommst du auch nicht den context der activity wenn das der Grund dafür sein sollte.

Im allgemeinen macht man das etwas anders. Im Konstruktor übergibt man den context wen der in der Klasse gebraucht wird. Speichert ihn dort in einer klassen Variablen.
Zur Berechnung erstellt man eine Methode in der Klasse der du die Parameter übergibst und ewentuell auch gleich den Rückgabe Wert.
Oder die
Rückgabe in einer anderen Methode.

Das alles im Konstruktor machen zu wollen ist kein schöner Stil. Wirst du so auch nicht gelernt haben.

Was mir bei deinem Code auffällt ist das bestimmt nicht den Unterschied zwischen lokalen und Klassen Variablen weißt.

— geändert am 07.04.2020, 16:04:51

Pascal P.

Antworten
patrickk83
  • Forum-Beiträge: 93

07.04.2020, 21:11:10 via Website

Ich glaube das wird leider nichts... Habe mal meinen letzten Denkansatz als Grafik angehängt. Vielleicht werden meine Denkfehler so ersichtlicher.

image

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

07.04.2020, 21:26:54 via Website

Naja so ganz falsch ist das nicht:

Activity:

String rueckGabeWert= objectCTL.latLonToGridSuare(wertA,wertB); //der rückgabewert der Methode in einen String speichern.

textView.setText("Wert: " + rueckGabeWert);

Das Prinzip in deiner Klasse ist richtig, da könntest du dir entweder im Konstruktor oder beim Methodenaufruf noch parameter sparen, aber funktionieren müsste es.

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
patrickk83
  • Forum-Beiträge: 93

07.04.2020, 21:32:15 via Website

Allerdings will das nicht funktionieren...
Bei String retValue = objCoordToLoc.latLonToGridSquare(fLat, fLon); erhalte ich eine Fehlermeldung:
Unhandled exception: java.lang.Exception (Surround with try/catch)

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

07.04.2020, 21:37:08 via Website

Das liegt jetzt aber wieder daran, dass du in deiner Klasse in latLonToGridSuare 2 float Zahlen addierst.
Aus float + float = float und du willst aber einen String.
Also eher

String locator = String.valueOf(lat) + String.valueOf(lon); //hänge die Lat und Lon als String intereinander

Edit: Es kann ein, dass du über AndroidStudio schon ein Throws zur Methode hinzugefügt hast, das muss dann natürlich weg

Bitte beschäftige doch noch etwas intensiver mit den Java Grundlagen, dann sollte dir in dieser Hinsicht einiges klarer werden.

— geändert am 07.04.2020, 21:40:43

LG Pascal //It's not a bug, it's a feature. :) ;)

Jokel

Antworten
Jokel
  • Forum-Beiträge: 1.527

07.04.2020, 21:40:29 via Website

Hallo
Erstmal bei Android keine Statements im KlassenRumpf.
Definieren der Variablen im Rumpf als Klassenvariablen ja. Zuweisen mit new in der onCreate.

Wie ich sehe benutzt du den default Kostrucktor ohne Parameter. Ist auch richtig denn du hast ja auch schon eine fertige Methode mit Rückgabe String und den zwei Übergabe Parametern.

Die Rufst du einfach mit der eben erstellten Instanz auf und bekommst auch den String als Rückgabewert mehr nicht .
Wo du das machst ist dir überlassen, denn die Instanz ist eine Kassenvariabel die in der gesamten Klasse verfügbar ist.
Die beiden Konstruktoren brauchst du eigentlich nicht.

    public class MainActivity extends AppCompatActivity {
    CoortToLoc objCoord;
    String stText;

protected void onCreate(Bundle savedInstanceState) {

    objCoord = new CoordToLoc();


    // zb im Listner

    st = objCoord.latLonToGridSquare(lat, lon); // parameter als float)

— geändert am 07.04.2020, 21:50:29

Pascal P.

Antworten
Jokel
  • Forum-Beiträge: 1.527

07.04.2020, 21:41:12 via Website

Ok ihr wart schneller als Ich.

Antworten
patrickk83
  • Forum-Beiträge: 93

07.04.2020, 21:52:31 via Website

Dachte mir dass die Konstruktoren nicht nötig sind.

Die Methode beinhaltet tatsächlich ein throws:

public String latLonToGridSquare(float lat, float lon) throws Exception{}

allerdings wird throw dann wieder innerhalb der Methode verwendet:

if (Float.isNaN(lat)) throw new Exception("lat is NaN");
if (Float.isNaN(lon)) throw new Exception("lon is NaN");

Gut, das throws mal gelöscht und die if-Abfragen auskommentiert.

Jetzt kommt noch ein Fehler bei objCoord = new CoordToLoc();das ich nun in der onCreate() habe:

no suitable constructor found for CoordToLoc(no arguments)

— geändert am 07.04.2020, 21:59:03

Antworten
Jokel
  • Forum-Beiträge: 1.527

07.04.2020, 22:03:25 via Website

Wenn der Default Kostrucktor fehlt nicht automatisch erstellt wird dann erstelle ihn selber.

public CoordToLoc() { }

throw new Exception("lat is NaN");

das ist nur eine zusätzlicher Catch den du in der Try/Catch der Main Activity abfragen kannst.
Einen Tray/Catch Block musst du in der übergeordneten Kasse machen da du das angegeben hast.

public String latLonToGridSquare(float lat, float lon) throws Exception{}

wenn nicht müsstest du es in der Klasse machen.

— geändert am 07.04.2020, 22:13:47

Pascal P.patrickk83

Antworten
patrickk83
  • Forum-Beiträge: 93

07.04.2020, 22:10:03 via Website

Boah, vielen Dank. Es läuft jetzt zumindest erstmal. Nur leider mit dem falschen Ergebnis bei der Berechnung :-) Aber das sollte ich irgendwie schaffen.

Wirklich ein TOP-Forum mit TOP-Mitgliedern!! Danke für die Hilfe und die Geduld

JokelPascal P.

Antworten
Jokel
  • Forum-Beiträge: 1.527

07.04.2020, 22:16:09 via Website

Bitte sehr. Gern geschehen.

Pascal P.

Antworten
patrickk83
  • Forum-Beiträge: 93

08.04.2020, 12:26:06 via Website

Entschuldigung nochmal ganz kurz...
Ist es möglich, den Code für Latitude und Longitude (siehe Link von Jokel) in eine eigene .java Datei auszulagern und was wäre da zu beachten?
Würde gerne in der MainActivity und auch in einer zweiten Activity auf die Werte zugreifen.

Danke nochmals,

liebe Grüsse

Antworten
swa00
  • Forum-Beiträge: 3.704

08.04.2020, 13:29:42 via Website

Du kannst jederzeit dir eigene ausgelagerte Klassen erstellen und davon mehrere Instanzen in deinen verschiedenen activities davon initiieren.

Für deine Locationabfrage würde ich das allerdings nicht empfehlen, da dann mehrfach der Listener bearbeitet wird. (Resourcenkiller)

Ich rate Dir dazu, nur eine übergeordnete Instanz für die App als Singleton-Klasse zu deklarieren.
https://medium.com/@kevalpatel2106/how-to-make-the-perfect-singleton-de6b951dfdb0

— geändert am 08.04.2020, 20:08:30

Liebe Grüße - Stefan
[ App - Entwicklung ]

patrickk83Pascal P.Jokel

Antworten
patrickk83
  • Forum-Beiträge: 93

08.04.2020, 21:06:24 via Website

In der getLastLocation() Methode erhalte ich die gewünschten Werte. Allerdings nur innerhalb dieser Methode. Die zwei Variablen habe ich vor der onCreate() angelegt. In der onCreate() erfolgt dann der Aufruf der Methode getLastLocation(). Wenn ich dort ein Toast ausgebe so werden mir meine Werte für Lat und Lon korrekt angezeigt. Wenn ich aber ein Toast in der onCreate() nach dem Aufruf der Methode getLastLocation() anlege, so wird mir nur der Wert 0 für beide angezeigt. Was verstehe ich jetzt wieder falsch?

Beispiel:

public class MainActivity{

double a, b;
onCreate(){
getLastLocation();
Toast(...);

public void getLastLocation(){
    a = location.getLatitude();
    b = location.getLongitude();
    Toast(...);
}

}
}

Dass die Methode keinen Rückgabewert hat ist mir bewusst. Aber warum werden die Variablen wieder auf 0 gesetzt wenn die Methode verlassen wird?

Antworten
Jokel
  • Forum-Beiträge: 1.527

08.04.2020, 21:24:45 via Website

Der toast in der onCrate wird bestimmt vor dem toast in der Methode ausgeführt. In der methote host du die Werte bestimmt in einem listner.

Ist der Code wirklich so eine Methode innerhalb einer Methode? Oder ist das beim kopieren passiert?

Die getLastLocation gehört raus aus der onCreate.

— geändert am 08.04.2020, 21:32:49

Antworten
patrickk83
  • Forum-Beiträge: 93

08.04.2020, 21:27:16 via Website

Ich habe die Toast immer nur einzeln ausgeführt (jeweils den anderen auskommentiert)

Antworten
patrickk83
  • Forum-Beiträge: 93

08.04.2020, 21:40:27 via Website

Hier die Methode:

public void getLastLocation() {
    if (checkPermissions()) {
        if (isLocationEnabled()) {
            mFusedLocationClient.getLastLocation().addOnCompleteListener(
                    new OnCompleteListener<Location>() {
                        @Override
                        public void onComplete(@NonNull Task<Location> task) {
                            Location location = task.getResult();
                            if (location == null) {
                                requestNewLocationData();
                            } else {

                                double lat = location.getLatitude();
                                double lon = location.getLongitude();
                                fLat = (float) lat;
                                fLon = (float) lon;
                                latitude = String.valueOf(lat);
                                longitude = String.valueOf(lon);
                                strLocator=objCoordToLoc.latLonToGridSquare(fLat, fLon);
                                tv_qth_on_main_activity.setText("QTH: "+strLocator);

                                //Toast.makeText(getApplicationContext(),"Latitude: "+fLat+" Longitude: "+fLon,Toast.LENGTH_LONG).show();
                                //latTextView.setText("Latitude: "+lat);
                                //lonTextView.setText("Longitude: "+lon);
                            }
                        }
                    }
            );

Antworten
Jokel
  • Forum-Beiträge: 1.527

08.04.2020, 22:00:16 via Website

Dachte ich mir das du die Werte aus einem listner liest. Der bestimmt erst später die Variablen setzt.
Also der toast in der onCrate wird früher ausgeführt als der in der Methode.

patrickk83

Antworten
Jokel
  • Forum-Beiträge: 1.527

08.04.2020, 22:04:07 via Website

Wenn du es genau wissen willst mache dir einen Button der den toast der onCrate anzeigt. Clicke erst nachdem der toast aus der Methode gekommen ist.

patrickk83

Antworten