logo
Development
検索
Androidワークスペース統合ガイド

Androidワークスペース統合ガイド

概要

本ガイドでは、AndroidアプリにGPTBotsワークスペースを統合する方法について、権限申請、ネイティブとH5の連携、その他設定を含めて詳しく説明します。
GPTBotsはワークスペースのDEMOプロジェクトも提供しており、迅速な導入が可能です。Android用DEMOプロジェクト:Android端DEMOプロジェクト

権限一覧

基本権限

ワークスペース機能を正常に利用するため、AndroidManifest.xmlに以下の権限を設定してください。

<!-- ネットワーク権限 --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 録音権限 --> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <!-- ストレージ権限 --> <!-- Android 13未満 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- Android 13以上 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <!-- その他補助権限 --> <uses-permission android:name="android.permission.WAKE_LOCK" />
                      
                      <!-- ネットワーク権限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<!-- 録音権限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

<!-- ストレージ権限 -->
<!-- Android 13未満 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Android 13以上 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />

<!-- その他補助権限 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />

                    
このコードブロックをポップアップで表示

権限処理

アプリ起動時に、マイク・カメラ・アルバム等の実行時権限を動的にリクエストしてください。

// Android 13以上で必要な権限 private final String[] permissionsForAndroid13 = { Manifest.permission.RECORD_AUDIO, Manifest.permission.READ_MEDIA_IMAGES, Manifest.permission.READ_MEDIA_AUDIO, Manifest.permission.READ_MEDIA_VIDEO }; // Android 13未満で必要な権限 private final String[] permissionsForBelowAndroid13 = { Manifest.permission.RECORD_AUDIO, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE };
                      
                      // Android 13以上で必要な権限
private final String[] permissionsForAndroid13 = {
    Manifest.permission.RECORD_AUDIO,
    Manifest.permission.READ_MEDIA_IMAGES,
    Manifest.permission.READ_MEDIA_AUDIO,
    Manifest.permission.READ_MEDIA_VIDEO
};

// Android 13未満で必要な権限
private final String[] permissionsForBelowAndroid13 = {
    Manifest.permission.RECORD_AUDIO,
    Manifest.permission.READ_EXTERNAL_STORAGE,
    Manifest.permission.WRITE_EXTERNAL_STORAGE
};

                    
このコードブロックをポップアップで表示

WebView設定

基本設定

WebViewインスタンス生成時の推奨設定:

WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); // JavaScript有効化 webSettings.setDomStorageEnabled(true); // DOMストレージAPI有効化 webSettings.setAllowFileAccess(true); // ファイルアクセス許可 webSettings.setAllowContentAccess(true); // コンテンツURLアクセス許可 webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); // 混在コンテンツ許可 webSettings.setMediaPlaybackRequiresUserGesture(false); // ユーザー操作不要でメディア再生
                      
                      WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true); // JavaScript有効化
webSettings.setDomStorageEnabled(true); // DOMストレージAPI有効化
webSettings.setAllowFileAccess(true); // ファイルアクセス許可
webSettings.setAllowContentAccess(true); // コンテンツURLアクセス許可
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); // 混在コンテンツ許可
webSettings.setMediaPlaybackRequiresUserGesture(false); // ユーザー操作不要でメディア再生

                    
このコードブロックをポップアップで表示

録音関連設定

webSettings.setAllowFileAccessFromFileURLs(true); // ファイルURLからのアクセス許可 webSettings.setAllowUniversalAccessFromFileURLs(true); // ユニバーサルアクセス許可 webSettings.setDatabaseEnabled(true); // データベース有効化 webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); // キャッシュモード設定
                      
                      webSettings.setAllowFileAccessFromFileURLs(true); // ファイルURLからのアクセス許可
webSettings.setAllowUniversalAccessFromFileURLs(true); // ユニバーサルアクセス許可
webSettings.setDatabaseEnabled(true); // データベース有効化
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); // キャッシュモード設定

                    
このコードブロックをポップアップで表示

User-Agent設定

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

                    
このコードブロックをポップアップで表示

ワークスペースアクセス

URL構築

ワークスペースアクセスにはBase URLとAiTokenが必要です。

String baseUrl = "https://gptbots.ai/space/h5/home"; String aiToken = "YOUR_AI_TOKEN"; // 実際のAiTokenに置き換えてください String fullUrl = baseUrl + "?AiToken=" + AiToken;
                      
                      String baseUrl = "https://gptbots.ai/space/h5/home";
String aiToken = "YOUR_AI_TOKEN"; // 実際のAiTokenに置き換えてください
String fullUrl = baseUrl + "?AiToken=" + AiToken;

                    
このコードブロックをポップアップで表示

アプリにはデフォルトAiTokenが設定されています。変更する場合はログイン画面で入力してください。

ページ読み込み

webView.loadUrl(fullUrl);
                      
                      webView.loadUrl(fullUrl);

                    
このコードブロックをポップアップで表示

WebViewとネイティブの連携

JavaScriptインターフェース登録

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

                    
このコードブロックをポップアップで表示

H5ページはグローバルオブジェクトagentWebBridge経由でネイティブメソッドを呼び出せます。

権限処理

WebView権限リクエスト

H5ページが録音等の特殊権限を要求する場合、WebViewの権限リクエストを処理します。

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) { // アプリが録音権限を持っているか確認 if (checkSelfPermission(Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) { request.grant(requestedResources); } else { // システム権限リクエスト requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, REQUEST_CODE); // 権限リクエストを保存し、取得後に処理 pendingPermissionRequest = request; } } else { // その他権限は直接許可 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) {
            // アプリが録音権限を持っているか確認
            if (checkSelfPermission(Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
                request.grant(requestedResources);
            } else {
                // システム権限リクエスト
                requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, REQUEST_CODE);
                // 権限リクエストを保存し、取得後に処理
                pendingPermissionRequest = request;
            }
        } else {
            // その他権限は直接許可
            request.grant(requestedResources);
        }
    }
});

                    
このコードブロックをポップアップで表示

ファイル選択処理

H5ページのファイル選択操作を処理します。

webView.setWebChromeClient(new WebChromeClient() { @Override public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { // コールバック保存 this.filePathCallback = filePathCallback; // ファイル選択Intent生成 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) { // 選択結果を処理 // ... } filePathCallback.onReceiveValue(results); filePathCallback = null; } } }
                      
                      webView.setWebChromeClient(new WebChromeClient() {
    @Override
    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
        // コールバック保存
        this.filePathCallback = filePathCallback;
        
        // ファイル選択Intent生成
        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) {
                // 選択結果を処理
                // ...
            }
            
            filePathCallback.onReceiveValue(results);
            filePathCallback = null;
        }
    }
}

                    
このコードブロックをポップアップで表示

機能例

WebViewの閉じる

H5ページからWebViewを閉じるリクエスト例:

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

                    
このコードブロックをポップアップで表示

ネイティブ側の処理:

public void onClick(JSONObject data) { String value = data.optString("value"); if (TextUtils.equals(value, "close")) { closeWeb(data); } } public void closeWeb(JSONObject data) { // H5に閉じる通知 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); // 1秒後にActivityを終了 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に閉じる通知
    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);
    
    // 1秒後にActivityを終了
    webView.postDelayed(() -> {
        finish();
    }, 1000);
}

                    
このコードブロックをポップアップで表示