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
相关产品推荐
相关产品推荐

