App läuft unter Android 12 nicht mehr richtig

  • Antworten:16
  • Bentwortet
Robbiani Renato
  • Forum-Beiträge: 614

26.02.2022, 21:13:17 via Website

Hallo zusammen

Ich habe eine App die läuft auf meinem Testhandy (Samsung e20) mit Android 11 ohne Probleme. Wenn ich die App aber auf meinem Handy (Samsung S10) mit Android 12 laufen lasse, dann geschehen sonderliche Sachen.

Das GPS wird nicht mehr gelesen und wenn ich welche Daten speichere, werden die nicht mehr gefunden.

Da ich bald die Kurve nicht mehr kriege möchte ich nachfragen, ob in der Version 12 irgend was mit den Rechten geändert wurde?

Gruss Renato

Kommentieren
Beste Antwort
Jokel
  • Forum-Beiträge: 1.537

07.03.2022, 13:06:01 via Website

So ganz vollständig erscheint mit die Abfrage der Pernission nicht.
Wo ist die Liste der Manifest Permission?
kein Aufruf der erneuten ab frage wenn die Permission nicht GRANTED ist.
kein Aufruf der onRequestPermissionsResult Methode.
Überschrieben scheint die Methode auch nicht zu sein.

hier ein Beispiel wie es sein sollte.

public class MainActivity extends AppCompatActivity {

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

    private final static int REQUEST_CODE_ASK_PERMISSIONS = 1;

    private static final String[] REQUIRED_SDK_PERMISSIONS = new String[]{
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.CAMERA,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
    };


    protected void checkPermissions() {
        final List<String> missingPermissions = new ArrayList<String>();
        // check all required dynamic permissions
        for (final String permission : REQUIRED_SDK_PERMISSIONS) {
            final int result = ContextCompat.checkSelfPermission(this, permission);
            if (result != PackageManager.PERMISSION_GRANTED) {
                missingPermissions.add(permission);
            }
        }
        if (!missingPermissions.isEmpty()) {
            // request all missing permissions
            final String[] permissions = missingPermissions
                    .toArray(new String[missingPermissions.size()]);
            ActivityCompat.requestPermissions(this, permissions, REQUEST_CODE_ASK_PERMISSIONS);
        } else {
            final int[] grantResults = new int[REQUIRED_SDK_PERMISSIONS.length];
            Arrays.fill(grantResults, PackageManager.PERMISSION_GRANTED);
            onRequestPermissionsResult(REQUEST_CODE_ASK_PERMISSIONS, REQUIRED_SDK_PERMISSIONS,
                    grantResults);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[],
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case REQUEST_CODE_ASK_PERMISSIONS:
                for (int index = permissions.length - 1; index >= 0; --index) {
                    if (grantResults[index] != PackageManager.PERMISSION_GRANTED) {
                        // exit the app if one permission is not granted
                        Toast.makeText(this, "Required permission '" + permissions[index]
                                + "' not granted, exiting", Toast.LENGTH_LONG).show();
                        finish();
                        return;
                    }
                }
                // all permissions were granted
                initialize();        //new onCreate
                break;
        }
    }

    private void initialize() {
        int x = 1;
    }

}
Hilfreich?
Robbiani Renato
Kommentieren
Jokel
  • Forum-Beiträge: 1.537

27.02.2022, 18:01:20 via Website

Mit was greifst du denn auf Datein zu?

Welchen Speicherbereich willst du nutzen?

Zugriff auf das gesamte Filesystem geht nur noch mit SAF

https://developer.android.com/guide/topics/providers/document-provider

Die klaschischen Datei Pfade kannst du fast vergessen.

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 614

27.02.2022, 20:05:35 via Website

Ciao Jokel

Danke für die Hilfe.
Ich speichere keine Dateien. Ich mache es wie folgt.

Speichern:

private void schreibe_daten(double breit, double lang, String str_ort){

// SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(ctx);
SharedPreferences pref = getSharedPreferences(APP, 0);
SharedPreferences.Editor edit = pref.edit();
edit.putFloat("BREIT", (float) breit);
edit.putFloat("LANG", (float) lang);
edit.putString("ORT", str_ort);
if(edit.commit()){
Log.v("sun_app", "Optionen wurden gespeichert");
}else {
Log.e("sun_app", "Optionen konnten nicht gespeichert werden");
}
}

Lesen :

 private void lese_daten(){
    float breit, lang;
    String ort_name;
    SharedPreferences pref = getSharedPreferences(APP, 0);
        breit = pref.getFloat("BREIT", 0);
        setD_breite((double) breit);
        lang = pref.getFloat("LANG", 0);
        setD_laenge((double) lang);
        ort_name = pref.getString("ORT", "- ? -");
        setN_zone(Astronomy.zeitzone(lang));
        setStr_ort(ort_name);

// }
}

und die Optionen lesen

private void lese_option_daten(){
    SharedPreferences optpref = PreferenceManager.getDefaultSharedPreferences(ctx);
    if ( optpref.contains("key_anzeige") ){
        String str_anzeige = optpref.getString("key_anzeige", "grd");
        switch (str_anzeige){
            case "grd" : n_anzeige = 0;
                break;
            case "grdmin" : n_anzeige = 1;
                break;
            case "grdminsek" : n_anzeige = 2;
        }
        b_findpos = optpref.getBoolean("key_findpos", true);
        b_gps = optpref.getBoolean("key_gps", false);
        n_distanz = optpref.getInt("key_distanz", 500);
        b_sommer = optpref.getBoolean("key_sommer", false);
    }
}

Gruss Renato

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 614

27.02.2022, 21:03:13 via Website

Ciao Jokel

Ich habe mal den Debugger bemüht. Das Problem liegt an einem anderen Ort. Der Toast wird auf meinem Handy (android 12) einfach nicht angezeigt.

 private void initial(){
    //Gespeicherte Position lesen damit sofort was angezeigt wird
    lese_daten();
    lese_option_daten();
    Double b_breit = getD_breite();
    Double b_lang = getD_laenge();
    String str_ortname = getStr_ort();

// setN_zone(Astronomy.zeitzone(b_lang));
zeig_pos();
//Position ermitteln nur wenn gewünscht Optionen
if( b_findpos ) {
str_starttext += getResources().getString(R.string.lbl_possuch);
position();
}
//Parameter übergeben
String str_breit, str_lang;
str_breit = Double.toString(b_breit);
str_lang = Double.toString(b_lang);
Bundle daten = new Bundle();
daten.putString("BREITE", str_breit);
daten.putString("LÄNGE", str_lang);
daten.putString("DATUM", str_datum);
daten.putString("ZONE", Integer.toString(n_zone));
//Anzeigen was gemacht wird
Toast.makeText( ctx, str_starttext, Toast.LENGTH_SHORT).show();
fragment.setArguments(daten);
}

Aber wenn ich die App in der Entwicklungsumgebung starte, dann wird der Toast angezeigt. Sobald ich die App vom Handy starte, wird der Toast nicht mehr angezeigt. Ich verstehe das nicht mehr.
Vielleicht hast du eine Idee woran das liegen könnte?

Gruss Renato

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.537

01.03.2022, 10:06:42 via Website

Toast.makeText( ctx, str_starttext, Toast.LENGTH_SHORT).show();

Welcher Context ist "ctx" ?
Zeige das.

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 614

02.03.2022, 19:51:01 via Website

Ciao Jokel

Herzlichen Dank für deine Hilfe.
Also der Context ist der folgende :

ctx = getApplicationContext();

Ich habe es auch schon mit "this" probiert. Derselbe Effekt.
Aber ich denke das Problem liegt an einem andern Ort. Ich denke, dass die Methode "initial" nicht durchlaufen wird. Wenn ich die App ein erstes mal starte, dann wird der Toast angezeigt. Bei jedem weiteren Aufruf kommt der Toast nicht. Wenn ich die App aus den offenen Apps entferne und es wieder starte, dann wird der Toast wieder einmal gezeigt. Ich habe die Methode mit dem Erteilen der Rechte gekoppelt. Offensichtilch verliert die App beim Schliessen die Rechte nicht.

Gruss Renato

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.537

03.03.2022, 09:35:46 via Website

"initial" ist doch wie der Name schon sagt bestimmt eine Methode die zum initialisieren da ist. Deshalb hast du sie doch wohl auch so genannt. Und soll bestimmt nur einmal durchlaufen werden.
Aber das müsstest du selber wissen.

Tipp baue doch ein paar „Logs“ ein mit denen du schauen kannst in welcher reihen folge dein Methoden durlaufen werden. Die du in der Logcat beobachten kannst. wenn dein Handy mit Usb verbunden ist kannst du die Logdaten auch im Studio in der Logcat beobachten.

Du bist doch in einem Fragment oder? Ob da getApplicationContext() der richtige ist mag ich etwas zu bezweifeln.
Wie mit was startest du dein Fragment?

Für einen Tost brauchst du den Kontext der Activity in der du das Fragment startest. Übergebe doch den Kontext der Activity an das Fragment mit dem Konstruktor und speichere ihn in einer Instanzvariablen.
Denn getActivty() ist ja seit Api 28 deaktiviert.
Mit Androidx sollte es aber wieder möglich sein den zu benutzen, im Fragment. Ich hoffe du nutzt auch androidx und nicht mehr die alten Support Libs.

— geändert am 03.03.2022, 09:38:20

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.537

03.03.2022, 14:46:09 via Website

Ich habe es auch schon mit "this" probiert. Derselbe Effekt.

THIS zeigt ja immer auf das Objekt in dem du gerade bist.
Du bist in einem Fragment und vielleicht auch noch in einem Listener anonyme Klasse.
Da ist this immer falsch.

Wie ich schon sagte brauchst du den Context der Activity den du dir in der activity mit this auch holen kannst und an das Fragment weiter geben kannst.

Benutze ein log und schaue ob und wann du in die Methode kommst.

Ein prüfen mit Toast ist oft Fehler trächtig.

Hilfreich?
Pascal P.
Kommentieren
Jokel
  • Forum-Beiträge: 1.537

03.03.2022, 20:01:15 via Website

Mit Androidx in eimen Fragment müsstest du dir den Context auch so holen können.

Toast.makeText(getActivity(), “hallo”, Toast.LENGTH_SHORT).show();

Toast.makeText(getActivity().getApplicationContext(), “hallo”, Toast.LENGTH_SHORT).show();
Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 614

04.03.2022, 18:32:30 via Website

Ciao Jokel

Ich bevinde mich nicht einem Fragment. Ich habe drei Fragmente um ein Tabpage zu generieren.
Ich frage dir Rechte nach. Wenn die in Ordnung sind dann führe ich die Methode Initial aus. Ich denkte, dass die einfach nur einmal ausgeführt wird. Aber ich werde das mal mit dem Log nachprüfen.

Herzlichen Dank allen die mir geholfen haben.

Gruss Renato

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 614

04.03.2022, 18:34:35 via Website

Habe noch gleich was gesehen.
Ich verwende "androix". Ich will ja meine Apps immer auf dem neusten Stand halten.

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.537

04.03.2022, 20:31:08 via Website

Ok dann zeige mal wo du deine Initial Methode aufrufst.

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 614

05.03.2022, 20:37:03 via Website

Ciao Jokel

Innerhalb von onCreate mache ich folgendes :

       //prüft ob OS Version > 6 ist, denn vorher kann nicht die Rechte geprüft werden
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        //prüfen ob Rechte vorhanden sind um auf die GPS Daten zu zugreifen
        if (pruefrechte()) {
            str_starttext = getResources().getString(R.string.lbl_start_neu);
            initial();

        } else {
        }
    }else{
        str_starttext = getResources().getString(R.string.lbl_start_alt);
        initial();
    }

Aber bin mir nicht so sicher, ob dies weiterhilft. Das ist eines von meinen ersten Projekten und mittlerweile ein zimmliches Chaos im Code.

Was mir mehr Kopfzerbrechen macht ist folgenden Code

    private void position(){
    //    private DatePickerDialog.OnDateSetListener listener;
    LocationManager posmanager = (LocationManager) getSystemService(LOCATION_SERVICE);
    LocationListener horcher = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            Double lang = location.getLongitude();
            Double breit = location.getLatitude();
            Double hoch = (double) 0;
            if (location.hasAltitude())
                hoch = location.getAltitude() - location.getAccuracy();

            setD_breite(breit);
            setD_laenge(lang);
            setN_zone(Astronomy.zeitzone(lang));
            zeig_pos();
            txt_hoch.setText(String.format(FORMAT_FLOAT, hoch));
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onProviderDisabled(String provider) {

        }
    };
    //Position wird gesucht
    if( b_gps ) { //genau
        str_starttext += getResources().getString(R.string.lbl_genau);
        posmanager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, n_distanz, (LocationListener) horcher);
    }else { //ungenau
        str_starttext += getResources().getString(R.string.lbl_ungenau);
        posmanager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, n_distanz, (LocationListener) horcher);
    }
}

Die Zeilen sind rot unterlegt und melden den Fehler

 posmanager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, n_distanz, (LocationListener) horcher);

und

posmanager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, n_distanz, (LocationListener) horcher);

ergibt die Warnung

Call requires permission which may be rejected by user: code should explicitly check to see if permission is available (with checkPermission) or explicitly handle a potential SecurityException

Was könnte man dagegen machen?

Gruss Renato

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.537

06.03.2022, 16:24:12 via Website

Hallo die Fehlermeldung sagt dir doch das die Permission nicht passen.

Wie sieht dein Manifest aus und wie erfragst du sie vom User. Zeige.

Das ist wohl in der pruefrechte() Methode?

Wenn es rot unterstrichen ist dann wirst du die Permission garnicht im Manifest haben.

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 614

06.03.2022, 18:26:58 via Website

Ciao Jokel

Ich hoffe schon, dass ich die Rechte richtig abfrage.

Manifest:

<?xml version="1.0" encoding="utf-8"?>

xmlns:tools="http://schemas.android.com/tools"
package="ch.robbisoft.sun_app">

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA"/>

<uses-feature android:name="android.hardware.location.gps" />
<uses-feature android:name="android.hardware.location.network" />
<uses-feature android:name="android.hardware.camera"
    android:required="true" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme.NoActionBar"
    tools:ignore="GoogleAppIndexingWarning">
    <activity android:name=".BildSonne"/>
    <activity android:name=".LoadActivity" />
    <activity android:name=".SaveActivity" />
    <activity android:name=".SettingsActivity" />
    <activity android:name=".Main"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

und hier ist die Methode mit der ich die Rechte abfrage:

   private boolean pruefrechte(){
    int result;
    List listPermissionsNeeded = new ArrayList<>();
    for (String p:rechte)
    {
        result = ContextCompat.checkSelfPermission(this,p);
        if (result != PackageManager.PERMISSION_GRANTED)
        {
            listPermissionsNeeded.add(p);
        }
    }
    if (!listPermissionsNeeded.isEmpty())
    {
        ActivityCompat.requestPermissions(this, (String[]) listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),MULTIPLE_PERMISSIONS );
        // keine permissions gesetzt
        return false;
    }
    // alle permissions gesetzt
    return true;
}

Ich habe nun alles in eine try catch genommen

try {
            posmanager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, n_distanz, (LocationListener) horcher);
        }catch (SecurityException e){
            Log.e("sun_app", e.getMessage());
        }

und nun sind die roten Striche weg. Ist dies ebenfalls eine Lösung?

Gruss Renato

Hilfreich?
Kommentieren
Beste Antwort
Jokel
  • Forum-Beiträge: 1.537

07.03.2022, 13:06:01 via Website

So ganz vollständig erscheint mit die Abfrage der Pernission nicht.
Wo ist die Liste der Manifest Permission?
kein Aufruf der erneuten ab frage wenn die Permission nicht GRANTED ist.
kein Aufruf der onRequestPermissionsResult Methode.
Überschrieben scheint die Methode auch nicht zu sein.

hier ein Beispiel wie es sein sollte.

public class MainActivity extends AppCompatActivity {

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

    private final static int REQUEST_CODE_ASK_PERMISSIONS = 1;

    private static final String[] REQUIRED_SDK_PERMISSIONS = new String[]{
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.CAMERA,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
    };


    protected void checkPermissions() {
        final List<String> missingPermissions = new ArrayList<String>();
        // check all required dynamic permissions
        for (final String permission : REQUIRED_SDK_PERMISSIONS) {
            final int result = ContextCompat.checkSelfPermission(this, permission);
            if (result != PackageManager.PERMISSION_GRANTED) {
                missingPermissions.add(permission);
            }
        }
        if (!missingPermissions.isEmpty()) {
            // request all missing permissions
            final String[] permissions = missingPermissions
                    .toArray(new String[missingPermissions.size()]);
            ActivityCompat.requestPermissions(this, permissions, REQUEST_CODE_ASK_PERMISSIONS);
        } else {
            final int[] grantResults = new int[REQUIRED_SDK_PERMISSIONS.length];
            Arrays.fill(grantResults, PackageManager.PERMISSION_GRANTED);
            onRequestPermissionsResult(REQUEST_CODE_ASK_PERMISSIONS, REQUIRED_SDK_PERMISSIONS,
                    grantResults);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[],
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case REQUEST_CODE_ASK_PERMISSIONS:
                for (int index = permissions.length - 1; index >= 0; --index) {
                    if (grantResults[index] != PackageManager.PERMISSION_GRANTED) {
                        // exit the app if one permission is not granted
                        Toast.makeText(this, "Required permission '" + permissions[index]
                                + "' not granted, exiting", Toast.LENGTH_LONG).show();
                        finish();
                        return;
                    }
                }
                // all permissions were granted
                initialize();        //new onCreate
                break;
        }
    }

    private void initialize() {
        int x = 1;
    }

}
Hilfreich?
Robbiani Renato
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 614

12.03.2022, 21:32:25 via Website

Danke Jokel.
Ich werde mir mal bei Gelegenheit den Code anschauen.

Gruss Renato

Hilfreich?
Kommentieren