我有一个网络应用程序 (https://salon.techwithin.in) 将在浏览器和 Android 应用程序上使用。
我的应用程序的示例二维码 https://i.postimg.cc/Fsm9bKwT/sample-qr-scan.jpg
为了将此 Web 应用程序转换为 Android 应用程序,我使用 WebView 创建了一个简单的 Android 应用程序
public class MainActivity extends AppCompatActivity {
private WebView mywebView;
private String userAgent;
private static final int PERMISSION_REQUEST_CODE = 200;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (checkPermission()) {
} else {
requestPermission();
}
setContentView(R.layout.activity_main);
mywebView=findViewById(R.id.webview);
mywebView.setWebViewClient(new mywebClient());
// TO TEST ON DEVELOPERS DEMO PORTAL I USED THEIR PAGE TO LOAD IN WEBVIEW, BUT SAME ERROR ON THAT PAGE TOO.
//mywebView.loadUrl("https://blog.minhazav.dev/research/html5-qrcode.html");
mywebView.loadUrl("https://salon.techwithin.in");
WebSettings webSettings=mywebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setDatabaseEnabled(true);
webSettings.setPluginState(WebSettings.PluginState.ON);
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
webSettings.setLoadWithOverviewMode(false);
webSettings.setAllowFileAccess(true);
webSettings.setSupportZoom(true);
webSettings.setBuiltInZoomControls(false);
webSettings.setSupportMultipleWindows(true);
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
CookieManager.getInstance().setAcceptCookie(true);
//userAgent = System.getProperty("http.agent");
//webSettings.setUserAgentString(webSettings.getUserAgentString().replace("; wv",""));
mywebView.setWebChromeClient(new WebChromeClient(){
@Override
public void onPermissionRequest(final PermissionRequest request) {
request.grant(request.getResources());
}
});
}
我在 logcat 中收到以下错误,QR 扫描仪区域保持空白。
2022-09-06 09:05:44.877 2932-2932/in.techwithin.thesalonman I/chromium:[INFO:CONSOLE(2)] “Uncaught ReferenceError: globalThis is not defined”,来源:https://blog .minhazav.dev/assets/research/html5qrcode/html5-qrcode.min.js (2) 2022-09-06 09:05:44.894 2932-2932/in.techwithin.thesalonman I/编舞:跳过 33 帧!应用程序可能在其主线程上做了太多工作。 2022-09-06 09:05:44.975 2932-2932/in.techwithin.thesalonman I/chromium: [INFO:CONSOLE(432)] “Uncaught TypeError: Html5QrcodeScanner is not a constructor”,来源:https://blog .minhazav.dev/research/html5-qrcode.html (432)
当前插件用于扫描我的网络应用程序中的二维码
https://github.com/mebjas/html5-qrcode
我试过在 webview 中使用开发人员的 Html5-qrcode 演示页面,它抛出了同样的错误。 (查看代码示例中的注释)
Android 应用程序正确请求 CAMERA 访问, 为了测试相机的工作情况,我测试了另一个插件演示网页
https://nimiq.github.io/qr-scanner/demo/
它打开相机并正确扫描QR码,
但是现在,我无法在我的网络应用程序中切换到这个工作插件,因此我需要一个仅包含当前插件 (html5-qrcode) 的解决方案。 我当前的网络应用程序是在 Core PHP 中构建的,并直接在浏览器中使用 html5-qrcode 插件,无需任何加载程序
<script src="https://unpkg.com/html5-qrcode" type="text/javascript">
我是 Android 应用程序开发的新手,因此我们将不胜感激。
我也是安卓应用的新手。
html5-qrcode
插件在我的WebView中工作。
这是代码
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<meta-data android:name="com.onesignal.suppressLaunchURLs" android:value="true"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.CAMERA2" />
<uses-permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT" />
<uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT" />
<uses-permission android:name="android.permission.VIDEO_CAPTURE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_stat_onesignal_default"
android:label="PRONOMIO"
android:roundIcon="@mipmap/ic_stat_onesignal_default_round"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.NoActionBar"
android:usesCleartextTraffic="true"
android:background="@android:color/black"
android:name=".PronomioTitanApplicationClass">
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data android:name="android.webkit.WebView.EnableSafeBrowsing" android:value="false" />
</application>
</manifest>
MainActivity.java
package com.test.myapp;
import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings.Secure;
import android.util.Log;
import android.view.Window;
import android.webkit.JsResult;
import android.webkit.PermissionRequest;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.widget.Toast;
import com.test.myapp.databinding.ActivityMainBinding;
import java.io.IOException;
import java.io.StringWriter;
import java.lang.annotation.Target;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.view.WindowCompat;
public class MainActivity extends AppCompatActivity {
private WebView myapp;
Context context;
ActivityMainBinding binding;
private int currentApiVersion;
@Override
protected void onResume() {
super.onResume();
checkCameraPermission();
}
private void checkCameraPermission() {
int writeExternalStorage = ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA);
if (writeExternalStorage != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.CAMERA}, 1001);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1001) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//Do your stuff
//openWebView();
} else {
checkCameraPermissionAndStartWebView();
}
}
}
private void checkCameraPermissionAndStartWebView() {
int writeExternalStorage = ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA);
if (writeExternalStorage != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.CAMERA}, 1001);
} else {
//openWebView();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
currentApiVersion = android.os.Build.VERSION.SDK_INT;
final int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
if (currentApiVersion >= Build.VERSION_CODES.KITKAT) {
getWindow().getDecorView().setSystemUiVisibility(flags);
final View decorView = getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
@Override
public void onSystemUiVisibilityChange(int visibility) {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
decorView.setSystemUiVisibility(flags);
}
}
});
}
myapp = (WebView) findViewById(R.id.myapp);
myapp.setWebViewClient(new WebViewClient() {
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
myapp.loadUrl("file:///android_asset/error-page.html");
}
});
if(haveNetworkConnection()) {
myapp.getSettings().setMediaPlaybackRequiresUserGesture(true);
myapp.getSettings().setSupportZoom(true);
myapp.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
myapp.getSettings().setJavaScriptEnabled(true);
myapp.getSettings().setAllowFileAccessFromFileURLs(true);
myapp.getSettings().setAllowUniversalAccessFromFileURLs(true);
myapp.getSettings().setPluginState(WebSettings.PluginState.ON);
myapp.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
myapp.getSettings().setLoadWithOverviewMode(false);
myapp.getSettings().setAllowFileAccess(true);
myapp.getSettings().setBuiltInZoomControls(false);
myapp.getSettings().setSupportMultipleWindows(true);
myapp.setWebChromeClient(new WebChromeClient(){
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
//Required functionality here
return super.onJsAlert(view, url, message, result);
}
@Override
public void onPermissionRequest(final PermissionRequest request) {
request.grant(request.getResources());
}
});
myapp.loadUrl("https://webview.example.com/");
} else {
myapp.loadUrl("file:///android_asset/error-page.html");
}
myapp.getSettings().setDomStorageEnabled(true);
myapp.getSettings().setJavaScriptEnabled(true);
}
public void onPermissionRequest(final PermissionRequest request) {
final String[] requestedResources = request.getResources();
for (String r : requestedResources) {
if (r.equals(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) {
request.grant(new String[]{PermissionRequest.RESOURCE_VIDEO_CAPTURE});
break;
}
}
}
@SuppressLint("NewApi")
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (currentApiVersion >= Build.VERSION_CODES.KITKAT && hasFocus) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
}
private boolean haveNetworkConnection() {
boolean haveConnectedWifi = false;
boolean haveConnectedMobile = false;
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo[] netInfo = cm.getAllNetworkInfo();
for (NetworkInfo ni : netInfo) {
if (ni.getTypeName().equalsIgnoreCase("WIFI"))
if (ni.isConnected())
haveConnectedWifi = true;
if (ni.getTypeName().equalsIgnoreCase("MOBILE"))
if (ni.isConnected())
haveConnectedMobile = true;
}
return haveConnectedWifi || haveConnectedMobile;
}
}
我在网站上有
<head></head>
<script src="https://github.com/mebjas/html5-qrcode" id="scan-qr-js"></script>
在
<body></body>
<div class="SCAN-QR-READER-AREA">
<div id="qr-reader"></div>
<div id="qr-reader-results"></div>
</div>
<script>
function docReady(fn) {
// see if DOM is already available
if (document.readyState === "complete"
|| document.readyState === "interactive") {
// call on next available tick
setTimeout(fn, 1);
} else {
document.addEventListener("DOMContentLoaded", fn);
}
}
docReady(function () {
var resultContainer = document.getElementById("qr-reader-results");
var lastResult, countResults = 0;
function onScanSuccess(decodedText, decodedResult) {
if (decodedText !== lastResult) {
++countResults;
//lastResult = decodedText;
// Handle on success condition with the decoded message.
console.log(`Scan result ${decodedText}`, decodedResult);
alert(decodedText);
}
}
var html5QrcodeScanner = new Html5QrcodeScanner(
"qr-reader", { fps: 10, qrbox: 250, rememberLastUsedCamera: false });
html5QrcodeScanner.render(onScanSuccess);
}
});
</script>
希望有帮助
问题不在于你的安卓代码 根据项目的问题列表,问题出在 2.3.1 版本之后的 html5-qrcode.min.js 文件中
所以我从以下链接复制了文件,它开始工作了。 https://github.com/mebjas/html5-qrcode/releases/tag/v2.3.1