写在前面
这篇文章主要是梳理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。