Android 工作區整合指南
Android 工作區整合指南
簡介
本指南提供詳細說明,協助您將 GPTBots 工作區整合進 Android 應用程式,包括權限請求、原生與 H5 頁面的互動,以及其他相關配置。
GPTBots 亦提供工作區示例專案,助您快速上手。Android 範例專案:Android Demo Project
權限清單
基本權限
為確保工作區相關功能正常運作,請於 AndroidManifest.xml 配置下列權限:
權限處理
為確保應用程式於執行期間能獲取麥克風、相機、相簿等敏感權限,建議於應用啟動時請求必要的執行期間權限:
// 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。如需更改,可於登入頁面輸入新的 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);
// 延遲關閉 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);
// 延遲關閉 Activity
webView.postDelayed(() -> {
finish();
}, 1000);
}
此代碼塊在浮窗中顯示
