logo
Entwicklung
Suchen
Android-Integration im Workspace: Leitfaden

Android-Integration im Workspace: Leitfaden

Einführung

Diese Anleitung bietet eine detaillierte Schritt-für-Schritt-Erklärung zur Integration des GPTBots-Workspaces in eine Android-Anwendung – von der Berechtigungsanfrage über die native H5-Interaktion bis hin zu weiteren relevanten Konfigurationen.

GPTBots stellt zudem ein Workspace-Demo-Projekt bereit, das Ihnen einen schnellen Einstieg ermöglicht. Android-Demo-Projekt: Android Demo Project

Berechtigungsliste

Grundlegende Berechtigungen

Um sicherzustellen, dass Workspace-bezogene Funktionen ordnungsgemäß funktionieren, konfigurieren Sie bitte die folgenden Berechtigungen in der AndroidManifest.xml:

Umgang mit Berechtigungen

Damit die App zur Laufzeit auf sensible Berechtigungen wie Mikrofon, Kamera und Galerie zugreifen kann, sollten die erforderlichen Berechtigungen bereits beim Start der App abgefragt werden:

// Berechtigungen für Android 13 und höher private final String[] permissionsForAndroid13 = { Manifest.permission.RECORD_AUDIO, Manifest.permission.READ_MEDIA_IMAGES, Manifest.permission.READ_MEDIA_AUDIO, Manifest.permission.READ_MEDIA_VIDEO }; // Berechtigungen für Android-Versionen unter 13 private final String[] permissionsForBelowAndroid13 = { Manifest.permission.RECORD_AUDIO, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE };
                      
                      // Berechtigungen für Android 13 und höher
private final String[] permissionsForAndroid13 = {
    Manifest.permission.RECORD_AUDIO,
    Manifest.permission.READ_MEDIA_IMAGES,
    Manifest.permission.READ_MEDIA_AUDIO,
    Manifest.permission.READ_MEDIA_VIDEO
};

// Berechtigungen für Android-Versionen unter 13
private final String[] permissionsForBelowAndroid13 = {
    Manifest.permission.RECORD_AUDIO,
    Manifest.permission.READ_EXTERNAL_STORAGE,
    Manifest.permission.WRITE_EXTERNAL_STORAGE
};

                    
Dieser Codeblock im schwebenden Fenster

WebView-Konfiguration

Grundkonfiguration

Die App erstellt eine WebView-Instanz und nimmt die erforderlichen Einstellungen vor:

WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); // JavaScript aktivieren webSettings.setDomStorageEnabled(true); // DOM Storage API aktivieren webSettings.setAllowFileAccess(true); // Dateizugriff erlauben webSettings.setAllowContentAccess(true); // Zugriff auf Content-URLs erlauben webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); // Gemischte Inhalte erlauben webSettings.setMediaPlaybackRequiresUserGesture(false); // Medienwiedergabe ohne Nutzerinteraktion erlauben
                      
                      WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true); // JavaScript aktivieren
webSettings.setDomStorageEnabled(true); // DOM Storage API aktivieren
webSettings.setAllowFileAccess(true); // Dateizugriff erlauben
webSettings.setAllowContentAccess(true); // Zugriff auf Content-URLs erlauben
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); // Gemischte Inhalte erlauben
webSettings.setMediaPlaybackRequiresUserGesture(false); // Medienwiedergabe ohne Nutzerinteraktion erlauben

                    
Dieser Codeblock im schwebenden Fenster

Konfiguration für Audioaufnahmen

webSettings.setAllowFileAccessFromFileURLs(true); // Dateizugriff von Datei-URLs erlauben webSettings.setAllowUniversalAccessFromFileURLs(true); // Universellen Zugriff erlauben webSettings.setDatabaseEnabled(true); // Datenbank aktivieren webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); // Cache-Modus setzen
                      
                      webSettings.setAllowFileAccessFromFileURLs(true); // Dateizugriff von Datei-URLs erlauben
webSettings.setAllowUniversalAccessFromFileURLs(true); // Universellen Zugriff erlauben
webSettings.setDatabaseEnabled(true); // Datenbank aktivieren
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); // Cache-Modus setzen

                    
Dieser Codeblock im schwebenden Fenster

User-Agent-Einstellung

String userAgent = webSettings.getUserAgentString(); webSettings.setUserAgentString(userAgent + " WebViewApp/1.0");
                      
                      String userAgent = webSettings.getUserAgentString();
webSettings.setUserAgentString(userAgent + " WebViewApp/1.0");

                    
Dieser Codeblock im schwebenden Fenster

Workspace-Zugriff

URL-Konstruktion

Für den Zugriff auf den Workspace werden die Base-URL und der AiToken-Parameter benötigt:

String baseUrl = "https://gptbots.ai/space/h5/home"; String aiToken = "YOUR_AI_TOKEN"; // Ersetzen Sie dies durch Ihren tatsächlichen AiToken String fullUrl = baseUrl + "?AiToken=" + aiToken;
                      
                      String baseUrl = "https://gptbots.ai/space/h5/home";
String aiToken = "YOUR_AI_TOKEN"; // Ersetzen Sie dies durch Ihren tatsächlichen AiToken
String fullUrl = baseUrl + "?AiToken=" + aiToken;

                    
Dieser Codeblock im schwebenden Fenster

Der Standard-AiToken ist in der App vorkonfiguriert. Falls Sie ihn ändern möchten, können Sie dies auf der Login-Seite tun.

Laden der Seite

webView.loadUrl(fullUrl);

WebView- und Native-Interaktion

JavaScript-Schnittstelle registrieren

webView.addJavascriptInterface(new JSBridge(), "agentWebBridge");
                      
                      webView.addJavascriptInterface(new JSBridge(), "agentWebBridge");

                    
Dieser Codeblock im schwebenden Fenster

Die H5-Seite ruft native Methoden über das globale Objekt agentWebBridge auf.

Umgang mit Berechtigungen

WebView-Berechtigungsanfragen

Wenn die H5-Seite spezielle Berechtigungen (z. B. Audioaufnahme) anfordert, müssen diese über die WebView behandelt werden:

webView.setWebChromeClient(new WebChromeClient() { @Override public void onPermissionRequest(PermissionRequest request) { String[] requestedResources = request.getResources(); boolean hasAudioPermission = false; for (String resource : requestedResources) { if (PermissionRequest.RESOURCE_AUDIO_CAPTURE.equals(resource)) { hasAudioPermission = true; break; } } if (hasAudioPermission) { // Prüfen, ob die App die Berechtigung zur Audioaufnahme hat if (checkSelfPermission(Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) { request.grant(requestedResources); } else { // Systemberechtigung anfordern requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, REQUEST_CODE); // Berechtigungsanfrage speichern, um sie nach Erteilung zu bearbeiten pendingPermissionRequest = request; } } else { // Andere Berechtigungen direkt gewähren request.grant(requestedResources); } } });
                      
                      webView.setWebChromeClient(new WebChromeClient() {
    @Override
    public void onPermissionRequest(PermissionRequest request) {
        String[] requestedResources = request.getResources();
        boolean hasAudioPermission = false;
        
        for (String resource : requestedResources) {
            if (PermissionRequest.RESOURCE_AUDIO_CAPTURE.equals(resource)) {
                hasAudioPermission = true;
                break;
            }
        }
        
        if (hasAudioPermission) {
            // Prüfen, ob die App die Berechtigung zur Audioaufnahme hat
            if (checkSelfPermission(Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
                request.grant(requestedResources);
            } else {
                // Systemberechtigung anfordern
                requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, REQUEST_CODE);
                // Berechtigungsanfrage speichern, um sie nach Erteilung zu bearbeiten
                pendingPermissionRequest = request;
            }
        } else {
            // Andere Berechtigungen direkt gewähren
            request.grant(requestedResources);
        }
    }
});

                    
Dieser Codeblock im schwebenden Fenster

Dateiauswahl behandeln

Dateiauswahl-Operationen von H5-Seiten behandeln:

webView.setWebChromeClient(new WebChromeClient() { @Override public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { // Callback speichern this.filePathCallback = filePathCallback; // Datei-Auswahl-Intent erstellen Intent intent = fileChooserParams.createIntent(); startActivityForResult(intent, REQUEST_FILE_CHOOSER); return true; } }); @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_FILE_CHOOSER) { if (filePathCallback != null) { Uri[] results = null; if (resultCode == RESULT_OK && data != null) { // Auswahl-Ergebnisse verarbeiten // ... } filePathCallback.onReceiveValue(results); filePathCallback = null; } } }
                      
                      webView.setWebChromeClient(new WebChromeClient() {
    @Override
    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
        // Callback speichern
        this.filePathCallback = filePathCallback;
        
        // Datei-Auswahl-Intent erstellen
        Intent intent = fileChooserParams.createIntent();
        startActivityForResult(intent, REQUEST_FILE_CHOOSER);
        return true;
    }
});

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    
    if (requestCode == REQUEST_FILE_CHOOSER) {
        if (filePathCallback != null) {
            Uri[] results = null;
            
            if (resultCode == RESULT_OK && data != null) {
                // Auswahl-Ergebnisse verarbeiten
                // ...
            }
            
            filePathCallback.onReceiveValue(results);
            filePathCallback = null;
        }
    }
}

                    
Dieser Codeblock im schwebenden Fenster

Funktionsbeispiele

WebView schließen

Die H5-Seite kann das Schließen der WebView wie folgt anfordern:

var message = { eventType: "click", data: { value: "close" } }; agentWebBridge.callNative(JSON.stringify(message));
                      
                      var message = {
    eventType: "click",
    data: {
        value: "close"
    }
};
agentWebBridge.callNative(JSON.stringify(message));

                    
Dieser Codeblock im schwebenden Fenster

Native-Seite:

public void onClick(JSONObject data) { String value = data.optString("value"); if (TextUtils.equals(value, "close")) { closeWeb(data); } } public void closeWeb(JSONObject data) { // H5 benachrichtigen, dass geschlossen wird JSONObject willCloseData = new JSONObject(); willCloseData.put("value", data.optString("value")); willCloseData.put("reason", "user_request"); willCloseData.put("delay", 1000); willCloseData.put("timestamp", System.currentTimeMillis()); webViewBridge.callH5(WebViewBridge.EVENT_CLICK, willCloseData); // Schließen der Activity verzögern webView.postDelayed(() -> { finish(); }, 1000); }
                      
                      public void onClick(JSONObject data) {
    String value = data.optString("value");
    if (TextUtils.equals(value, "close")) {
        closeWeb(data);
    }
}
public void closeWeb(JSONObject data) {
    // H5 benachrichtigen, dass geschlossen wird
    JSONObject willCloseData = new JSONObject();
    willCloseData.put("value", data.optString("value"));
    willCloseData.put("reason", "user_request");
    willCloseData.put("delay", 1000);
    willCloseData.put("timestamp", System.currentTimeMillis());
    webViewBridge.callH5(WebViewBridge.EVENT_CLICK, willCloseData);
    // Schließen der Activity verzögern
    webView.postDelayed(() -> {
        finish();
    }, 1000);
}

                    
Dieser Codeblock im schwebenden Fenster