mirror of
https://github.com/apache/cordova-android.git
synced 2026-04-04 00:02:03 +08:00
Compare commits
2 Commits
pr-add-pre
...
getusermed
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
710611262d | ||
|
|
ec14fd715f |
@@ -48,10 +48,6 @@ import androidx.core.splashscreen.SplashScreen;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.webkit.WebViewCompat;
|
||||
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
/**
|
||||
* This class is the main Android activity that represents the Cordova
|
||||
@@ -111,11 +107,6 @@ public class CordovaActivity extends AppCompatActivity {
|
||||
|
||||
private boolean canEdgeToEdge = false;
|
||||
private boolean isFullScreen = false;
|
||||
/**
|
||||
* Flag set in {@link #checkWebViewVersion} indicating whether the WebView version
|
||||
* is below the minimum required version specified in config.xml.
|
||||
*/
|
||||
private boolean isWebViewVersionBlocked = false;
|
||||
|
||||
/**
|
||||
* Called when the activity is first created.
|
||||
@@ -130,9 +121,6 @@ public class CordovaActivity extends AppCompatActivity {
|
||||
// need to activate preferences before super.onCreate to avoid "requestFeature() must be called before adding content" exception
|
||||
loadConfig();
|
||||
|
||||
// Check WebView version requirement
|
||||
checkWebViewVersion();
|
||||
|
||||
canEdgeToEdge = preferences.getBoolean("AndroidEdgeToEdge", false)
|
||||
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM;
|
||||
|
||||
@@ -177,10 +165,6 @@ public class CordovaActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
if (isWebViewVersionBlocked) {
|
||||
return;
|
||||
}
|
||||
|
||||
appView = makeWebView();
|
||||
createViews();
|
||||
if (!appView.isInitialized()) {
|
||||
@@ -295,10 +279,6 @@ public class CordovaActivity extends AppCompatActivity {
|
||||
* Load the url into the WebView.
|
||||
*/
|
||||
public void loadUrl(String url) {
|
||||
if (isWebViewVersionBlocked) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (appView == null) {
|
||||
init();
|
||||
}
|
||||
@@ -608,124 +588,6 @@ public class CordovaActivity extends AppCompatActivity {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the WebView version meets the minimum required version specified by
|
||||
* preference `AndroidMinimumWebViewVersion` in config.xml.
|
||||
* If not, display an error dialog and block the app from loading further.
|
||||
*/
|
||||
private void checkWebViewVersion() {
|
||||
String minimumWebViewVersion = preferences.getString("AndroidMinimumWebViewVersion", null);
|
||||
if (minimumWebViewVersion == null || minimumWebViewVersion.isEmpty()) {
|
||||
return; // No minimum version requirement set
|
||||
}
|
||||
|
||||
try {
|
||||
String currentWebViewVersion = getWebViewVersion();
|
||||
if (currentWebViewVersion != null && !isWebViewVersionSufficient(currentWebViewVersion, minimumWebViewVersion)) {
|
||||
isWebViewVersionBlocked = true;
|
||||
String title = getWebViewVersionTitle();
|
||||
String message = getWebViewVersionMessage();
|
||||
String button = getWebViewVersionButtonText();
|
||||
displayError(title, message, button, true);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.e(TAG, "Error checking WebView version: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the WebView version check dialog title from string resources.
|
||||
*/
|
||||
private String getWebViewVersionTitle() {
|
||||
int resId = getResources().getIdentifier("webview_version_too_old_title", "string", getPackageName());
|
||||
return resId != 0 ? getString(resId) : "WebView Update Required";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the WebView version check dialog message from string resources.
|
||||
*/
|
||||
private String getWebViewVersionMessage() {
|
||||
int resId = getResources().getIdentifier("webview_version_too_old_message", "string", getPackageName());
|
||||
return resId != 0 ? getString(resId) : "Your Android System WebView version is too old. Please update it through the Google Play Store.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the WebView version check dialog button text from string resources.
|
||||
*/
|
||||
private String getWebViewVersionButtonText() {
|
||||
int resId = getResources().getIdentifier("webview_version_ok_button", "string", getPackageName());
|
||||
return resId != 0 ? getString(resId) : "OK";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current WebView version string.
|
||||
* @return Version string (e.g., "80.0.1234.56") or null if unable to determine
|
||||
*/
|
||||
private String getWebViewVersion() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
try {
|
||||
PackageInfo webViewPackage = WebViewCompat.getCurrentWebViewPackage(this);
|
||||
if (webViewPackage != null) {
|
||||
return webViewPackage.versionName;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.d(TAG, "Could not get WebView version using WebViewCompat: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback for older API levels
|
||||
PackageManager pm = getPackageManager();
|
||||
String[] fallbackPackages = new String[] {
|
||||
"com.google.android.webview",
|
||||
"com.android.webview",
|
||||
"com.android.chrome"
|
||||
};
|
||||
|
||||
for (String packageName : fallbackPackages) {
|
||||
try {
|
||||
PackageInfo pi = pm.getPackageInfo(packageName, 0);
|
||||
return pi.versionName;
|
||||
} catch (PackageManager.NameNotFoundException ignored) {
|
||||
// Try next package
|
||||
}
|
||||
}
|
||||
|
||||
LOG.d(TAG, "Could not find WebView package");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two version strings and determine if current version is >= minimum version.
|
||||
* @param currentVersion Current version string (e.g., "80.0.1234.56")
|
||||
* @param minimumVersion Minimum required version string (e.g., "80.0")
|
||||
* @return true if currentVersion >= minimumVersion
|
||||
*/
|
||||
private boolean isWebViewVersionSufficient(String currentVersion, String minimumVersion) {
|
||||
try {
|
||||
String[] currentParts = currentVersion.split("\\.");
|
||||
String[] minimumParts = minimumVersion.split("\\.");
|
||||
|
||||
int maxLength = Math.max(currentParts.length, minimumParts.length);
|
||||
|
||||
for (int i = 0; i < maxLength; i++) {
|
||||
int currentPart = i < currentParts.length ? Integer.parseInt(currentParts[i]) : 0;
|
||||
int minimumPart = i < minimumParts.length ? Integer.parseInt(minimumParts[i]) : 0;
|
||||
|
||||
if (currentPart > minimumPart) {
|
||||
return true;
|
||||
} else if (currentPart < minimumPart) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true; // Versions are equal
|
||||
} catch (NumberFormatException e) {
|
||||
LOG.e(TAG, "Error parsing version strings: " + e.getMessage());
|
||||
return true; // If we can't parse, assume it's OK
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether to show the splash screen while the WebView is initially loading.
|
||||
* <p>
|
||||
|
||||
@@ -23,6 +23,9 @@ import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.ClipData;
|
||||
import android.content.Context;
|
||||
@@ -45,6 +48,10 @@ import android.webkit.PermissionRequest;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import androidx.activity.result.ActivityResultCallback;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
import org.apache.cordova.CordovaDialogsHelper;
|
||||
@@ -59,6 +66,12 @@ import org.apache.cordova.LOG;
|
||||
*/
|
||||
public class SystemWebChromeClient extends WebChromeClient {
|
||||
|
||||
private interface PermissionListener {
|
||||
void onPermissionSelect(Boolean isGranted);
|
||||
}
|
||||
|
||||
private ActivityResultLauncher permissionLauncher;
|
||||
private PermissionListener permissionListener;
|
||||
private static final int FILECHOOSER_RESULTCODE = 5173;
|
||||
private static final String LOG_TAG = "SystemWebChromeClient";
|
||||
private long MAX_QUOTA = 100 * 1024 * 1024;
|
||||
@@ -77,6 +90,15 @@ public class SystemWebChromeClient extends WebChromeClient {
|
||||
this.parentEngine = parentEngine;
|
||||
appContext = parentEngine.webView.getContext();
|
||||
dialogsHelper = new CordovaDialogsHelper(appContext);
|
||||
permissionLauncher = parentEngine.cordova.getActivity().registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), isGranted -> {
|
||||
if (permissionListener != null) {
|
||||
boolean granted = true;
|
||||
for (Map.Entry<String, Boolean> permission : isGranted.entrySet()) {
|
||||
if (!permission.getValue()) granted = false;
|
||||
}
|
||||
permissionListener.onPermissionSelect(granted);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -325,7 +347,27 @@ public class SystemWebChromeClient extends WebChromeClient {
|
||||
@Override
|
||||
public void onPermissionRequest(final PermissionRequest request) {
|
||||
LOG.d(LOG_TAG, "onPermissionRequest: " + Arrays.toString(request.getResources()));
|
||||
request.grant(request.getResources());
|
||||
List<String> permissionList = new ArrayList<>();
|
||||
if (Arrays.asList(request.getResources()).contains("android.webkit.resource.VIDEO_CAPTURE")) {
|
||||
permissionList.add(Manifest.permission.CAMERA);
|
||||
}
|
||||
if (Arrays.asList(request.getResources()).contains("android.webkit.resource.AUDIO_CAPTURE")) {
|
||||
permissionList.add(Manifest.permission.MODIFY_AUDIO_SETTINGS);
|
||||
permissionList.add(Manifest.permission.RECORD_AUDIO);
|
||||
}
|
||||
if (!permissionList.isEmpty()) {
|
||||
String[] permissions = permissionList.toArray(new String[0]);
|
||||
permissionListener = (isGranted) -> {
|
||||
if (isGranted) {
|
||||
request.grant(request.getResources());
|
||||
} else {
|
||||
request.deny();
|
||||
}
|
||||
};
|
||||
permissionLauncher.launch(permissions);
|
||||
} else {
|
||||
request.grant(request.getResources());
|
||||
}
|
||||
}
|
||||
|
||||
public void destroyLastDialog(){
|
||||
|
||||
47
package-lock.json
generated
47
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "cordova-android",
|
||||
"version": "15.0.1-dev.0",
|
||||
"version": "15.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "cordova-android",
|
||||
"version": "15.0.1-dev.0",
|
||||
"version": "15.0.0",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"android-versions": "^2.1.1",
|
||||
@@ -2280,9 +2280,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/glob/node_modules/minimatch": {
|
||||
"version": "10.2.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
|
||||
"integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
|
||||
"version": "10.2.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz",
|
||||
"integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==",
|
||||
"dev": true,
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
@@ -3245,9 +3245,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.3.tgz",
|
||||
"integrity": "sha512-M2GCs7Vk83NxkUyQV1bkABc4yxgz9kILhHImZiBPAZ9ybuvCb0/H7lEl5XvIg3g+9d4eNotkZA5IWwYl0tibaA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
@@ -4318,31 +4318,14 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/test-exclude/node_modules/glob/node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/test-exclude/node_modules/glob/node_modules/brace-expansion": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/test-exclude/node_modules/glob/node_modules/minimatch": {
|
||||
"version": "9.0.9",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
|
||||
"integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
|
||||
"version": "9.0.6",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.6.tgz",
|
||||
"integrity": "sha512-kQAVowdR33euIqeA0+VZTDqU+qo1IeVY+hrKYtZMio3Pg0P0vuh/kwRylLUddJhB6pf3q/botcOvRtx4IN1wqQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.2"
|
||||
"brace-expansion": "^5.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
@@ -4359,9 +4342,9 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/test-exclude/node_modules/minimatch": {
|
||||
"version": "10.2.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
|
||||
"integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
|
||||
"version": "10.2.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz",
|
||||
"integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==",
|
||||
"dev": true,
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cordova-android",
|
||||
"version": "15.0.1-dev.0",
|
||||
"version": "15.0.0",
|
||||
"description": "cordova-android release",
|
||||
"types": "./types/index.d.ts",
|
||||
"main": "lib/Api.js",
|
||||
|
||||
@@ -24,8 +24,4 @@
|
||||
<string name="launcher_name">@string/app_name</string>
|
||||
<!-- App label shown on the task switcher. -->
|
||||
<string name="activity_name">@string/launcher_name</string>
|
||||
<!-- WebView version check messages -->
|
||||
<string name="webview_version_too_old_title">WebView Update Required</string>
|
||||
<string name="webview_version_too_old_message">Your Android System WebView version is too old. Please update it through the Google Play Store.</string>
|
||||
<string name="webview_version_ok_button">OK</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user