334 lines
14 KiB
C#
334 lines
14 KiB
C#
|
|
// #if UNITY_2023_2_OR_NEWER
|
||
|
|
#if UNIWEBVIEW_NEW_ANDROID_BUILD_SYSTEM
|
||
|
|
|
||
|
|
using System;
|
||
|
|
using System.Linq;
|
||
|
|
using Unity.Android.Gradle;
|
||
|
|
using Unity.Android.Gradle.Manifest;
|
||
|
|
using UnityEditor.Android;
|
||
|
|
using UnityEngine;
|
||
|
|
using Action = Unity.Android.Gradle.Manifest.Action;
|
||
|
|
|
||
|
|
class UniWebViewPostBuildModifier : AndroidProjectFilesModifier {
|
||
|
|
|
||
|
|
const string ContextSettingsKey = "uniwebview_settings";
|
||
|
|
|
||
|
|
public override AndroidProjectFilesModifierContext Setup() {
|
||
|
|
var context = new AndroidProjectFilesModifierContext {
|
||
|
|
Dependencies = {
|
||
|
|
DependencyFiles = new[] {
|
||
|
|
// Set UniWebView editor settings asset path to be included in the build. With that we do not need
|
||
|
|
// a clean build to update the settings anymore (maybe, not confirmed).
|
||
|
|
UniWebViewEditorSettings.AssetPath
|
||
|
|
}
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
var settings = UniWebViewEditorSettings.GetOrCreateSettings();
|
||
|
|
context.SetData(ContextSettingsKey, settings);
|
||
|
|
return context;
|
||
|
|
}
|
||
|
|
|
||
|
|
public override void OnModifyAndroidProjectFiles(AndroidProjectFiles projectFiles) {
|
||
|
|
var settings = projectFiles.GetData<UniWebViewEditorSettingsReading>(ContextSettingsKey);
|
||
|
|
PatchUnityLibraryAndroidManifest(projectFiles.UnityLibraryManifest, settings);
|
||
|
|
PatchUnityLibraryBuildGradle(projectFiles.UnityLibraryBuildGradle, settings);
|
||
|
|
PatchGradleProperty(projectFiles.GradleProperties, settings);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void PatchUnityLibraryAndroidManifest(
|
||
|
|
AndroidManifestFile manifest, UniWebViewEditorSettingsReading settings
|
||
|
|
) {
|
||
|
|
// Set hardwareAccelerated
|
||
|
|
var launcherActivities = manifest.Manifest.GetActivitiesWithLauncherIntent();
|
||
|
|
foreach (var activity in launcherActivities) {
|
||
|
|
// Required for playing video in web view.
|
||
|
|
activity.Attributes.HardwareAccelerated.Set(true);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Set usesCleartextTraffic
|
||
|
|
if (settings.usesCleartextTraffic) {
|
||
|
|
manifest.Manifest.Application.Attributes.UsesCleartextTraffic.Set(true);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Set WRITE_EXTERNAL_STORAGE permission
|
||
|
|
if (settings.writeExternalStorage) {
|
||
|
|
AddUsesPermission(manifest, "android.permission.WRITE_EXTERNAL_STORAGE");
|
||
|
|
}
|
||
|
|
|
||
|
|
// Set ACCESS_FINE_LOCATION permission
|
||
|
|
if (settings.accessFineLocation) {
|
||
|
|
AddUsesPermission(manifest, "android.permission.ACCESS_FINE_LOCATION");
|
||
|
|
}
|
||
|
|
|
||
|
|
// Set auth callback intent filter
|
||
|
|
if (settings.authCallbackUrls.Length > 0 || settings.supportLINELogin) {
|
||
|
|
var authActivity = new Activity();
|
||
|
|
authActivity.Attributes.Name.Set("com.onevcat.uniwebview.UniWebViewAuthenticationActivity");
|
||
|
|
authActivity.Attributes.Exported.Set(true);
|
||
|
|
authActivity.Attributes.LaunchMode.Set(LaunchMode.SingleTask);
|
||
|
|
authActivity.Attributes.ConfigChanges.Set(
|
||
|
|
new[] {
|
||
|
|
ConfigChanges.Orientation, ConfigChanges.ScreenSize, ConfigChanges.KeyboardHidden
|
||
|
|
});
|
||
|
|
|
||
|
|
foreach (var url in settings.authCallbackUrls) {
|
||
|
|
AddAuthCallbacksIntentFilter(authActivity, url);
|
||
|
|
}
|
||
|
|
if (settings.supportLINELogin) {
|
||
|
|
AddAuthCallbacksIntentFilter(authActivity, "lineauth://auth");
|
||
|
|
}
|
||
|
|
manifest.Manifest.Application.ActivityList.AddElement(authActivity);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void PatchUnityLibraryBuildGradle(ModuleBuildGradleFile gradleFile, UniWebViewEditorSettingsReading settings) {
|
||
|
|
if (settings.addsKotlin) {
|
||
|
|
var kotlinPrefix = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:";
|
||
|
|
var kotlinVersion = String.IsNullOrWhiteSpace(settings.kotlinVersion)
|
||
|
|
? UniWebViewEditorSettings.defaultKotlinVersion : settings.kotlinVersion;
|
||
|
|
ReplaceContentOrAddStartsWith(gradleFile.Dependencies,
|
||
|
|
kotlinPrefix,
|
||
|
|
kotlinVersion);
|
||
|
|
Debug.Log("<UniWebView> Updated Kotlin dependency in build.gradle.");
|
||
|
|
}
|
||
|
|
|
||
|
|
if (settings.addsAndroidBrowser) {
|
||
|
|
var browserPrefix = "androidx.browser:browser:";
|
||
|
|
var browserVersion = String.IsNullOrWhiteSpace(settings.androidBrowserVersion)
|
||
|
|
? UniWebViewEditorSettings.defaultAndroidBrowserVersion : settings.androidBrowserVersion;
|
||
|
|
ReplaceContentOrAddStartsWith(gradleFile.Dependencies,
|
||
|
|
browserPrefix,
|
||
|
|
browserVersion);
|
||
|
|
Debug.Log("<UniWebView> Updated Browser dependency in build.gradle.");
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!settings.addsAndroidBrowser && settings.addsAndroidXCore) {
|
||
|
|
var androidXCorePrefix = "androidx.core:core:";
|
||
|
|
var androidXCoreVersion = String.IsNullOrWhiteSpace(settings.androidXCoreVersion)
|
||
|
|
? UniWebViewEditorSettings.defaultAndroidXCoreVersion : settings.androidXCoreVersion;
|
||
|
|
ReplaceContentOrAddStartsWith(gradleFile.Dependencies,
|
||
|
|
androidXCorePrefix,
|
||
|
|
androidXCoreVersion);
|
||
|
|
Debug.Log("<UniWebView> Updated Android X Core dependency in build.gradle.");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void PatchGradleProperty(GradlePropertiesFile file, UniWebViewEditorSettingsReading settings) {
|
||
|
|
var values = file.GetElements();
|
||
|
|
foreach (var ele in values) {
|
||
|
|
if (ele.GetRaw().Contains("android.enableJetifier")) {
|
||
|
|
ele.SetRaw("android.enableJetifier=" + (settings.enableJetifier ? "true": "false"));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void AddUsesPermission(AndroidManifestFile manifest, string name) {
|
||
|
|
|
||
|
|
var list = manifest.Manifest.UsesPermissionList;
|
||
|
|
foreach (var item in list) {
|
||
|
|
Debug.LogError(item.GetName());
|
||
|
|
}
|
||
|
|
|
||
|
|
var existing = manifest.Manifest.UsesPermissionList
|
||
|
|
.FirstOrDefault(ele => ele.Attributes.Name.Get() == name);
|
||
|
|
if (existing != null) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
var permission = new UsesPermission();
|
||
|
|
permission.Attributes.Name.Set(name);
|
||
|
|
manifest.Manifest.UsesPermissionList.AddElement(permission);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void AddAuthCallbacksIntentFilter(Activity activity, string callbackUrl) {
|
||
|
|
var uri = new Uri(callbackUrl);
|
||
|
|
var scheme = uri.Scheme;
|
||
|
|
|
||
|
|
if (String.IsNullOrEmpty(scheme)) {
|
||
|
|
Debug.LogError("<UniWebView> Auth callback url contains an empty scheme. Please check the url: " + callbackUrl);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
var intentFilter = new IntentFilter();
|
||
|
|
|
||
|
|
var action = new Action();
|
||
|
|
action.Attributes.Name.Set("android.intent.action.VIEW");
|
||
|
|
intentFilter.ActionList.AddElement(action);
|
||
|
|
|
||
|
|
var defaultCategory = new Category();
|
||
|
|
intentFilter.CategoryList.AddElement(defaultCategory);
|
||
|
|
defaultCategory.Attributes.Name.Set("android.intent.category.DEFAULT");
|
||
|
|
|
||
|
|
var browsableCategory = new Category();
|
||
|
|
browsableCategory.Attributes.Name.Set("android.intent.category.BROWSABLE");
|
||
|
|
intentFilter.CategoryList.AddElement(browsableCategory);
|
||
|
|
|
||
|
|
var data = new Data();
|
||
|
|
data.Attributes.Scheme.Set(scheme);
|
||
|
|
if (!String.IsNullOrEmpty(uri.Host)) {
|
||
|
|
data.Attributes.Host.Set(uri.Host);
|
||
|
|
}
|
||
|
|
if (uri.Port != -1) {
|
||
|
|
data.Attributes.Port.Set(uri.Port.ToString());
|
||
|
|
}
|
||
|
|
if (!String.IsNullOrEmpty(uri.PathAndQuery) && uri.PathAndQuery != "/") {
|
||
|
|
data.Attributes.Path.Set(uri.PathAndQuery);
|
||
|
|
}
|
||
|
|
intentFilter.DataList.AddElement(data);
|
||
|
|
activity.IntentFilterList.AddElement(intentFilter);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void ReplaceContentOrAddStartsWith(Dependencies dependencies, string prefix, string version) {
|
||
|
|
var all = dependencies.GetElements();
|
||
|
|
var matching = "implementation '" + prefix;
|
||
|
|
var found = all.FirstOrDefault(ele => ele.GetRaw().StartsWith(matching));
|
||
|
|
if (found != null) {
|
||
|
|
found.SetRaw($"implementation '{prefix}{version}'");
|
||
|
|
} else {
|
||
|
|
dependencies.AddDependencyImplementationRaw($"'{prefix}{version}'");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#else
|
||
|
|
using System;
|
||
|
|
using System.IO;
|
||
|
|
using UnityEditor.Android;
|
||
|
|
using UnityEngine;
|
||
|
|
|
||
|
|
class UniWebViewPostBuildProcessor : IPostGenerateGradleAndroidProject
|
||
|
|
{
|
||
|
|
public int callbackOrder { get { return 1; } }
|
||
|
|
public void OnPostGenerateGradleAndroidProject(string path) {
|
||
|
|
Debug.Log("<UniWebView> UniWebView Post Build Script is patching manifest file and gradle file...");
|
||
|
|
PatchAndroidManifest(path);
|
||
|
|
PatchBuildGradle(path);
|
||
|
|
PatchGradleProperty(path);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void PatchAndroidManifest(string root) {
|
||
|
|
var manifestFilePath = GetManifestFilePath(root);
|
||
|
|
var manifest = new UniWebViewAndroidManifest(manifestFilePath);
|
||
|
|
|
||
|
|
var changed = false;
|
||
|
|
|
||
|
|
Debug.Log("<UniWebView> Set hardware accelerated to enable smooth web view experience and HTML5 support like video and canvas.");
|
||
|
|
changed = manifest.SetHardwareAccelerated() || changed;
|
||
|
|
|
||
|
|
var settings = UniWebViewEditorSettings.GetOrCreateSettings();
|
||
|
|
if (settings.usesCleartextTraffic) {
|
||
|
|
changed = manifest.SetUsesCleartextTraffic() || changed;
|
||
|
|
}
|
||
|
|
if (settings.writeExternalStorage) {
|
||
|
|
changed = manifest.AddWriteExternalStoragePermission() || changed;
|
||
|
|
}
|
||
|
|
if (settings.accessFineLocation) {
|
||
|
|
changed = manifest.AddAccessFineLocationPermission() || changed;
|
||
|
|
}
|
||
|
|
if (settings.authCallbackUrls.Length > 0) {
|
||
|
|
changed = manifest.AddAuthCallbacksIntentFilter(settings.authCallbackUrls) || changed;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (settings.supportLINELogin) {
|
||
|
|
changed = manifest.AddAuthCallbacksIntentFilter(new string[] { "lineauth://auth" }) || changed;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (changed) {
|
||
|
|
manifest.Save();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void PatchBuildGradle(string root) {
|
||
|
|
var gradleFilePath = GetGradleFilePath(root);
|
||
|
|
var config = new UniWebViewGradleConfig(gradleFilePath);
|
||
|
|
|
||
|
|
var settings = UniWebViewEditorSettings.GetOrCreateSettings();
|
||
|
|
|
||
|
|
var kotlinPrefix = "implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:";
|
||
|
|
var kotlinVersion = String.IsNullOrWhiteSpace(settings.kotlinVersion)
|
||
|
|
? UniWebViewEditorSettings.defaultKotlinVersion : settings.kotlinVersion;
|
||
|
|
|
||
|
|
var browserPrefix = "implementation 'androidx.browser:browser:";
|
||
|
|
var browserVersion = String.IsNullOrWhiteSpace(settings.androidBrowserVersion)
|
||
|
|
? UniWebViewEditorSettings.defaultAndroidBrowserVersion : settings.androidBrowserVersion;
|
||
|
|
|
||
|
|
var androidXCorePrefix = "implementation 'androidx.core:core:";
|
||
|
|
var androidXCoreVersion = String.IsNullOrWhiteSpace(settings.androidXCoreVersion)
|
||
|
|
? UniWebViewEditorSettings.defaultAndroidXCoreVersion : settings.androidXCoreVersion;
|
||
|
|
|
||
|
|
var dependenciesNode = config.Root.FindChildNodeByName("dependencies");
|
||
|
|
if (dependenciesNode != null) {
|
||
|
|
// Add kotlin
|
||
|
|
if (settings.addsKotlin) {
|
||
|
|
dependenciesNode.ReplaceContentOrAddStartsWith(kotlinPrefix, kotlinPrefix + kotlinVersion + "'");
|
||
|
|
Debug.Log("<UniWebView> Updated Kotlin dependency in build.gradle.");
|
||
|
|
}
|
||
|
|
|
||
|
|
// Add browser package
|
||
|
|
if (settings.addsAndroidBrowser) {
|
||
|
|
dependenciesNode.ReplaceContentOrAddStartsWith(browserPrefix, browserPrefix + browserVersion + "'");
|
||
|
|
Debug.Log("<UniWebView> Updated Browser dependency in build.gradle.");
|
||
|
|
}
|
||
|
|
|
||
|
|
// Add Android X Core package
|
||
|
|
if (!settings.addsAndroidBrowser && settings.addsAndroidXCore) {
|
||
|
|
// When adding android browser to the project, we don't need to add Android X Core package, since gradle resolves for it.
|
||
|
|
dependenciesNode.ReplaceContentOrAddStartsWith(androidXCorePrefix, androidXCorePrefix + androidXCoreVersion + "'");
|
||
|
|
Debug.Log("<UniWebView> Updated Android X Core dependency in build.gradle.");
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
Debug.LogError("UniWebViewPostBuildProcessor didn't find the `dependencies` field in build.gradle.");
|
||
|
|
Debug.LogError("Although we can continue to add a `dependencies`, make sure you have setup Gradle and the template correctly.");
|
||
|
|
|
||
|
|
var newNode = new UniWebViewGradleNode("dependencies", config.Root);
|
||
|
|
if (settings.addsKotlin) {
|
||
|
|
newNode.AppendContentNode(kotlinPrefix + kotlinVersion + "'");
|
||
|
|
}
|
||
|
|
if (settings.addsAndroidBrowser) {
|
||
|
|
newNode.AppendContentNode(browserPrefix + browserVersion + "'");
|
||
|
|
}
|
||
|
|
|
||
|
|
if (settings.addsAndroidXCore) {
|
||
|
|
newNode.AppendContentNode(androidXCorePrefix + androidXCoreVersion + "'");
|
||
|
|
}
|
||
|
|
newNode.AppendContentNode("implementation(name: 'UniWebView', ext:'aar')");
|
||
|
|
config.Root.AppendChildNode(newNode);
|
||
|
|
}
|
||
|
|
config.Save();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void PatchGradleProperty(string root) {
|
||
|
|
var gradlePropertyFilePath = GetGradlePropertyFilePath(root);
|
||
|
|
var patcher =
|
||
|
|
new UniWebViewGradlePropertyPatcher(gradlePropertyFilePath, UniWebViewEditorSettings.GetOrCreateSettings());
|
||
|
|
patcher.Patch();
|
||
|
|
}
|
||
|
|
|
||
|
|
private string CombinePaths(string[] paths) {
|
||
|
|
var path = "";
|
||
|
|
foreach (var item in paths) {
|
||
|
|
path = Path.Combine(path, item);
|
||
|
|
}
|
||
|
|
return path;
|
||
|
|
}
|
||
|
|
|
||
|
|
private string GetManifestFilePath(string root) {
|
||
|
|
string[] comps = {root, "src", "main", "AndroidManifest.xml"};
|
||
|
|
return CombinePaths(comps);
|
||
|
|
}
|
||
|
|
|
||
|
|
private string GetGradleFilePath(string root) {
|
||
|
|
string[] comps = {root, "build.gradle"};
|
||
|
|
return CombinePaths(comps);
|
||
|
|
}
|
||
|
|
|
||
|
|
private string GetGradlePropertyFilePath(string root) {
|
||
|
|
#if UNITY_2019_3_OR_NEWER
|
||
|
|
string[] compos = {root, "..", "gradle.properties"};
|
||
|
|
#else
|
||
|
|
string[] compos = {root, "gradle.properties"};
|
||
|
|
#endif
|
||
|
|
return CombinePaths(compos);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endif
|