You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chainway C6000(Android6)WebView运行JS报错问题求助

WebView应用在Chainway C6000(Android 6)设备上运行不一致问题排查与解决方案

问题描述

同型号Chainway C6000(Android 6系统)设备上,我司开发的WebView应用表现不一致:部分设备可正常运行,部分设备无法运行。所有设备的系统版本、预装应用、默认浏览器均一致,推测是某些组件未更新导致问题。

该应用在WebView、Cordova、.NET MAUI WebView及Blazor绑定场景下,均频繁抛出Uncaught SyntaxError,JavaScript无法正常执行。

核心报错日志

I/chromium: [INFO:CONSOLE(20)] "Uncaught SyntaxError: Unexpected token )", source: http://example.com/js/bootstrap.min.js (20)
I/chromium: [INFO:CONSOLE(365)] "Uncaught SyntaxError: Identifier 't' has already been declared", source: http://example.com/js/bootbox.all.min.js (365)
I/chromium: [INFO:CONSOLE(116)] "Uncaught SyntaxError: Unexpected token [", source: http://xampp.geinal.com:33432/js/funcs.js (116)
I/chromium: [INFO:CONSOLE(1)] "Uncaught SyntaxError: Unexpected token )", source: http://example.com/_framework/blazor.server.js (1) 

注:日志仅作参考,核心问题为JavaScript无法正常运行。

关键差异点

测试发现,正常运行设备的UserAgent浏览器版本为75.0,异常设备为44.0。

相关代码(MainActivity.java)

package com.example.testview;

import static com.google.android.material.internal.ContextUtils.getActivity;

import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Build;
import android.os.Bundle;

import com.google.android.material.snackbar.Snackbar;

import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;

import com.example.testview.databinding.ActivityMainBinding;

import android.view.Menu;
import android.view.MenuItem;


import android.webkit.CookieManager;
import android.webkit.SslErrorHandler;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MainActivity extends AppCompatActivity {

    WebView webView;
    private static final String TAG = MainActivity.class.getSimpleName();
    private String mCM;
    private ValueCallback mUM;
    private ValueCallback<Uri[]> mUMA;
    private final static int FCR=1;



    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent){




         int _result = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
        // int _result = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);

        if (_result == PackageManager.PERMISSION_GRANTED){
            Log.d("-----------------CODE X","Hay permisos");
        } else {
            Log.d("-----------------CODE X","ERROR permisos");
        }


        super.onActivityResult(requestCode, resultCode, intent);
        if(Build.VERSION.SDK_INT >= 21){
            Uri[] results = null;
            //Check if response is positive
            if(resultCode== Activity.RESULT_OK){
              if(requestCode == FCR){
                    if(null == mUMA){
                        Log.d("-----------------CODE 0","ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR");
                         return;
                    }
                    if(intent == null || intent.getData() == null){
                        //Capture Photo if no image available
                        if(mCM != null){

                            Log.d("-----------------CODE 1",new Uri[]{Uri.parse(mCM)}.toString());
                            Log.d("----------------CODE R3", String.valueOf(results));

                            results = new Uri[]{Uri.parse(mCM)};
                        }
                    }else{
                        String dataString = intent.getDataString();
                        if(dataString != null){
                            Log.d("-----------------CODE 2",new Uri[]{Uri.parse(dataString)}.toString());
                            Log.d("-----------------CODE D",dataString);
                            Log.d("----------------CODE R2", String.valueOf(results));

                            results = new Uri[]{Uri.parse(dataString)};

                        }
                    }
                }
            }

            Log.d("----------------CODE R1", String.valueOf(results));

            mUMA.onReceiveValue(results);
            mUMA = null;
        }else{
            if(requestCode == FCR){
                if(null == mUM) return;
                Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData();
                mUM.onReceiveValue(result);
                mUM = null;
            }
        }
    }

    @SuppressLint({"SetJavaScriptEnabled", "WrongViewCast"})
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);


      // if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
          //      ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 3);
             //   ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 3);
          //  }



        Log.d("-----------------CODE C","ONCREATEONCREATEONCREATEONCREATEONCREATEONCREATEONCREATEONCREATEONCREATEONCREATEONCREATE");


        setContentView(R.layout.activity_main);

        if(Build.VERSION.SDK_INT >=23 && (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)) {
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, 1);
        }


        // Andorid 10 filechooser not showing camera option
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                == PackageManager.PERMISSION_DENIED) {
            ActivityCompat.requestPermissions(MainActivity.this, new String[] {Manifest.permission.CAMERA}, 1);
        }

        ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE);



        webView = (WebView) findViewById(R.id.MyWeb);
        //    assert webView != null;
        //  WebSettings webSettings = webView.getSettings();
        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setAllowFileAccess(true);

        webView.getSettings().setDomStorageEnabled(true);
        webView.getSettings().setDatabaseEnabled(true);

        webView.getSettings().setAllowContentAccess(true);
        webView.getSettings().setAllowFileAccess(true);

        webView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
        CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true);

        if(Build.VERSION.SDK_INT >= 21){
            webView.getSettings().setMixedContentMode(0);
            webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
        }else if(Build.VERSION.SDK_INT >= 19){
            webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
        }else {
            webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        }
        webView.setWebViewClient(new Callback());



         webView.loadUrl("http://192.168.56.154");



        webView.setWebChromeClient(new WebChromeClient(){
            private ValueCallback<Uri[]> uploadMessage;

            //For Android 5.0+
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams){
                Log.d("Message tag -2 File cho","onShowFileChooser done");




                if(mUMA != null){
                    mUMA.onReceiveValue(null);
                }

                mUMA = filePathCallback;
                Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

                if(takePictureIntent.resolveActivity(MainActivity.this.getPackageManager()) != null){
                    File photoFile = null;
                    try{
                        photoFile = createImageFile();
                        takePictureIntent.putExtra("PhotoPath", mCM);
                    }catch(IOException ex){
                        Log.e(TAG, "Image file creation failed", ex);
                    }
                    if(photoFile != null){
                        mCM = "file:" + photoFile.getAbsolutePath();
                        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
                    }else{
                        takePictureIntent = null;
                    }
                }

                Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
                contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
                contentSelectionIntent.setType("*/*");
                Intent[] intentArray;

                if(takePictureIntent != null){
                    intentArray = new Intent[]{takePictureIntent};
                }else{
                    intentArray = new Intent[0];
                }

                Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
                //    Intent chooserIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

                chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
                chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
                chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
                startActivityForResult(chooserIntent, FCR);
                return true;


            }
        });
    }



    public class Callback extends WebViewClient{

        @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
            handler.proceed();
        }


        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl){
            Toast.makeText(getApplicationContext(), "Failed loading app!", Toast.LENGTH_SHORT).show();
        }
    }

    // Create an image file
    private File createImageFile() throws IOException{


        @SuppressLint("SimpleDateFormat") String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "img_"+timeStamp+"_";
        File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
        return File.createTempFile(imageFileName,".jpg",storageDir);
    }

    @Override
    public boolean onKeyDown(int keyCode, @NonNull KeyEvent event){
        if(event.getAction() == KeyEvent.ACTION_DOWN){
            switch(keyCode){
                case KeyEvent.KEYCODE_BACK:
                    if(webView.canGoBack()){
                        webView.goBack();
                    }else{
                        finish();
                    }
                    return true;
            }
        }
        return super.onKeyDown(keyCode, event);
    }
/*
    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        handler.proceed(); // Ignore SSL certificate errors
    }
*/


    @Override

    public void onConfigurationChanged(Configuration newConfig){
        super.onConfigurationChanged(newConfig);
    }
}

排查思路

  • 锁定WebView内核版本差异:Android 6的WebView依赖Android System WebView(或Chrome)组件,异常设备的44.0版本属于老旧版本,对ES6+等现代JavaScript语法支持不足,这是导致语法报错的核心原因。
  • 检查WebView组件状态:确认异常设备是否禁用了Android System WebView自动更新,或组件被系统冻结/未安装最新版本,导致版本停留在44.0。
  • 验证前端代码兼容性:排查前端JS代码是否使用了旧版WebView不支持的语法,比如箭头函数、解构赋值、let/const重复声明处理等特性。

解决方案

  • 统一WebView版本:在异常设备上手动更新Android System WebView(或Chrome浏览器)至75.0及以上版本;若有批量设备,可通过MDM工具推送组件更新,确保所有同型号设备WebView版本一致。
  • 前端代码降级兼容:使用Babel将ES6+代码转译为ES5语法,确保旧版WebView可正常解析;同时修复代码中重复声明变量等问题,避免触发旧引擎的语法检测报错。
  • 应用内WebView配置优化:在MainActivity中确保已启用必要的WebView设置(如setJavaScriptEnabled(true)、setDomStorageEnabled(true)),并检查是否存在限制WebView版本的代码逻辑。

内容的提问来源于stack exchange,提问作者Andi Hincu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 17:15:09