Autor Beitrag
JmHobby
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Do 14.07.22 21:06 
Hi Delphianer,

habe ein kleines Problem mit eigener SQL Datenbank "spkasse.db" und "canastra.db".
Diese DB ist in den Ordner GetHomePath auf den Android-Smartphone bereitgestellt
und der Zugriff funktioniert super (Speichern,Löschen usw.).
Jetzt möchte das DB's so Art als Sicherung in den GetSharedDocumentsPath abspeichern.
Auch das klappt super. Hier der Codeauschnitt:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
procedure Texptform.btn_dbexportClick(Sender: TObject);
var
pfad_can, pfad_spk : String;
begin
    pfad_can := System.IOUtils.TPath.GetHomePath + PathDelim +'canastra.db';
     pfad_spk := System.IOUtils.TPath.GetHomePath + PathDelim +'spkasse.db';

    if FileExists(pfad_can) then
     begin
       begin
          PermissionsService.RequestPermissions(['android.permission.READ_EXTERNAL_STORAGE','android.permission.WRITE_INTERNAL_STORAGE'],
            procedure(const APermissions: TClassicStringDynArray; const AGrantResults: TClassicPermissionStatusDynArray)
             begin
              System.IOUtils.TFile.Copy(PChar(pfad_can),PChar(System.IOUtils.TPath.GetSharedDocumentsPath + PathDelim +'canastra.db'),true);
              System.IOUtils.TFile.Copy(PChar(pfad_spk),PChar(System.IOUtils.TPath.GetSharedDocumentsPath + PathDelim +'spkasse.db'),true);
             end);
          lbl_exptmeldung.Text := 'Die Canastra-Dateien ("canastra.db" und "spkasse.db") wurden in den Dokumenten-Ordner  des Phones kopiert.';
      end;
      end
    else begin
     lbl_exptmeldung.Text := '';
     ShowMessage('Es keine Datei gefunden.');
    end;
end;


Aber umgekehrt funktioniert es nicht. Dateien werden mit den Daten nicht übernommen.
Hier der Code:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
procedure Texptform.btn_dbimportClick(Sender: TObject);
var
pfad_can, pfad_spk : String;
begin
    pfad_can := System.IOUtils.TPath.GetSharedDocumentsPath + PathDelim +'canastra.db';
     pfad_spk := System.IOUtils.TPath.GetSharedDocumentsPath + PathDelim +'spkasse.db';

    if FileExists(pfad_can) then
     begin
       begin
          PermissionsService.RequestPermissions(['android.permission.READ_EXTERNAL_STORAGE','android.permission.WRITE_INTERNAL_STORAGE'],
            procedure(const APermissions: TClassicStringDynArray; const AGrantResults: TClassicPermissionStatusDynArray)
             begin
              System.IOUtils.TFile.Copy(PChar(pfad_can),PChar(System.IOUtils.TPath.GetHomePath + PathDelim +'canastra.db'),true);
              System.IOUtils.TFile.Copy(PChar(pfad_spk),PChar(System.IOUtils.TPath.GetHomePath + PathDelim +'spkasse.db'),true);
             end);
          lbl_exptmeldung.Text := 'Die importierten Canastra-Datenbanken ("canastra.db" und "spkasse.db") wurden übernommen.';
      end;
      end
    else begin
     lbl_exptmeldung.Text := '';
     ShowMessage('Es keine Datei gefunden.');
    end;
end;


Frage: Ist es überhaupt möglich im .assets\internal eine SQL-Datenbank zu überschreiben.
Oder kann man einen Zugriff einer SQL-DB im Ordner GetSharedDocumentsPath ohne eine Bereitstellung durch Delphi bewerkstelligen.

Wer kann mir hier helfen?

Danke

Moderiert von user profile iconTh69: Topic aus Grafische Benutzeroberflächen (VCL & FireMonkey) verschoben am Fr 15.07.2022 um 08:32
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Fr 15.07.22 08:24 
Laut Erstellen einer Android-App: Laden und Bereitstellen von Dateien ist TPath.GetDocumentsPath der Pfad auf das "Assets/Internal"-Verzeichnis. Wenn du aber TPath.GetSharedDocumentsPath benutzt, so greifst du wohl auf das "external"-Verzeichnis zu.
Ändere den Pfad oder die "Permissions" auf WRITE_EXTERNAL_STORAGE.

PS: Du solltest aber in deiner Prozedur auch überprüfen, ob deiner App Zugriff gewährt wurde, s.a. Beispiel in Android Permission Model.

Für diesen Beitrag haben gedankt: JmHobby
JmHobby Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Fr 15.07.22 15:29 
Komme mit den Einstellungen der android.permission nicht klar.
Was muss ich wo einstellen damit man auf DB-Dateien ausserhalb von GetHomePath zugreifen kann.
Die beiden Dateien "canastra.db" und "spkasse.db" habe ich laut Bereitstellung-Manager Delphi in .\assets\internal bereitgestellt.
Das scheint ja in meinen Fall nicht richtig zu sein.
Was muss im Bereitstellungs-Manager Delphi stehen, damit meine beiden DB von der Anwendung ausserhalb vom .\assets\internal geladen,bearbeitet und gespeichert werden können.

Kenne mich in Android nicht gut aus und dachte mit Delphi Mobile wäre das ein wenig einfacher für ungeübte und wenig erfahrende Hobby Programmierer.

Für einen kleinen Beispiel-Code wäre ich dankbar

viele Grüße

Jmhobby

Moderiert von user profile iconTh69: Beitragsformatierung überarbeitet.
Moderiert von user profile iconTh69: Delphi-Tags hinzugefügt
Moderiert von user profile iconTh69: Code-Tags hinzugefügt
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Fr 15.07.22 16:41 
Was hast du denn jetzt geändert und was funktioniert immer noch nicht?

Ich hoffe, dir ist auch klar, daß die Zieldatei beim Kopieren nicht im Zugriff sein darf (d.h. keine [bzw. geschlossene] Datenbankverbindung)?!
Du solltest deswegen also jede Exception abfangen, s.a. TFile.Copy ("Hinweis" unten).

Für diesen Beitrag haben gedankt: JmHobby
JmHobby Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Fr 15.07.22 17:30 
Geändert habe ich jetzt nur WRITE_INTERNAL_STORAGE in EXTERNAL
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
procedure Texptform.btn_dbimportClick(Sender: TObject);
var
pfad_can, pfad_spk : String;
begin

        startcan.canastraConnection.Database := System.IOUtils.TPath.GetHomePath + PathDelim +'canastra.db';
        startcan.canastraConnection.Connected := False;
        startcan.canastraConnection.Options.Direct := False;
        startcan.canastraQuery.Connection := startcan.canastraConnection;
         startcan.canastraConnection.Database := System.IOUtils.TPath.GetHomePath + PathDelim +'spkasse.db';
        startcan.canastraConnection.Connected := False;
        startcan.canastraConnection.Options.Direct := False;
        startcan.canastraQuery.Connection := startcan.canastraConnection;


    pfad_can := System.IOUtils.TPath.GetSharedDocumentsPath + PathDelim +'canastra.db';
     pfad_spk := System.IOUtils.TPath.GetSharedDocumentsPath + PathDelim +'spkasse.db';

    if FileExists(pfad_can) then
     begin
       begin
         //PermissionsService.RequestPermissions(['android.permission.READ_EXTERNAL_STORAGE','android.permission.WRITE_INTERNAL_STORAGE'],
           PermissionsService.RequestPermissions(['android.permission.READ_EXTERNAL_STORAGE','android.permission.WRITE_EXTERNAL_STORAGE'],
            procedure(const APermissions: TClassicStringDynArray; const AGrantResults: TClassicPermissionStatusDynArray)
             begin
              try
                System.IOUtils.TFile.Copy(PChar(pfad_can),PChar(System.IOUtils.TPath.GetHomePath + PathDelim +'canastra.db'),true);
                System.IOUtils.TFile.Copy(PChar(pfad_spk),PChar(System.IOUtils.TPath.GetHomePath + PathDelim +'spkasse.db'),true);
              except
                on E: Exception do
                 ShowMessage('Fehler beim Laden: ' + E.Message);
              end;
             end);
          lbl_exptmeldung.Text := 'Die importierten Canastra-datenbanken ("canastra.db" und "spkasse.db") wurden übernommen.';
      end;
      end
    else begin
     lbl_exptmeldung.Text := '';
     ShowMessage('Es keine Datei gefunden.');
    end;

end;


Jetzt bekomme ich folgende Fehlermeldung:
Permission denied [/storage/emulated/0/Documents/canastra.db].

Kurze Info: Benutze die LiteDac - Komponente


Zuletzt bearbeitet von JmHobby am Fr 15.07.22 17:56, insgesamt 1-mal bearbeitet
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Fr 15.07.22 17:53 
Welche TargetSDKVersion verwendest du?
Vllt. hilft dir der englische SO-Beitrag Permission denied on writing to external storage despite permission ?

Aber möchtest du denn jetzt eher auf das "Internal" (wie in deinem Eingangsbeitrag beschrieben) oder doch jetzt auf das "External"-Verzeichnis zugreifen?
JmHobby Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Fr 15.07.22 18:00 
Bei delphi Android SDK 25.2.5 64 Bit
TargetSDKVersion = 30

Auf Smartphone
Android Version 12

Moderiert von user profile iconTh69: Beiträge zusammengefasst

Würde gern External bevorzugen, da ich die db's auch mit den aktuellen Daten auf ein Tablett mit derselben Anwendung benutzen möchte und die Daten dann auch gleich sind.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: So 17.07.22 09:57 
Hast du denn mal ausprobiert, ob wenigstens das Kopieren zum/vom "Internal"-Verzeichnis (TPath.GetDocumentsPath) jetzt einwandfrei funktioniert?

Und hast du denn auch im Android-Manifest die Berechtigung für READ/WRITE_EXTERNAL_STORAGE erteilt, s. Anwendungsmanifestdatei für Android (AndroidManifest.xml) sowie Verwende Berechtigungen ?
JmHobby Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: So 17.07.22 16:15 
Hi Moderator,

Das Kopieren von/zum Internal GetHomePath und GetDocumentsPath funktioniert in beiden Richtungen.
Aber ich möchte doch die beiden Dateien auch auf ein Android -Tablet mit der gleichen Anwendung benutzen.
Das Kopieren der beiden Dateien in den GetSharedDocumentsPath - Ordner funktioniert ja, nur vom
SharedDocumentsPath - Ordner in den Internal Anwendungsordner (GetHomePath) funkioniert nicht.
Der Zweck sollte ja so sein, dass ich die DB's mit den aktuellen Daten in den Anwendungsordner (z.B.vom Handy zum Tablet) die jeweiligen DB's
überschreiben kann und somit die aktuellen Daten auch auf dem Android-Tablet in der Anwendung sind und natürlich auch umgekehrt.
So Art einer Datensynchronisation.

Habe keine Ahnung wie ich das Problem noch lösen kann.

Hier noch meine aktuelle AndroidManifest für diese App:

ausblenden volle Höhe XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
<?xml version="1.0" encoding="utf-8"?>
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.embarcadero.canastra"
    android:versionCode="1"
    android:versionName="1.0.0"
    android:installLocation="auto">
    <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="30" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <uses-feature android:glEsVersion="0x00020000" android:required="true"/>
    <queries>

    </queries>
    <application
        android:persistent="False"
        android:restoreAnyVersion="False"
        android:label="canastra"
        android:debuggable="true"
        android:largeHeap="False"
        android:icon="@drawable/ic_launcher"
        android:theme="@style/AppTheme"
        android:hardwareAccelerated="true"
        android:resizeableActivity="false"
        android:requestLegacyExternalStorage="true">
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="com.embarcadero.canastra.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths" />
        </provider>




        <!-- Our activity is a subclass of the built-in NativeActivity framework class.
             This will take care of integrating with our NDK code. -->

        <activity
            android:name="com.embarcadero.firemonkey.FMXNativeActivity"
            android:label="canastra"
            android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
            android:launchMode="singleTask">
            <!-- Tell NativeActivity the name of our .so -->
            <meta-data android:name="android.app.lib_name" android:value="canastra" />

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <receiver android:name="com.embarcadero.rtl.notifications.NotificationAlarm" />

    </application>
</manifest>
<!-- END_INCLUDE(manifest) -->
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: So 17.07.22 18:21 
Du erhältst weiterhin eine "Permission denied"-Meldung? Und nur beim Lesen aus dem "EXTERNAL_STORAGE" oder doch beim Schreiben?

Hast du denn mal den englischen SO-Beitrag angeschaut? Oder kannst du kein englisch?

Setze mal (testweise) das TargetSDK auf 28 (oder kleiner).
JmHobby Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Do 21.07.22 19:03 
Lösung weiterhin offen.

Habe die App mal auf ein Gerät mit Android 8 installiert und alles funktioniert bestens.

Aber mit den Gerät auf dem Android 12 installiert ist, habe ich eben diese Permission denied Probleme.
Ich weiss wirklich nicht mehr weiter, wie man das mit Delphi 11 und Android 12 löst.
Weiss auch nicht wo und was ich bei Delphi-Bereitstellung einstellen muss.
Habe zum Bespiel in Option Laufzeit durch Benutzer Externen Speicher lesen und schreiben auf true, Sicher Dateifreigabe auf true usw. gestellt - Kein Erfolg bei Android 12.
Wie gesagt bei Android 8 funktioniert.

Ich bräuchte mal ein Code Beispiel wie man das bei Android 12 unter Delphi einstellt.
Im reinen Android bin ich nicht fit genug.

Vielen Dank im Voraus
Beste Grüße
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Fr 22.07.22 11:36 
Du mußt wohl einen anderen Weg gehen, s. Antwort in READ_EXTERNAL_STORAGE Problem with android 12 (Stichwort ist also Scoped Storage).