H5游戏微端开发(三):app启动流程

写在前面

这篇文章主要是梳理H5游戏微端app的启动流程,然后解决这个流程中出现的问题,如网络检测断网或访问出错处理



App启动流程

个人认为一个H5游戏微端app的启动流程应该是这样的:

Created with Raphaël 2.2.0游戏启动页检测联网是否联网?访问游戏主页是否访问成功?进入游戏显示错误页面解决网络问题yesnoyesno


自定义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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章