webview添加參數與修改請求頭的user-agent實例
前言
最近公司項目需求,在項目中嵌入h5頁面,一般原生,看著感覺跟往常一樣,一個地址就完全ok了,如果是這樣那就沒有這個博文的必要了!
項目的登錄使用的token登錄,在移動端的登錄是原生的,但是h5也是有登錄頁面,這就需要控制token的過期時間了,但是想達到的網頁訪問使用網頁的cookie,app登錄使用的是app原生的登錄token,在網頁的cookie登錄過期的時候,網頁是可以正常退回登錄頁面,而在app嵌入的h5也需要根據token是否過期,決定是否返回登錄頁。
那么,問題就是在此產生了,token過期的時候app端是如何知道呢?這篇博文記錄解決方案:
正常使用
按照正常程序走的話,我們使用
webView.loadUrl(url);
這樣就可以解決平時之間訪問一個網頁的需求?;蛘咴趗rl的后面拼接上我們需要的token去驗證登錄狀態(tài),也可以拼接其他參數做一些特殊的處理。
但是如果僅僅是拼接token過去,在當前頁面(一級頁面)是可以正常判斷過期時間,但是如果在此頁面(一級頁面)有按鈕點擊進入二級頁面,這樣在二級頁面是沒有token的拼接的,如果在一級頁面token過期了,還是能正常進入二級頁面,所以在二級頁面還是處于登錄的狀態(tài),但是實際在一級頁面的時候token已經是過期的了,所以正常來說二級頁面也是處于退出登錄狀態(tài)才對,但是由于token是在一級頁面的時候進行拼接的,所以能正常判斷,但是二級頁面我們沒有拼接,所以無法判斷。
總結:此方法不適合所有登錄頁面都需要判斷登錄狀態(tài)的h5
添加請求頭
在加載h5的時候添加請求頭
在度娘上有很多都是直接使用webView.loadUrl(url,header);直接添加請求頭(header),但是這種方法與step1中的沒有多大的區(qū)別,也只是在一級頁面的時候生效,二級頁面的header還是變成了之前的默認的了。
同步cookie
使用cookie,同步網頁的cookie,這種方法可以是可以,但是并不能使用很多情況,如果你是半原生,半h5,而你原生的登錄的登錄使用的是token進行登錄的驗證的話,cookie的這種方法也不是一個很好的方法。cookie的同步就不介紹了,在度娘上可以找到。
修改user-agent、訪問url都拼接token
因為我們的需求的進行多端登錄,進行不同設備的判斷,所以我們移動端的h5頁面要告訴服務端,這個是訪問是我們app訪問的,所以我們需要解決的是讓服務端如何知道這個網頁的訪問是移動端訪問的。
在http請求頭中,有user-agent,服務端可以根據請求頭的user-agent來判斷當前是什么設備訪問的,所以我們要跟服務端規(guī)定好給服務端傳一個特殊的字符串,默認這是我們app訪問的,這樣服務端就知道是誰訪問的了,然后進行相關的操作。
而webview中也剛好提供了方法進行user-agent的設置,具體使用下面再進行介紹。在請求頭里的作用可自行百度。
解決了身份的判斷了,就剩下解決退出登錄的通知了。
上面也說了,如果是直接使用拼接參數的方法是可以驗證是否登錄過期的,但是對二級頁面是不生效的,因為二級頁面是沒有進行拼接的,但是如果我們的二級頁面也進行了拼接呢?是否可以正常驗證呢?
下面我們使用的就是在所有的二級或者三級等頁面上都拼接上我們的token:
在介紹解決方法之前先介紹幾個方法:
@Nullable
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
return super.shouldInterceptRequest(view, request);
}
@Nullable
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
return super.shouldInterceptRequest(view, url);
}
方法一shouldInterceptRequest(WebView view, WebResourceRequest request)和方法二shouldInterceptRequest(WebView view, String url)其實左右是一樣的,但是方法二在在API級別21中已棄用。但是我們未來兼容版本,所以兩方法還是都要使用。


上圖是Google的官方文檔,我們可以知道,在h5中發(fā)起的所有的加載資源的url,都會再此方法中攔截,然后我們攔截到所以得url進行我們需要的操作。所以在所有的二級、三級等頁面拼接參數就在此方法中拼接。
同時再看兩個方法:
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
return super.shouldOverrideUrlLoading(view, request);
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return super.shouldOverrideUrlLoading(view, url);
}


在這里,我們可以處理重定向,變成我們需要顯示的效果,具體的使用可就不詳細介紹了。主要是shouldOverrideUrlLoading()方法的使用介紹。
解決方案:
1、修改user-agent
在webview中,提供了一個方法setUserAgentString(),可以修改user-agent,使用方法如下:
mWebView.getSettings().setUserAgentString(mWebView.getSettings().getUserAgentString().concat("Android-APP"));
Android-APP就是配置特殊字符串,服務端可以根據你的user-agent包含了Android-APP來判斷你是使用app進行訪問的。
但是在設置user-agent的時候,使用一下設置方法;
mWebView.getSettings().setUserAgentString(mWebView.getSettings().getUserAgentString()+"Android-APP");
這樣設置的話服務端怎么都拿不到Android-APP,這個問題我還沒搞明白是這么回事。有知道的朋友可以幫忙解惑一下,非常感謝?。?!
第一種設置方法就是在user-agent的基礎上在后面拼接上Android-APP,這樣app訪問的話,服務端就會知道是app訪問的,就會想要對應的操作。
2、拼接參數
/**
*
* @param view
* @param request
* @return
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, final WebResourceRequest request) {
if (request != null && request.getUrl() != null && request.getMethod().equalsIgnoreCase("get")) {
String scheme = request.getUrl().getScheme().trim();
if (scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https")) {
if (request.getUrl().toString().contains(".html")) {
try {
LogUtil.e("------->" + request.getUrl().toString());
URL url = new URL(injectIsParams(request.getUrl().toString()));
URLConnection connection = url.openConnection();
if (connection.getInputStream().toString().length() < 120) {
String value = IOUtils.toString(connection.getInputStream(), "UTF-8");
LogUtil.e(value);
if (value.startsWith("{")) {
HttpResult httpResult = JSONObject.parseObject(value, HttpResult.class);
if (httpResult != null) {
LogUtil.e(httpResult.toString());
if (Constants.LOGIN_OUT_CODE.equals(httpResult.getCode())) {
LoginActivity.startAction(getActivity());
SPUtils.put(getActivity(), Constants.ACCESS_TOKEN, "");
getActivity().finish();
}
}
}
} else {
connection.getInputStream().close();
}
return null;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return null;
}
/**
*
* @param view
* @param url
* @return
*/
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
if (url.contains(".html")) {
try {
URL url1 = new URL(injectIsParams(url));
URLConnection connection = url1.openConnection();
if (connection.getInputStream().toString().length() < 120) {
String value = IOUtils.toString(connection.getInputStream(), "UTF-8");
LogUtil.e(value);
if (value.startsWith("{")) {
HttpResult httpResult = JSONObject.parseObject(value, HttpResult.class);
if (httpResult != null) {
LogUtil.e(httpResult.toString());
if (Constants.LOGIN_OUT_CODE.equals(httpResult.getCode())) {
LoginActivity.startAction(getActivity());
SPUtils.put(getActivity(), Constants.ACCESS_TOKEN, "");
getActivity().finish();
}
}
}
} else {
connection.getInputStream().close();
}
return null;
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 注入參數
*
* @param url
* @return
*/
public static String injectIsParams(String url) {
if (url != null && !url.contains("app=true&access_token=")) {
if (url.contains("?")) {
return url + "&app=true&access_token=" + SPUtils.get(App.getInstance().getApplicationContext(), Constants.ACCESS_TOKEN, "");
} else {
return url + "?app=true&access_token=" + SPUtils.get(App.getInstance().getApplicationContext(), Constants.ACCESS_TOKEN, "");
}
} else {
return url;
}
}
因為在shouldInterceptRequest()中攔截的是所有的加載資源文件的url,想加載圖片,加載視頻,加載js等url都會再此攔截,所以我們拼接參數的話,是要過濾掉這些的,我這里只要是包含了.html的url都進行參數拼接。
URL url = new URL(injectIsParams(request.getUrl().toString()));
URLConnection connection = url.openConnection();
這里是對進行了拼接參數的url進行連接,連接完成之后,我們要獲取頁面的時間,使用一下方法去獲?。?/p>
connection.getInputStream()
以上的方法獲取的是整個頁面的數據,如果是網頁的話,會把整個網頁的代碼獲取下來,但是我們需要的并不是要網頁的代碼,我們是要獲取登錄失敗的消息。
在此,我們已服務端協商,在token失效后,給我們返回跟接口一樣的json字符串,如果是處于登錄失效的時候,我們使用connection.getInputStream()獲取的就是一串json字符串,因為token并不是都是過期的,所以connection.getInputStream()獲取的可以是一個網頁的代碼,這就需要我們進行過濾了。
json字符串是以大括號開始的,并且以大括號結束,這樣我們就可以區(qū)分是代碼還是json字符串了。
拿到json字符串之后就進行解析,執(zhí)行我們的退出登錄操作。至此,完美解決token失效的問題?。?!
下面就貼出整個頁面的代碼,如果有需要的可以去除錯誤部分,畢竟是從項目中抽出來的,只是做一個參考作用:
/**
* @author Administrator
*/
public class WebViewActivity extends BaseAbstractSimpleActivity implements IActivityStatusBar {
private String url = "";
private AgentWeb mAgentWeb;
private LinearLayout mLinearLayoutWebView;
private DownloadingService mDownloadingService;
private WebView mWebView;
private long mTime;
private LinearLayout mLinearLayoutSplash;
private ValueCallback<Uri[]> mUploadCallbackAboveFive;
private ValueCallback<Uri> mUploadMessage;
private final int RESULT_CODE_IMAGE = 1005;
private File userImgFile;
/**
* 請求開啟定位
*/
public static int REQUEST_CODE_ENABLE_LOCATION = 100;
public static int REQUEST_CODE_ACCESS_LOCATION_PERMISSION = 101;
private LocationWebChromeClient mWebChromeClient;
public static void startAction(Activity context, @NonNull String url) {
Intent intent = new Intent(context, WebViewActivity.class);
intent.putExtra("url", url);
context.startActivityForResult(intent, Constants.LOGIN_OUT_REQUEST);
}
@Override
protected int getLayout() {
return R.layout.activity_web_view;
}
@Override
protected void initEventAndData() {
mWebChromeClient = new LocationWebChromeClient();
mAgentWeb = AgentWeb.with(this)
.setAgentWebParent(mLinearLayoutWebView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))
.useDefaultIndicator(-1, 3)
.setAgentWebWebSettings(getSettings())
.setWebViewClient(mWebViewClient)
.setWebChromeClient(mWebChromeClient)
.setSecurityType(AgentWeb.SecurityType.STRICT_CHECK)
.setMainFrameErrorView(R.layout.agentweb_error_page, -1)
.setOpenOtherPageWays(DefaultWebClient.OpenOtherPageWays.DISALLOW)
.interceptUnkownUrl()
.createAgentWeb()
.ready()
.go(url);
mWebView = mAgentWeb.getWebCreator().getWebView();
mAgentWeb.getJsInterfaceHolder().addJavaObject("aaa", new JavaScriptInterface(this));
if (url.contains("<html>")) {
mWebView.loadDataWithBaseURL(null, url.toString(), "text/html", "utf-8", null);
}
mAgentWeb.getWebCreator().getWebView().setDownloadListener(new DownloadListener() {
@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
Uri uri = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
});
}
@Override
protected void initView() {
url = getIntent().getStringExtra("url");
mLinearLayoutWebView = findViewById(R.id.linear_layout_webview);
new RxPermissions(this)
.requestEach(Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE)
.subscribe(new SubscriberCallBack<>(new ApiCallback<Permission>() {
@Override
public void onSuccess(Permission model) {
if (model.granted) {
} else {
Toast.makeText(WebViewActivity.this, "請允許打開需要的權限", Toast.LENGTH_SHORT).show();
finish();
}
}
@Override
public void onFailure(String msg) {
}
}));
}
/**
* @return IAgentWebSettings
*/
public IAgentWebSettings getSettings() {
return new AbsAgentWebSettings() {
private AgentWeb mAgentWeb;
@Override
protected void bindAgentWebSupport(AgentWeb agentWeb) {
this.mAgentWeb = agentWeb;
}
/**
* AgentWeb 4.0.0 內部刪除了 DownloadListener 監(jiān)聽 ,以及相關API ,將 Download 部分完全抽離出來獨立一個庫,
* 如果你需要使用 AgentWeb Download 部分 , 請依賴上 compile 'com.just.agentweb:download:4.0.0 ,
* 如果你需要監(jiān)聽下載結果,請自定義 AgentWebSetting , New 出 DefaultDownloadImpl,傳入DownloadListenerAdapter
* 實現進度或者結果監(jiān)聽,例如下面這個例子,如果你不需要監(jiān)聽進度,或者下載結果,下面 setDownloader 的例子可以忽略。
* @param webView
* @param downloadListener
* @return WebListenerManager
*/
@Override
public WebListenerManager setDownloader(WebView webView, android.webkit.DownloadListener downloadListener) {
return super.setDownloader(webView,
DefaultDownloadImpl
.create((Activity) webView.getContext(),
webView,
mDownloadListenerAdapter,
mDownloadListenerAdapter,
this.mAgentWeb.getPermissionInterceptor()));
}
};
}
protected DownloadListenerAdapter mDownloadListenerAdapter = new DownloadListenerAdapter() {
@Override
public boolean onStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength, AgentWebDownloader.Extra extra) {
extra.setOpenBreakPointDownload(true)
.setIcon(R.drawable.ic_file_download_black_24dp)
.setConnectTimeOut(6000)
.setBlockMaxTime(2000)
.setDownloadTimeOut(60L * 5L * 1000L)
.setAutoOpen(true)
.setForceDownload(false);
return false;
}
@Override
public void onBindService(String url, DownloadingService downloadingService) {
super.onBindService(url, downloadingService);
mDownloadingService = downloadingService;
LogUtils.i("TAG", "onBindService:" + url + " DownloadingService:" + downloadingService);
}
@Override
public void onUnbindService(String url, DownloadingService downloadingService) {
super.onUnbindService(url, downloadingService);
mDownloadingService = null;
LogUtils.i("TAG", "onUnbindService:" + url);
}
@Override
public void onProgress(String url, long loaded, long length, long usedTime) {
int mProgress = (int) ((loaded) / Float.valueOf(length) * 100);
LogUtils.i("TAG", "onProgress:" + mProgress);
super.onProgress(url, loaded, length, usedTime);
}
@Override
public boolean onResult(String path, String url, Throwable throwable) {
if (null == throwable) {
//do you work
} else {
}
return false;
}
};
private WebViewClient mWebViewClient = new WebViewClient() {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
LogUtil.e("加載地址--》" + url);
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
}
/**
*
* @param view
* @param request
* @return
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, final WebResourceRequest request) {
if (request != null && request.getUrl() != null && request.getMethod().equalsIgnoreCase("get")) {
String scheme = request.getUrl().getScheme().trim();
if (scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https")) {
if (request.getUrl().toString().contains(".html")) {
try {
LogUtil.e("------->" + request.getUrl().toString());
URL url = new URL(injectIsParams(request.getUrl().toString()));
URLConnection connection = url.openConnection();
if (connection.getInputStream().toString().length() < 120) {
String value = IOUtils.toString(connection.getInputStream(), "UTF-8");
LogUtil.e(value);
if (value.startsWith("{")) {
HttpResult httpResult = JSONObject.parseObject(value, HttpResult.class);
if (httpResult != null) {
LogUtil.e(httpResult.toString());
if (Constants.LOGIN_OUT_CODE.equals(httpResult.getCode())) {
setResult(LOGIN_OUT_RESULT);
finish();
}
}
}
} else {
connection.getInputStream().close();
}
return null;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return null;
}
/**
*
* @param view
* @param url
* @return
*/
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
if (url.contains(".html")) {
try {
URL url1 = new URL(injectIsParams(url));
URLConnection connection = url1.openConnection();
if (connection.getInputStream().toString().length() < 120) {
String value = IOUtils.toString(connection.getInputStream(), "UTF-8");
LogUtil.e(value);
if (value.startsWith("{")) {
HttpResult httpResult = JSONObject.parseObject(value, HttpResult.class);
if (httpResult != null) {
LogUtil.e(httpResult.toString());
if (Constants.LOGIN_OUT_CODE.equals(httpResult.getCode())) {
setResult(LOGIN_OUT_RESULT);
finish();
}
}
}
} else {
connection.getInputStream().close();
}
return null;
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
};
/**
* 注入參數
*
* @param url
* @return
*/
public static String injectIsParams(String url) {
if (url != null && !url.contains("app=true&access_token=")) {
if (url.contains("?")) {
return url + "&app=true&access_token=" + SPUtils.get(App.getInstance().getApplicationContext(), Constants.ACCESS_TOKEN, "");
} else {
return url + "?app=true&access_token=" + SPUtils.get(App.getInstance().getApplicationContext(), Constants.ACCESS_TOKEN, "");
}
} else {
return url;
}
}
@Override
public int getStatusBarColor() {
return ContextCompat.getColor(this, R.color.colorPrimary);
}
@Override
protected void onResume() {
mAgentWeb.getWebLifeCycle().onResume();
super.onResume();
}
@Override
protected void onPause() {
mAgentWeb.getWebLifeCycle().onPause();
super.onPause();
}
@Override
protected void onDestroy() {
AgentWebConfig.clearDiskCache(this);
mWebView.clearCache(true);
mAgentWeb.getWebLifeCycle().onDestroy();
super.onDestroy();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.e("TAG", "結果碼-->" + resultCode + "\n請求碼--》" + requestCode);
if (resultCode == 0) {
if (mUploadCallbackAboveFive != null) {
mUploadCallbackAboveFive.onReceiveValue(null);
mUploadCallbackAboveFive = null;
}
if (mUploadMessage != null) {
mUploadMessage.onReceiveValue(null);
mUploadMessage = null;
}
return;
}
switch (requestCode) {
//拍照
case GET_PICTURE_TAKE_PHOTO:
userImgFile = ImageSelector.cutPicture(this, userImgFile);
break;
//選擇照片
case GET_PICTURE_SELECT_PHOTO:
userImgFile = ImageSelector.getPhotoFromIntent(data, this);
userImgFile = ImageSelector.cutPicture(this, userImgFile);
break;
//裁剪照片
case CUT_PHOTO:
if (resultCode == Activity.RESULT_OK) {
compressImage(userImgFile);
}
break;
default:
break;
}
}
/**
* 壓縮圖片
*
* @param file
*/
public void compressImage(File file) {
List<File> list = new ArrayList<>();
list.add(file);
BitmapUtil.compressFiles(list, new ICompressImageResponse() {
@Override
public void onSuccess(List<File> images) {
File imgFile = images.get(0);
Uri result = ImageSelector.toURI(WebViewActivity.this, imgFile);
Log.e("TAG", "文件URI-->" + result);
if (null != mUploadMessage && null == mUploadCallbackAboveFive) {
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
if (null == mUploadMessage && null != mUploadCallbackAboveFive) {
mUploadCallbackAboveFive.onReceiveValue(new Uri[]{result});
mUploadCallbackAboveFive = null;
}
}
@Override
public void onMarch() {
}
@Override
public void onFail() {
}
@Override
public void onFinish() {
}
});
}
/**
* 顯示圖片選擇器
*
* @param context
* @param view
*/
public void showSelector(final Activity context, View view) {
PopupGetPictureView popupGetPictureView = new PopupGetPictureView(context, new
PopupGetPictureView.GetPicture() {
@Override
public void takePhoto(View v) {
if (PermissionUtils.checkTakePhotoPermission(context)) {
userImgFile = ImageSelector.takePicture(context, GET_PICTURE_TAKE_PHOTO);
}
}
@Override
public void selectPhoto(View v) {
if (PermissionUtils.checkAlbumStroagePermission(context)) {
ImageSelector.photoPick(context, GET_PICTURE_SELECT_PHOTO);
}
}
@Override
public void cancel(PopupWindow popupWindow) {
if (popupWindow.isShowing()) {
if (mUploadCallbackAboveFive != null) {
mUploadCallbackAboveFive.onReceiveValue(null);
mUploadCallbackAboveFive = null;
}
if (mUploadMessage != null) {
mUploadMessage.onReceiveValue(null);
mUploadMessage = null;
}
popupWindow.dismiss();
}
}
});
popupGetPictureView.showPop(view);
}
class LocationWebChromeClient extends WebChromeClient {
private LocationWebChromeClientListener mLocationWebChromeClientListener;
private GeolocationPermissions.Callback mGeolocationPermissionsCallback;
private String mOrigin;
private boolean mShowRequestPermissionRationale = false;
public LocationWebChromeClient() {
mLocationWebChromeClientListener = new LocationWebChromeClientListener() {
@Override
public boolean onReturnFromLocationSetting(int requestCode) {
if (requestCode == REQUEST_CODE_ENABLE_LOCATION) {
if (mGeolocationPermissionsCallback != null) {
if (isEnabledLocationFunction()) {
mGeolocationPermissionsCallback.invoke(mOrigin, true, true);
} else {
//顯然,從設置界面回來還沒有開啟定位服務,肯定是要拒絕定位了
Toast.makeText(WebViewActivity.this, "您拒絕了定位請求", Toast.LENGTH_SHORT).show();
mGeolocationPermissionsCallback.invoke(mOrigin, false, false);
}
}
return true;
}
return false;
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
boolean pass = true;
for (Integer result : grantResults) {
if (result == PackageManager.PERMISSION_DENIED) {
pass = false;
break;
}
}
if (pass) {
onAccessLocationPermissionGranted();
} else {
onAccessLocationPermissionRejected();
}
}
public void onAccessLocationPermissionGranted() {
doJudgeLocationServiceEnabled();
}
public void onAccessLocationPermissionRejected() {
if (mShowRequestPermissionRationale) {
Toast.makeText(WebViewActivity.this, "您拒絕了定位請求", Toast.LENGTH_SHORT).show();
mGeolocationPermissionsCallback.invoke(mOrigin, false, false);
} else {
doRequestAppSetting();
}
}
};
}
@Override
public void onProgressChanged(WebView view, int newProgress) {
//do you work
}
@SuppressWarnings("unused")
public void openFileChooser(ValueCallback<Uri> uploadMsg, String AcceptType, String capture) {
this.openFileChooser(uploadMsg);
}
@SuppressWarnings("unused")
public void openFileChooser(ValueCallback<Uri> uploadMsg, String AcceptType) {
this.openFileChooser(uploadMsg);
}
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
mUploadMessage = uploadMsg;
showSelector(WebViewActivity.this, mWebView);
}
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
mUploadCallbackAboveFive = filePathCallback;
showSelector(WebViewActivity.this, mWebView);
return true;
}
private void doRequestAppSetting() {
AlertDialog.Builder builder = new AlertDialog.Builder(WebViewActivity.this);
builder.setTitle("溫馨提示");
builder.setMessage(String.format("您禁止了應用獲取當前位置的權限,是否前往開啟?", mOrigin));
builder.setPositiveButton("是", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent mIntent = new Intent();
mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= 9) {
mIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
mIntent.setData(Uri.fromParts("package", getPackageName(), null));
} else if (Build.VERSION.SDK_INT <= 8) {
mIntent.setAction(Intent.ACTION_VIEW);
mIntent.setClassName("com.android.settings", "com.android.setting.InstalledAppDetails");
mIntent.putExtra("com.android.settings.ApplicationPkgName", getPackageName());
}
startActivity(mIntent);
}
});
builder.setNegativeButton("否", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
mGeolocationPermissionsCallback.invoke(mOrigin, false, false);
}
});
builder.create().show();
}
public LocationWebChromeClientListener getLocationWebChromeClientListener() {
return mLocationWebChromeClientListener;
}
@Override
public void onGeolocationPermissionsHidePrompt() {
super.onGeolocationPermissionsHidePrompt();
}
@Override
public void
onGeolocationPermissionsShowPrompt(final String origin, final GeolocationPermissions.Callback geolocationPermissionsCallback) {
this.mOrigin = origin;
this.mGeolocationPermissionsCallback = geolocationPermissionsCallback;
//是否擁有定位權限
if (hasAccessLocationPermission()) {
doJudgeLocationServiceEnabled();
} else {
//請求定位
requestAccessLocationPermission();
}
}
private void doJudgeLocationServiceEnabled() {
//是否開啟定位
if (isEnabledLocationFunction()) {
AlertDialog.Builder builder = new AlertDialog.Builder(WebViewActivity.this);
builder.setTitle("溫馨提示");
builder.setMessage(String.format("網站%s,正在請求使用您當前的位置,是否許可?", mOrigin));
builder.setPositiveButton("許可", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
mGeolocationPermissionsCallback.invoke(mOrigin, true, true);
}
});
builder.setNegativeButton("不許可", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
mGeolocationPermissionsCallback.invoke(mOrigin, false, false);
}
});
builder.create().show();
} else {
//請求開啟定位功能
requestEnableLocationFunction(mOrigin, mGeolocationPermissionsCallback);
}
}
/**
* 請求開啟定位服務
*/
private void requestEnableLocationFunction(final String origin, final GeolocationPermissions.Callback geolocationPermissionsCallback) {
AlertDialog.Builder builder = new AlertDialog.Builder(WebViewActivity.this);
builder.setTitle("溫馨提示");
builder.setMessage(String.format("網站%s,正在請求使用您當前的位置,是否前往開啟定位服務?", origin));
builder.setPositiveButton("前往開啟", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivityForResult(intent, REQUEST_CODE_ENABLE_LOCATION);
}
});
builder.setNegativeButton("拒絕", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
geolocationPermissionsCallback.invoke(origin, false, false);
}
});
builder.create().show();
}
private boolean isEnabledLocationFunction() {
int locationMode = 0;
String locationProviders;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
locationMode = Settings.Secure.getInt(WebViewActivity.this.getContentResolver(), Settings.Secure.LOCATION_MODE);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
return false;
}
return locationMode != Settings.Secure.LOCATION_MODE_OFF;
} else {
locationProviders = Settings.Secure.getString(WebViewActivity.this.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
return !TextUtils.isEmpty(locationProviders);
}
}
private boolean hasAccessLocationPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED;
} else {
return ContextCompat.checkSelfPermission(WebViewActivity.this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED;
}
}
private void requestAccessLocationPermission() {
// 是否要顯示問什么要獲取權限的解釋界面
/**
* 什么情況下 shouldShowRequestPermissionRationale會返回true?
* - 首次請求權限,但是用戶禁止了,但是沒有勾選“禁止后不再詢問”,這樣,之后的請求都會返回true
* 什么情況下,shouldShowRequestPermissionRationale會返回false?
* - 首次請求權限或者請求權限時,用戶勾選了“禁止后不再詢問”,之后的請求都會返回false
*/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
//請求過定位權限,但是被用戶拒絕了(但是沒有勾選“禁止后不再詢問”)
// 顯示解釋權限用途的界面,然后再繼續(xù)請求權限
mShowRequestPermissionRationale = true;
} else {
mShowRequestPermissionRationale = false;
}
} else {
mShowRequestPermissionRationale = false;
}
AlertDialog.Builder builder = new AlertDialog.Builder(WebViewActivity.this);
builder.setTitle("溫馨提示");
builder.setMessage(String.format("網站%s,正在請求使用您當前的位置,是否許可應用獲取當前位置權限?", mOrigin));
builder.setPositiveButton(" 是 ", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_CODE_ACCESS_LOCATION_PERMISSION);
} else {
//額,版本低,正常情況下,安裝默認許可,然鵝,國產ROM各種魔改,有闊輪提前實現了單獨授權
doRequestAppSetting();
}
}
});
builder.setNegativeButton(" 否 ", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
mGeolocationPermissionsCallback.invoke(mOrigin, false, false);
}
});
builder.create().show();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (mWebChromeClient != null && mWebChromeClient.getLocationWebChromeClientListener() != null) {
mWebChromeClient.getLocationWebChromeClientListener().onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
interface LocationWebChromeClientListener {
/**
* 用戶從開啟定位頁面回來了
*/
boolean onReturnFromLocationSetting(int requestCode);
/**
* 請求權限結果
*/
void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults);
}
private final class JavaScriptInterface {
public Activity activity;
public JavaScriptInterface(Activity activity) {
this.activity = activity;
}
@JavascriptInterface
public void scanCode() {
}
@JavascriptInterface
public void androidGoBack() {
activity.finish();
}
@JavascriptInterface
public void call(String phone) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:" + phone));
//開啟系統撥號器
activity.startActivity(intent);
}
}
}
特別說明:使用shouldInterceptRequest()方法拼接參數,并不是修改了訪問的網頁url,只不過是在加載資源的時候對頁面進行了一層是否登陸的驗證,驗證通過則進行加載頁面,不通過執(zhí)行相對于的操作。如果頁面有重定向的,則需要在處理重定向的方法中進行驗證,驗證成功,則加載重定向,驗證不成功,不加載,然后執(zhí)行我們的操作即可。
以上使用的webview是AgentWeb,導入依賴方法:
//agentweb 下載文件、選擇文件 implementation 'com.just.agentweb:download:4.0.2' // (可選) implementation 'com.just.agentweb:agentweb:4.0.2' implementation 'com.just.agentweb:filechooser:4.0.2'
使用的解析庫是阿里fastJson解析庫:
//阿里fastJson解析庫
implementation 'com.alibaba:fastjson:1.2.55'
使用的io裝換庫:
// https://mvnrepository.com/artifact/commons-io/commons-io
implementation group: 'commons-io', name: 'commons-io', version: '2.6'
以上這篇webview添加參數與修改請求頭的user-agent實例就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Android使用HorizontalScrollView實現水平滾動
這篇文章主要為大家詳細介紹了Android使用HorizontalScrollView實現水平滾動,并點擊有相應的反應效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-11-11
Android 6.0 無法在SD卡創(chuàng)建目錄的方法
今天小編就為大家分享一篇Android 6.0 無法在SD卡創(chuàng)建目錄的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08

