android與h5的互相互動傳參
阿新 • • 發佈:2019-02-15
最近幾年隨著h5的強勢崛起,越來越多的公司運用h5開發或者採用h5與android的混合開發,前端時間公司就碰到了一個h5就和android互動的專案,本人也是在摸索中一次次改進,廢話不說了直接上程式碼:
1.建議使用new Webview構建webview物件而不是直接在佈局xml檔案中運用
<LinearLayout 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"> <LinearLayout android:id="@+id/ll_web" android:orientation="vertical" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="0dp"> </LinearLayout> </LinearLayout>
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:
<LinearLayout 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">
<ProgressBar
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" />
<LinearLayout
android:background="@color/colorWhite"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/ll_web"
android:orientation="vertical"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp">
</LinearLayout>
</LinearLayout>
</LinearLayout>
progressbar樣式:
<!-- 自定義的progressbar樣式 --> <style name="StyleProgressBarMini" parent="Widget.AppCompat.ProgressBar.Horizontal"> <item name="android:maxHeight">50dp</item> <item name="android:minHeight">10dp</item> <item name="android:indeterminateOnly">false</item> <item name="android:indeterminateDrawable">@android:drawable/progress_indeterminate_horizontal</item> <item name="android:progressDrawable">@drawable/shape_progressbar_mini</item> </style>
drawable/shape_progressbar_mini樣式:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@android:id/background"> <clip> <shape> <gradient android:endColor="@color/colorWhite" android:startColor="@color/colorWhite"/> </shape> </clip> </item> <item android:id="@android:id/secondaryProgress"> <clip> <shape> <gradient android:endColor="@color/loginbg" android:startColor="@color/loginbg"/> </shape> </clip> </item> <item android:id="@android:id/progress"> <clip> <shape> <gradient android:endColor="@color/dialogcolor" android:startColor="@color/dialogcolor"/> </shape> </clip> </item> </layer-list>
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); } }