1.webview加载视频,横竖屏切换
Activity内嵌WebView,加载有视频的页面时,视频无法全屏播放。全屏按钮不显示或者灰显。
页面布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff">
<include
android:id="@+id/include_toolbar"
layout="@layout/toolbar"/>
<FrameLayout
android:id="@+id/fl_video"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
android:layout_below="@+id/include_toolbar"/>
<WebView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/webView"
android:layout_below="@+id/include_toolbar"
android:layout_centerHorizontal="true"/>
<LinearLayout
android:id="@+id/llty_pbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="gone"
android:gravity="center"
android:orientation="horizontal">
<ProgressBar
android:id="@+id/pbar_more"
android:layout_width="32dp"
android:layout_height="32dp"/>
<TextView
android:id="@+id/loading_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:text="加载中..."
android:textSize="14sp"/>
</LinearLayout>
</RelativeLayout>
主要就是fl_video和webView,这两个是需要横竖屏切换的。WebView在点击全屏按钮后,会调用onShowCustomView方法。而全屏的视频会在其参数View view中进行渲染。在onShowCustomView触发后,将其view传入fl_video,使APP横屏,fl_video全屏显示。
先设置硬件加速和横竖屏切换
<activity
android:name=".activity.WebViewActivity"
android:screenOrientation="portrait"
android:configChanges="keyboardHidden|orientation|screenSize"
android:hardwareAccelerated = "true"/>
WebViewActivity里相关代码
private FrameLayout mLayout; // 用来显示视频的布局
private View mCustomView; //用于全屏渲染视频的View
private WebChromeClient.CustomViewCallback mCustomViewCallback;
...
public class MyWebChromeClient extends WebChromeClient
{
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result)
{
Log.i(TAG, "onJsAlert: " + message);
return super.onJsAlert(view, url, message, result);
}
@Override
public boolean onJsConfirm(WebView view, String url, String message, JsResult result)
{
Log.i(TAG, "onJsConfirm: " + message);
return super.onJsConfirm(view, url, message, result);
}
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result)
{
Log.i(TAG, "onJsPrompt: " + message);
return super.onJsPrompt(view, url, message, defaultValue, result);
}
@Override
public void onReceivedTitle(WebView view, String title)
{
super.onReceivedTitle(view, title);
}
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
super.onShowCustomView(view, callback);
//如果view 已经存在,则隐藏
if (mCustomView != null) {
callback.onCustomViewHidden();
return;
}
mCustomView = view;
mCustomView.setVisibility(View.VISIBLE);
mCustomViewCallback = callback;
mLayout.addView(mCustomView);
mLayout.setVisibility(View.VISIBLE);
mLayout.bringToFront();
//设置横屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
@Override
public void onHideCustomView() {
super.onHideCustomView();
if (mCustomView == null) {
return;
}
mCustomView.setVisibility(View.GONE);
mLayout.removeView(mCustomView);
mCustomView = null;
mLayout.setVisibility(View.GONE);
try {
mCustomViewCallback.onCustomViewHidden();
} catch (Exception e) {
}
// titleView.setVisibility(View.VISIBLE);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//竖屏
}
}
...
/**
* 横竖屏切换监听
*/
@Override
public void onConfigurationChanged(Configuration config) {
super.onConfigurationChanged(config);
switch (config.orientation) {
case Configuration.ORIENTATION_LANDSCAPE:
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
toolbar.setVisibility(View.GONE);
break;
case Configuration.ORIENTATION_PORTRAIT:
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
toolbar.setVisibility(View.VISIBLE);
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//清空所有cookie
CookieSyncManager.createInstance(WebViewActivity.this);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeAllCookie();
CookieSyncManager.getInstance().sync();
webView.setWebChromeClient(null);
webView.setWebViewClient(null);
webView.getSettings().setJavaScriptEnabled(false);
webView.clearCache(true);
webView.destroy();
if(receiver!=null){
unregisterReceiver(receiver);
}
}
2.点击视频下载没反应
需要监听setDownloadListener,然后使用系统默认的下载管理器下载
private DownloadCompleteReceiver receiver;
...
webView.setDownloadListener(new DownloadListener() {
@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {
// TODO: 2017-5-6 处理下载事件
downloadBySystem(url,contentDisposition,mimeType);
ToastUtil.showLongToast("正在下载中...");
}
});
if(receiver!=null){
unregisterReceiver(receiver);
}
// 使用
receiver = new DownloadCompleteReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
registerReceiver(receiver, intentFilter);
private void downloadBySystem(String url, String contentDisposition, String mimeType) {
// 指定下载地址
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
// 允许媒体扫描,根据下载的文件类型被加入相册、音乐等媒体库
request.allowScanningByMediaScanner();
// 设置通知的显示类型,下载进行时和完成后显示通知
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
// 设置通知栏的标题,如果不设置,默认使用文件名
// request.setTitle("This is title");
// 设置通知栏的描述
// request.setDescription("This is description");
// 允许在计费流量下下载
request.setAllowedOverMetered(false);
// 允许该记录在下载管理界面可见
request.setVisibleInDownloadsUi(false);
// 允许漫游时下载
request.setAllowedOverRoaming(true);
// 允许下载的网路类型
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
// 设置下载文件保存的路径和文件名
String fileName = URLUtil.guessFileName(url, contentDisposition, mimeType);
Log.d("fileName:{}", fileName);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
// 另外可选一下方法,自定义下载路径
// request.setDestinationUri()
// request.setDestinationInExternalFilesDir()
final DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
// 添加一个下载任务
long downloadId = downloadManager.enqueue(request);
Log.d("downloadId:{}", downloadId+"");
}
private class DownloadCompleteReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent) {
Log.d("onReceive. intent:{}", intent != null ? intent.toUri(0) : null);
if (intent != null) {
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) {
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
Log.d("downloadId:{}", downloadId+"");
DownloadManager downloadManager = (DownloadManager) context.getSystemService(DOWNLOAD_SERVICE);
String type = downloadManager.getMimeTypeForDownloadedFile(downloadId);
Log.d("getMimeTypeForDownloadedFile:{}", type);
if (TextUtils.isEmpty(type)) {
type = "*/*";
}
Uri uri = downloadManager.getUriForDownloadedFile(downloadId);
Log.d("UriForDownloadedFile:{}", uri+"");
if (uri != null) {
Intent handlerIntent = new Intent(Intent.ACTION_VIEW);
handlerIntent.setDataAndType(uri, type);
context.startActivity(handlerIntent);
}
}
}
}
}
别忘了在ondestroy中释放receiver
if(receiver!=null){
unregisterReceiver(receiver);
}
完整代码
public class WebViewActivity extends BaseNeedContactActivity
{
private static final String TAG = WebViewActivity.class.getSimpleName();
public static final String WEBVIEW_TITLE = "webview_title";
public static final String WEBVIEW_URL = "webview_url";
public static final String WEBVIEW_ACTION = "webview_action";
public static final String WEBVIEW_ACTION_PATTEN = "webview_action_patten";
private WebAction action = null;
private String actionPatten = null;
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.webView)
WebView webView = null;
@BindView(R.id.llty_pbar)
LinearLayout llty_pbar;
private String title = "";
private ContactData contactData = null;
private DownloadCompleteReceiver receiver;
private FrameLayout mLayout; // 用来显示视频的布局
private View mCustomView; //用于全屏渲染视频的View
private WebChromeClient.CustomViewCallback mCustomViewCallback;
public static void start(Context context, String title, String url, String iM_ID)
{
Intent intent = new Intent(context, WebViewActivity.class);
intent.putExtra(WEBVIEW_TITLE, title);
intent.putExtra(WEBVIEW_URL, url);
intent.putExtra(Extras.EXTRA_DATA, iM_ID);
context.startActivity(intent);
}
public static void start(Context context, String title, String url, String actionPatten, WebAction action, String iM_ID)
{
Intent intent = new Intent(context, WebViewActivity.class);
intent.putExtra(WEBVIEW_TITLE, title);
intent.putExtra(WEBVIEW_URL, url);
intent.putExtra(WEBVIEW_ACTION_PATTEN, actionPatten);
intent.putExtra(WEBVIEW_ACTION, action);
intent.putExtra(Extras.EXTRA_DATA, iM_ID);
context.startActivity(intent);
}
public static void startForResult(Activity activity, String title, String url, int requestCode, String actionPatten, WebAction action)
{
Intent intent = new Intent(activity, WebViewActivity.class);
intent.putExtra(WEBVIEW_TITLE, title);
intent.putExtra(WEBVIEW_URL, url);
intent.putExtra(WEBVIEW_ACTION_PATTEN, actionPatten);
intent.putExtra(WEBVIEW_ACTION, action);
activity.startActivityForResult(intent, requestCode);
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web_view);
//using butter knife
ButterKnife.bind(this);
mLayout = findViewById(R.id.fl_video);
setToolBar(R.id.toolbar, true);
initWebView();
initData();
}
private void initData()
{
Intent intent = getIntent();
if (intent == null)
{
ToastUtil.showToast("地址不能为空");
return;
}
title = intent.getStringExtra(WEBVIEW_TITLE);
if (TextUtils.isEmpty(title))
{
toolbar.setTitle("");
}
else
{
if (title.contains("("))
{
SpannableStringBuilder builder = new SpannableStringBuilder(title);
AbsoluteSizeSpan span = new AbsoluteSizeSpan(15, true);
builder.setSpan(span, title.indexOf("("), title.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
toolbar.setTitle(builder);
}
else
{
toolbar.setTitle(title);
}
}
action = (WebAction) intent.getSerializableExtra(WEBVIEW_ACTION);
actionPatten = intent.getStringExtra(WEBVIEW_ACTION_PATTEN);
if (action == null || actionPatten == null)
{
action = null;
actionPatten = null;
}
String url = intent.getStringExtra(WEBVIEW_URL);
if (TextUtils.isEmpty(url))
{
ToastUtil.showToast("地址错误,地址不能为空");
return;
}
else
{
webView.loadUrl(url);
llty_pbar.setVisibility(View.VISIBLE);
}
String account = intent.getStringExtra(Extras.EXTRA_DATA);
if(!TextUtils.isEmpty(account))
{
contactData = MyContactManager.getInstance().getContactByIm(account);
}
}
private void initWebView()
{
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
// 设置字符编码
webSettings.setDefaultTextEncodingName("utf-8");
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings.setAllowFileAccess(true);
webSettings.setLoadsImagesAutomatically(true);
// webSettings.setAppCacheEnabled(true);
// webSettings.setBlockNetworkImage(true);
// webSettings.setGeolocationEnabled(true);
webSettings.setSupportZoom(true);
// webSettings.setBuiltInZoomControls(true);
// webSettings.setPluginsEnabled(true);
//webView.addJavascriptInterface(this, "AppInterface");
webView.setWebChromeClient(new MyWebChromeClient());
webView.setWebViewClient(new MyWebViewClient());
webView.setDownloadListener(new DownloadListener() {
@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {
// TODO: 2017-5-6 处理下载事件
downloadBySystem(url,contentDisposition,mimeType);
ToastUtil.showLongToast("正在下载中...");
}
});
if(receiver!=null){
unregisterReceiver(receiver);
}
// 使用
receiver = new DownloadCompleteReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
registerReceiver(receiver, intentFilter);
}
private void downloadBySystem(String url, String contentDisposition, String mimeType) {
// 指定下载地址
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
// 允许媒体扫描,根据下载的文件类型被加入相册、音乐等媒体库
request.allowScanningByMediaScanner();
// 设置通知的显示类型,下载进行时和完成后显示通知
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
// 设置通知栏的标题,如果不设置,默认使用文件名
// request.setTitle("This is title");
// 设置通知栏的描述
// request.setDescription("This is description");
// 允许在计费流量下下载
request.setAllowedOverMetered(false);
// 允许该记录在下载管理界面可见
request.setVisibleInDownloadsUi(false);
// 允许漫游时下载
request.setAllowedOverRoaming(true);
// 允许下载的网路类型
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
// 设置下载文件保存的路径和文件名
String fileName = URLUtil.guessFileName(url, contentDisposition, mimeType);
Log.d("fileName:{}", fileName);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
// 另外可选一下方法,自定义下载路径
// request.setDestinationUri()
// request.setDestinationInExternalFilesDir()
final DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
// 添加一个下载任务
long downloadId = downloadManager.enqueue(request);
Log.d("downloadId:{}", downloadId+"");
}
private class DownloadCompleteReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent) {
Log.d("onReceive. intent:{}", intent != null ? intent.toUri(0) : null);
if (intent != null) {
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) {
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
Log.d("downloadId:{}", downloadId+"");
DownloadManager downloadManager = (DownloadManager) context.getSystemService(DOWNLOAD_SERVICE);
String type = downloadManager.getMimeTypeForDownloadedFile(downloadId);
Log.d("getMimeTypeForDownloadedFile:{}", type);
if (TextUtils.isEmpty(type)) {
type = "*/*";
}
Uri uri = downloadManager.getUriForDownloadedFile(downloadId);
Log.d("UriForDownloadedFile:{}", uri+"");
if (uri != null) {
Intent handlerIntent = new Intent(Intent.ACTION_VIEW);
handlerIntent.setDataAndType(uri, type);
context.startActivity(handlerIntent);
}
}
}
}
}
public class MyWebViewClient extends WebViewClient
{
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
// 如果不是url地址 我就不调用此跳转页面方法
if (null != url && !"".equals(url) && (url.indexOf("/") < 0))
{
return false;
}
if (actionPatten != null && url.lastIndexOf(actionPatten) != -1)
{
if (title.equals("随访表单"))
{
if (ManagerPlanDetailActivity.instance != null)
{
ManagerPlanDetailActivity.instance.finish();
}
if (VisitFormActivity.instance != null)
{
VisitFormActivity.instance.finish();
}
finish();
}
else
{
action.doAction(WebViewActivity.this);
}
return true;
}
try
{
view.loadUrl(url);
}
catch (Exception e)
{
e.printStackTrace();
}
return true;
}
@Override
public void onPageFinished(WebView view, String url)
{
Log.i(TAG, "onPageFinished: url=" + url);
llty_pbar.setVisibility(View.GONE);
}
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)
{
//handler.cancel(); // Android默认的处理方式
handler.proceed(); // 接受所有网站的证书
//handleMessage(Message msg); // 进行其他处理
}
}
public class MyWebChromeClient extends WebChromeClient
{
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result)
{
Log.i(TAG, "onJsAlert: " + message);
return super.onJsAlert(view, url, message, result);
}
@Override
public boolean onJsConfirm(WebView view, String url, String message, JsResult result)
{
Log.i(TAG, "onJsConfirm: " + message);
return super.onJsConfirm(view, url, message, result);
}
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result)
{
Log.i(TAG, "onJsPrompt: " + message);
return super.onJsPrompt(view, url, message, defaultValue, result);
}
@Override
public void onReceivedTitle(WebView view, String title)
{
super.onReceivedTitle(view, title);
}
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
super.onShowCustomView(view, callback);
//如果view 已经存在,则隐藏
if (mCustomView != null) {
callback.onCustomViewHidden();
return;
}
mCustomView = view;
mCustomView.setVisibility(View.VISIBLE);
mCustomViewCallback = callback;
mLayout.addView(mCustomView);
mLayout.setVisibility(View.VISIBLE);
mLayout.bringToFront();
//设置横屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
@Override
public void onHideCustomView() {
super.onHideCustomView();
if (mCustomView == null) {
return;
}
mCustomView.setVisibility(View.GONE);
mLayout.removeView(mCustomView);
mCustomView = null;
mLayout.setVisibility(View.GONE);
try {
mCustomViewCallback.onCustomViewHidden();
} catch (Exception e) {
}
// titleView.setVisibility(View.VISIBLE);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//竖屏
}
}
public static interface WebAction extends Serializable
{
public void doAction(WebViewActivity webViewActivity);
}
@Override
protected ContactData getCurrContactData()
{
return contactData;
}
/**
* 横竖屏切换监听
*/
@Override
public void onConfigurationChanged(Configuration config) {
super.onConfigurationChanged(config);
switch (config.orientation) {
case Configuration.ORIENTATION_LANDSCAPE:
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
toolbar.setVisibility(View.GONE);
break;
case Configuration.ORIENTATION_PORTRAIT:
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
toolbar.setVisibility(View.VISIBLE);
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//清空所有cookie
CookieSyncManager.createInstance(WebViewActivity.this);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeAllCookie();
CookieSyncManager.getInstance().sync();
webView.setWebChromeClient(null);
webView.setWebViewClient(null);
webView.getSettings().setJavaScriptEnabled(false);
webView.clearCache(true);
webView.destroy();
if(receiver!=null){
unregisterReceiver(receiver);
}
}
}
参考文章
三种方式让 Android WebView 支持文件下载
Android WebView 视频播放,全屏按钮不显示或灰显解决方案