最近几年随着h5的强势崛起,越来越多的公司运用h5开发或者采用h5与android的混合开发,前端时间公司就碰到了一个h5就和android交互的项目,本人也是在摸索中一次次改进,废话不说了直接上代码:
1.建议使用new Webview构建webview对象而不是直接在布局xml文件中运用
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:fitsSystemWindows="true"
android:background="@color/loginbg"
android:layout_height="match_parent">
android:id="@+id/ll_web"
android:orientation="vertical"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp">
2.new出webview对象,并通过websetting 类设置
webView = new WebView(MainActivity.this); webView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); ll_web.addView(webView); WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true);
3.webview加载h5
webView.loadUrl(surl);
4.将java方法暴露给h5代码,当webview界面上触发某个事件后调取java方法(我这里是因为h5触发java两个不同的方法所以下面暴露两个java方法给h5
webView.addJavascriptInterface(new Lateralinterface(MainActivity.this), "wst"); webView.addJavascriptInterface(new LoginSucinterface(MainActivity.this), "log");
以下是我定义的其中一个给h5调取的方法写法
public class Lateralinterface { private Context context; private UpdateUi updateui; private Loginout loginout; public Lateralinterface(Context context) { this.context = context; updateui= (UpdateUi) context; loginout= (Loginout) context; } /** * 侧滑 * @param type */ @JavascriptInterface public void showToast(String type){ if(!TextUtils.isEmpty(type)){ updateui.showOrhide(type); } } public interface UpdateUi{ void showOrhide(String type); } /** * 退出 */ @JavascriptInterface public void loginOut(){ loginout.loginoutact(); } public interface Loginout{ void loginoutact(); } }
5.java代码调取h5的方法并传递值给h5(一定要等到h5界面加载完成后才能调取h5的方法,否者调取不成功,所以就要用到webview的
WebViewClient()回掉方法里面去调取
webView.setWebViewClient(new WebViewClient() { @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { // return super.shouldOverrideUrlLoading(view, request.getUrl().toString()); view.loadUrl(request.getUrl().toString()); return true; } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); progressBar.setProgress(0); progressBar.setVisibility(View.VISIBLE); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); // progressBar.setVisibility(View.GONE); boolean b=SpUtils.getLoginsuc(MainActivity.this); if(!b) {//false 表示h5没登陆成功,没登录成功调取h5的方法,登陆成功就不调取 webView.loadUrl("javascript:getUserInfo('" + SpUtils.getpwd(MainActivity.this).get("user") + "','" + SpUtils.getpwd(MainActivity.this).get("pswd") + "')"); } } @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { super.onReceivedError(view, errorCode, description, failingUrl); // 加载网页失败时处理 如:提示失败,或显示新的界面 } });
6.当webview搭载进度条一起使用的时候动态的处理进度条的状态就要用到webview的WebChromeClient();
webView.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); if (newProgress == 100) { progressBar.setVisibility(View.GONE); } else { progressBar.setVisibility(View.VISIBLE); progressBar.setProgress(newProgress); } } });
7.webview的缓存问题(我的想法是想要把缓存清除的透彻就给webview设置制定的缓存路径然后找到路径下去清除所以在websetting 加以下设置)
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);//这里要设置为不适用缓存但是下面数据库路径要设置下可以清除缓存 // webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); //设置 缓存模式 (这种情况的意思视情况来决定是否使用缓存) // 开启 DOM storage API 功能 webSettings.setDomStorageEnabled(true); //开启 database storage API 功能 webSettings.setDatabaseEnabled(true); String cacheDirPath = getFilesDir().getAbsolutePath() + APP_CACAHE_DIRNAME; // String cacheDirPath = getCacheDir().getAbsolutePath()+Constant.APP_DB_DIRNAME; // Log.i(TAG, "cacheDirPath="+cacheDirPath); //设置数据库缓存路径 webSettings.setDatabasePath(cacheDirPath); //设置 Application Caches 缓存目录 webSettings.setAppCachePath(cacheDirPath); //开启 Application Caches 功能 webSettings.setAppCacheEnabled(true);
/** * 清除WebView缓存 */ public void clearWebViewCache() { //清理Webview缓存数据库 try { deleteDatabase("webview.db"); deleteDatabase("webviewCache.db"); } catch (Exception e) { e.printStackTrace(); } //WebView 缓存文件 File appCacheDir = new File(getFilesDir().getAbsolutePath() + APP_CACAHE_DIRNAME); // Log.e(TAG, "appCacheDir path="+appCacheDir.getAbsolutePath()); File webviewCacheDir = new File(getCacheDir().getAbsolutePath() + "/webviewCache"); // Log.e(TAG, "webviewCacheDir path="+webviewCacheDir.getAbsolutePath()); //删除webview 缓存目录 if (webviewCacheDir.exists()) { deleteFile(webviewCacheDir); } //删除webview 缓存 缓存目录 if (appCacheDir.exists()) { deleteFile(appCacheDir); } } /** * 递归删除 文件/文件夹 * * @param file */ public void deleteFile(File file) { if (file.exists()) { if (file.isFile()) { file.delete(); } else if (file.isDirectory()) { File files[] = file.listFiles(); for (int i = 0; i < files.length; i++) { deleteFile(files[i]); } } file.delete(); } else { Log.e(TAG, "delete file no exists " + file.getAbsolutePath()); } }
以上就是我在开发过程中自己做的一点小的记录(附上完整代码希望对同行们有点效果)
xml:
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:fitsSystemWindows="true"
android:background="@color/loginbg"
android:layout_height="match_parent">
android:id="@+id/pb"
android:visibility="visible"
android:progress="0"
android:max="100"
style="@style/StyleProgressBarMini"
android:layout_width="match_parent"
android:layout_height="5dp" />
android:background="@color/colorWhite"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:id="@+id/ll_web"
android:orientation="vertical"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp">
progressbar样式:
drawable/shape_progressbar_mini样式:
xmlns:android="http://schemas.android.com/apk/res/android">
- android:id="@android:id/background">
android:endColor="@color/colorWhite"
android:startColor="@color/colorWhite"/>
- android:id="@android:id/secondaryProgress">
android:endColor="@color/loginbg"
android:startColor="@color/loginbg"/>
- android:id="@android:id/progress">
android:endColor="@color/dialogcolor"
android:startColor="@color/dialogcolor"/>
Activity写法:
public class MainActivity extends BaseActivity implements Lateralinterface.UpdateUi, Lateralinterface.Loginout { @ViewInject(R.id.ll_web) private LinearLayout ll_web; @ViewInject(R.id.pb) private ProgressBar progressBar; @ViewInject(R.id.rg_tab) private RadioGroup rg_tab; private WebView webView; private String surl; private static final String TAG = "MainActivity"; private static final String APP_CACAHE_DIRNAME = "/webcache";//app缓存地址 @Override public void setLayout() { setContentView(R.layout.activity_main); } @Override public void init(Bundle savedInstanceState) { surl = CadillacUrl.HOME_URL; webset(); } /** * webview的一些设置 */ private void webset() { clearWebViewCache();//清除掉缓存 ll_web.removeAllViews(); webView = null; webView = new WebView(MainActivity.this); webView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); ll_web.addView(webView); WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); // 设置允许JS弹窗 // webSettings.setJavaScriptCanOpenWindowsAutomatically(true); webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);//这里要设置为不适用缓存但是下面数据库路径要设置下可以清除缓存 // webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); //设置 缓存模式 (这种情况的意思视情况来决定是否使用缓存) // 开启 DOM storage API 功能 webSettings.setDomStorageEnabled(true); //开启 database storage API 功能 webSettings.setDatabaseEnabled(true); String cacheDirPath = getFilesDir().getAbsolutePath() + APP_CACAHE_DIRNAME; // String cacheDirPath = getCacheDir().getAbsolutePath()+Constant.APP_DB_DIRNAME; // Log.i(TAG, "cacheDirPath="+cacheDirPath); //设置数据库缓存路径 webSettings.setDatabasePath(cacheDirPath); //设置 Application Caches 缓存目录 webSettings.setAppCachePath(cacheDirPath); //开启 Application Caches 功能 webSettings.setAppCacheEnabled(true); //下面三个最常用,基本都需要设置 // setCacheMode 设置缓存的模式 eg: settings.setCacheMode(WebSettings.LOAD_NO_CACHE); // setJavaSciptEnabled 设置是否支持Javascript eg: settings.setJavaScriptEnabled(true); // setDefaultTextEncodingName 设置在解码时使用的默认编码 eg: settings.setDefaultTextEncodingName(“utf-8”); // setAllowFileAccess 启用或禁止WebView访问文件数据 // setBlockNetworkImage 是否显示网络图像 // setBuiltInZoomControls 设置是否支持缩放 // setDefaultFontSize 设置默认的字体大小 // setFixedFontFamily 设置固定使用的字体 // setLayoutAlgorithm 设置布局方式 // setLightTouchEnabled 设置用鼠标激活被选项 // setSupportZoom 设置是否支持变焦 // webView.setWebChromeClient(new WebChromeClient()); webView.loadUrl(surl); //暴露js侧滑动,java暴露方法然后显示隐藏 webView.addJavascriptInterface(new Lateralinterface(MainActivity.this), "wst"); webView.addJavascriptInterface(new LoginSucinterface(MainActivity.this), "log"); // // webView.setWebViewClient(new WebViewClient() { @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { // return super.shouldOverrideUrlLoading(view, request.getUrl().toString()); view.loadUrl(request.getUrl().toString()); return true; } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); progressBar.setProgress(0); progressBar.setVisibility(View.VISIBLE); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); // progressBar.setVisibility(View.GONE); boolean b=SpUtils.getLoginsuc(MainActivity.this); if(!b) {//false 表示h5没登陆成功 webView.loadUrl("javascript:getUserInfo('" + SpUtils.getpwd(MainActivity.this).get("user") + "','" + SpUtils.getpwd(MainActivity.this).get("pswd") + "')"); } } @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { super.onReceivedError(view, errorCode, description, failingUrl); // 加载网页失败时处理 如:提示失败,或显示新的界面 } }); webView.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); if (newProgress == 100) { progressBar.setVisibility(View.GONE); } else { progressBar.setVisibility(View.VISIBLE); progressBar.setProgress(newProgress); } } }); } @OnClick({R.id.rb_data, R.id.rb_stat, R.id.rb_flat}) public void OnClick(View view) { switch (view.getId()) { case R.id.rb_data://首页 surl = CadillacUrl.HOME_URL; webset(); break; case R.id.rb_stat:// surl = CadillacUrl.CENT_URL; webset(); break; case R.id.rb_flat: break; } } @Override protected void onDestroy() { super.onDestroy(); ll_web.removeAllViews(); webView.destroy(); webView = null; clearWebViewCache();//清除掉缓存 } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { if (webView.canGoBack()) { webView.goBack(); rg_tab.setVisibility(View.VISIBLE); return true; } // else { //// finish(); // } } return super.onKeyDown(keyCode, event); } @Override public void showOrhide(String type) { switch (type) { case "1"://显示 new Thread() { @Override public void run() { super.run(); runOnUiThread(new Runnable() { @Override public void run() { rg_tab.setVisibility(View.VISIBLE); } }); } }.start(); break; case "2"://隐藏 new Thread() { @Override public void run() { super.run(); runOnUiThread(new Runnable() { @Override public void run() { rg_tab.setVisibility(View.GONE); } }); } }.start(); break; } } /** * 清除WebView缓存 */ public void clearWebViewCache() { //清理Webview缓存数据库 try { deleteDatabase("webview.db"); deleteDatabase("webviewCache.db"); } catch (Exception e) { e.printStackTrace(); } //WebView 缓存文件 File appCacheDir = new File(getFilesDir().getAbsolutePath() + APP_CACAHE_DIRNAME); // Log.e(TAG, "appCacheDir path="+appCacheDir.getAbsolutePath()); File webviewCacheDir = new File(getCacheDir().getAbsolutePath() + "/webviewCache"); // Log.e(TAG, "webviewCacheDir path="+webviewCacheDir.getAbsolutePath()); //删除webview 缓存目录 if (webviewCacheDir.exists()) { deleteFile(webviewCacheDir); } //删除webview 缓存 缓存目录 if (appCacheDir.exists()) { deleteFile(appCacheDir); } } /** * 递归删除 文件/文件夹 * * @param file */ public void deleteFile(File file) { if (file.exists()) { if (file.isFile()) { file.delete(); } else if (file.isDirectory()) { File files[] = file.listFiles(); for (int i = 0; i < files.length; i++) { deleteFile(files[i]); } } file.delete(); } else { Log.e(TAG, "delete file no exists " + file.getAbsolutePath()); } } @Override public void loginoutact() { SpUtils.clearSp(MainActivity.this); finish(); openActivity(LoginAct.class); } }