寫在前面
這篇文章主要是梳理H5遊戲微端app的啓動流程
,然後解決這個流程中出現的問題,如網絡檢測
、斷網或訪問出錯處理
。
App啓動流程
個人認爲一個H5遊戲微端app的啓動流程應該是這樣的:
自定義html
在Android Studio工程新建assets目錄,添加兩個html文件:啓動頁(index.html)
和錯誤頁(error.html)
。
啓動頁:遊戲開始時顯示,可以在這裏顯示公司logp動畫,結束後正式訪問H5遊戲首頁。
錯誤頁:用於訪問H5遊戲首頁失敗,返回404或500錯誤時顯示。
webview加載html代碼:
final String INDEX_URL = "file:///android_asset/index.html";
WebViewCacheInterceptorInst.getInstance().loadUrl(mWebView, INDEX_URL);
注意,因爲我們用了CacheWebView第三方庫了,所以用WebViewCacheInterceptorInst.getInstance().loadUr()
代替mWebView.loadUrl()
方法;
檢測聯網
- 定義一個廣播類
NetStateReceiver
繼承BroadcastReceiver
,並且重寫onReceive方法,onReceive方法中就是我們想要廣播接收器收到廣播之後需要處理的操作。
@Override
public void onReceive(Context context, Intent intent){
// 檢測網絡是否連通
checkNetwork(context);
}
- 對廣播進行註冊:在MainActivity進行註冊,並監聽網絡變化。
// MainActivity.java
private NetStateReceiver receiver = new NetStateReceiver();
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(receiver, filter);
- 如果網絡正常,那麼直接下一個流程,訪問遊戲主頁。否則的話彈窗提示。問題在於當
NetStateReceiver
檢測到網絡正常時,如何跟MainActivity
通信。在NetStateReceiver
中聲明接口NetworkObserver
,然後MainActivity
實現該接口,並把自身傳入NetStateReceiver
作爲一個類成員變量,等到檢測網絡正常時調用對應方法。
// NetStateReceiver.java
public interface NetworkObserver{
public void networkSuccess();
public void networkFail();
}
public void setNetworkObserver(NetworkObserver observer) {
this.observer = observer;
}
// MainActivity.java
public class MainActivity extends AppCompatActivity implements NetStateReceiver.NetworkObserver {
private NetStateReceiver receiver = new NetStateReceiver();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 將自身傳入到NetStateReceiver中
receiver.setNetworkObserver(this);
}
}
// NetStateReceiver.java
// 檢測網絡,成功or失敗調用MainActivity對應的方法
public void checkNetwork(Context context){
ConnectivityManager manager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isAvailable()){
Toast.makeText(context, "網絡連接成功", Toast.LENGTH_SHORT).show();
closeDialog();
this.observer.networkSuccess();
LogUtil.d("network succuess");
}else{
showDialog(context);
this.observer.networkFail();
LogUtil.d("network fail");
}
}
Webview處理404、500、斷網
加載網頁的過程中,可能會因爲網絡問題出現各種錯誤情況,這時候會顯示默認的錯誤頁面。
瞭解WebView的各種錯誤情況,既可以定製錯誤頁面,也可以根據不同的錯誤情況進行處理。
WebView監聽錯誤的方法
- onReceiveError
onReceiveError是WebViewClient提供的方法,用於網頁產生錯誤時進行回調處理。
簡單來說,onReceiveError只有在遇到不可用的(unrecoverable)錯誤時纔會被調用。
不可用的情況包括:
1、沒有網絡連接
2、連接超時
3、找不到頁面
而下面的情況則不會被報告:
1、網頁內引用其他資源加載錯誤,比如圖片、css不可用
2、js執行錯誤
- onReceivedHttpError
onReceivedHttpError也是WebViewClient提供的方法,主要是用於捕獲 Http Error (404、500)。
處理404、500
Android6.0以上可以重寫onReceivedHttpError方法捕獲http Error,而Android6.0以下訪問出錯時,是不會跑到這個函數的。
- Android6.0以上版本:重寫onReceivedHttpError
mWebView.setWebViewClient(new WebViewClient(){
@TargetApi(android.os.Build.VERSION_CODES.M)
@Override
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
super.onReceivedHttpError(view, request, errorResponse);
// 這個方法在6.0纔出現
int statusCode = errorResponse.getStatusCode();
if (404 == statusCode || 500 == statusCode) {
LogUtil.d("deal http error(android version above 6.0), statusCode = " + statusCode);
showErrorPage();
}
}
}
- Android6.0以下版本:通過獲取網頁的title,判斷是否爲系統默認的404頁面
mWebView.setWebChromeClient(new WebChromeClient(){
@Override
public void onReceivedTitle(WebView view, String title) {
super.onReceivedTitle(view, title);
// android 6.0 以下通過title獲取
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
if (title.contains("404") || title.contains("500") || title.contains("Error") || title.contains("找不到網頁") || title.contains("網頁無法打開")) {
LogUtil.d("deal http error(android version below 6.0), title = " + title);
showErrorPage();
}
}
}
});
處理斷網和鏈接超時
- Android6.0以上版本:
@TargetApi(Build.VERSION_CODES.M)
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
super.onReceivedError(view, request, error);
if (request.isForMainFrame()){ // 是否是爲 main frame創建
LogUtil.d("onReceivedError (android version above 6.0), code = " + error.getErrorCode() + ", desc = " + error.getDescription());
showErrorPage();
}
}
- Android6.0以下版本
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
return;
}
LogUtil.d("onReceivedError (android version below 6.0), code = " + errorCode + ", desc = " + description);
showErrorPage();
}
完整的Github工程:H5MicroClient。