前言
近年來,混合開發也越來越用的更多,而原生webview
的各種坑,比如說 上傳圖片、檔案問題、視訊全屏問題(什麼在微信上開啟都是好的,你這怎麼全屏不了)、版本差異問題,所以還是建議使用騰訊x5瀏覽器。
如何使用
- 1.去官網上下載最新的
jar
、so
檔案等 連結點這裡 - 2.新增
jar
包、so
檔案,配置gradle
在build.gradle 中新增libs、配置ndk
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
複製程式碼
ndk {
abiFilters "armeabi"
}
複製程式碼
- 3.在
Application
中新增初始化x5程式碼,記得在AndroidManifest.xml
中註冊你自定的Application
QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback() {
@Override
public void onViewInitFinished(boolean arg0) {
//x5核心初始化完成的回撥,為true表示x5核心載入成功,否則表示x5核心載入失敗,會自動切換到系統核心。
Log.d("app", " onViewInitFinished is " + arg0);
}
@Override
public void onCoreInitFinished() {
}
};
//x5核心初始化介面
QbSdk.initX5Environment(getApplicationContext(), cb);
複製程式碼
- 4.新增許可權
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 硬體加速對X5視訊播放非常重要,建議開啟 -->
<uses-permission android:name="android.permission.GET_TASKS" />
複製程式碼
- 5.新增
WebActivity
,初始化x5配置 記得在AndroidManifest.xml
中註冊
webView = (WebView) findViewById(R.id.webView);
WebSettings webSetting = webView.getSettings();
webSetting.setJavaScriptEnabled(true);
webSetting.setJavaScriptCanOpenWindowsAutomatically(true);
webSetting.setAllowFileAccess(true);
webSetting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
webSetting.setSupportZoom(true);
webSetting.setBuiltInZoomControls(false);
webSetting.setUseWideViewPort(true);
webSetting.setSupportMultipleWindows(true);
// webSetting.setLoadWithOverviewMode(true);
webSetting.setAppCacheEnabled(true);
// webSetting.setDatabaseEnabled(true);
webSetting.setDomStorageEnabled(true);
webSetting.setGeolocationEnabled(true);
webSetting.setAppCacheMaxSize(Long.MAX_VALUE);
// webSetting.setPageCacheCapacity(IX5WebSettings.DEFAULT_CACHE_CAPACITY);
webSetting.setPluginState(WebSettings.PluginState.ON_DEMAND);
// webSetting.setRenderPriority(WebSettings.RenderPriority.HIGH);
webSetting.setCacheMode(WebSettings.LOAD_NO_CACHE);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
webView.getView().setOverScrollMode(View.OVER_SCROLL_ALWAYS);
// this.getSettingsExtension().setPageCacheCapacity(IX5WebSettings.DEFAULT_CACHE_CAPACITY);//extension
// settings 的設計
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView webView, String url) {
webView.loadUrl(url);
return true;
}
});
複製程式碼
- 6、新增上傳檔案、圖片適配程式碼
webView.setWebChromeClient(new WebChromeClient() {
// For Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
uploadFile = uploadFile;
openFileChooseProcess();
}
// For Android < 3.0
public void openFileChooser(ValueCallback<Uri> uploadMsgs) {
uploadFile = uploadFile;
openFileChooseProcess();
}
// For Android > 4.1.1
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
uploadFile = uploadFile;
openFileChooseProcess();
}
// For Android >= 5.0
public boolean onShowFileChooser(com.tencent.smtt.sdk.WebView webView,
ValueCallback<Uri[]> filePathCallback,
WebChromeClient.FileChooserParams fileChooserParams) {
uploadFiles = filePathCallback;
openFileChooseProcess();
return true;
}
});
複製程式碼
private void openFileChooseProcess() {
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
startActivityForResult(Intent.createChooser(i, "test"), 0);
}
複製程式碼
- 7、處理選擇檔案、圖片後回撥
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case 0:
if (null != uploadFile) {
Uri result = data == null || resultCode != RESULT_OK ? null
: data.getData();
uploadFile.onReceiveValue(result);
uploadFile = null;
}
if (null != uploadFiles) {
Uri result = data == null || resultCode != RESULT_OK ? null
: data.getData();
uploadFiles.onReceiveValue(new Uri[]{result});
uploadFiles = null;
}
break;
default:
break;
}
} else if (resultCode == RESULT_CANCELED) {
if (null != uploadFile) {
uploadFile.onReceiveValue(null);
uploadFile = null;
}
}
}
複製程式碼
- 8、新增視訊全屏相關程式碼
webView.setWebChromeClient(new WebChromeClient() {
// For Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
uploadFile = uploadFile;
openFileChooseProcess();
}
// For Android < 3.0
public void openFileChooser(ValueCallback<Uri> uploadMsgs) {
uploadFile = uploadFile;
openFileChooseProcess();
}
// For Android > 4.1.1
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
uploadFile = uploadFile;
openFileChooseProcess();
}
// For Android >= 5.0
public boolean onShowFileChooser(com.tencent.smtt.sdk.WebView webView,
ValueCallback<Uri[]> filePathCallback,
WebChromeClient.FileChooserParams fileChooserParams) {
uploadFiles = filePathCallback;
openFileChooseProcess();
return true;
}
View myVideoView;
View myNormalView;
IX5WebChromeClient.CustomViewCallback callback;
/**
* 全屏播放配置
*/
@Override
public void onShowCustomView(View view,
IX5WebChromeClient.CustomViewCallback customViewCallback) {
FrameLayout normalView = (FrameLayout) findViewById(R.id.web_filechooser);
ViewGroup viewGroup = (ViewGroup) normalView.getParent();
viewGroup.removeView(normalView);
viewGroup.addView(view);
myVideoView = view;
myNormalView = normalView;
callback = customViewCallback;
}
@Override
public void onHideCustomView() {
if (callback != null) {
callback.onCustomViewHidden();
callback = null;
}
if (myVideoView != null) {
ViewGroup viewGroup = (ViewGroup) myVideoView.getParent();
viewGroup.removeView(myVideoView);
viewGroup.addView(myNormalView);
}
}
});
複製程式碼
webView.addJavascriptInterface(new WebViewJavaScriptFunction() {
@Override
public void onJsFunctionCalled(String tag) {
}
@JavascriptInterface
public void onX5ButtonClicked() {
enableX5FullscreenFunc();
}
@JavascriptInterface
public void onCustomButtonClicked() {
disableX5FullscreenFunc();
}
@JavascriptInterface
public void onLiteWndButtonClicked() {
enableLiteWndFunc();
}
@JavascriptInterface
public void onPageVideoClicked() {
enablePageVideoFunc();
}
}, "Android");
複製程式碼
// 向webview發出資訊
private void enableX5FullscreenFunc() {
if (webView.getX5WebViewExtension() != null) {
Bundle data = new Bundle();
data.putBoolean("standardFullScreen", false);// true表示標準全屏,false表示X5全屏;不設定預設false,
data.putBoolean("supportLiteWnd", false);// false:關閉小窗;true:開啟小窗;不設定預設true,
data.putInt("DefaultVideoScreen", 2);// 1:以頁面內開始播放,2:以全屏開始播放;不設定預設:1
webView.getX5WebViewExtension().invokeMiscMethod("setVideoParams",
data);
}
}
private void disableX5FullscreenFunc() {
if (webView.getX5WebViewExtension() != null) {
Bundle data = new Bundle();
data.putBoolean("standardFullScreen", true);// true表示標準全屏,會調起onShowCustomView(),false表示X5全屏;不設定預設false,
data.putBoolean("supportLiteWnd", false);// false:關閉小窗;true:開啟小窗;不設定預設true,
data.putInt("DefaultVideoScreen", 2);// 1:以頁面內開始播放,2:以全屏開始播放;不設定預設:1
webView.getX5WebViewExtension().invokeMiscMethod("setVideoParams",
data);
}
}
private void enableLiteWndFunc() {
if (webView.getX5WebViewExtension() != null) {
Bundle data = new Bundle();
data.putBoolean("standardFullScreen", false);// true表示標準全屏,會調起onShowCustomView(),false表示X5全屏;不設定預設false,
data.putBoolean("supportLiteWnd", true);// false:關閉小窗;true:開啟小窗;不設定預設true,
data.putInt("DefaultVideoScreen", 2);// 1:以頁面內開始播放,2:以全屏開始播放;不設定預設:1
webView.getX5WebViewExtension().invokeMiscMethod("setVideoParams",
data);
}
}
private void enablePageVideoFunc() {
if (webView.getX5WebViewExtension() != null) {
Bundle data = new Bundle();
data.putBoolean("standardFullScreen", false);// true表示標準全屏,會調起onShowCustomView(),false表示X5全屏;不設定預設false,
data.putBoolean("supportLiteWnd", false);// false:關閉小窗;true:開啟小窗;不設定預設true,
data.putInt("DefaultVideoScreen", 1);// 1:以頁面內開始播放,2:以全屏開始播放;不設定預設:1
webView.getX5WebViewExtension().invokeMiscMethod("setVideoParams",
data);
}
}
複製程式碼
- 9、新增下載相關程式碼
webView.setDownloadListener(new DownloadListener() {
@Override
public void onDownloadStart(String s, String s1, String s2, String s3, long l) {
}
});
複製程式碼
- 10、最後,當
Activity
銷燬時,釋放webview
/**
* 確保登出配置能夠被釋放
*/
@Override
protected void onDestroy() {
if (this.webView != null) {
webView.destroy();
}
super.onDestroy();
}
複製程式碼
到這裡,x5瀏覽器的整合已經完成了,快去試試吧
常見問題
視訊無法全屏
請注意AndroidManifest.xml
中配置
<activity
android:name=".WebActivity"
android:configChanges="orientation|screenSize|keyboardHidden"></activity>
複製程式碼
原生與webview 共享cookie
首先,原生需要將cookie 持久化的儲存起來,具體可以參考 【Android架構】基於MVP模式的Retrofit2+RXjava封裝之常見問題(四),至於非okhttp
網路的,可以自行百度
然後傳遞給webview
//建立CookieSyncManager
CookieSyncManager.createInstance(context);
//得到CookieManager
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
cookieManager.removeSessionCookie();// 移除
cookieManager.removeAllCookie();
//得到向URL中新增的Cookie的值
store = new PersistentCookieStore(context);
List<Cookie> cookieList = store.getCookies();
if (cookieList != null && cookieList.size() > 0) {
Cookie cookie = null;
for (Cookie c : cookieList) {
if (c.domain() != null) {
if (c.domain().contains("38")) {
cookie = c;
}
}
}
if (cookie == null) {
cookie = cookieList.get(0);
}
cookieManager.setCookie(url, cookie.name() + "=" + cookie.value());
if (Build.VERSION.SDK_INT < 21) {
CookieSyncManager.getInstance().sync();
} else {
CookieManager.getInstance().flush();
}
}
複製程式碼
需要注意的是,本地儲存的cookie
可能會有多個,要根據domain
來判斷出正確的cookie