From 0137ee32220d75a282d105484d6c1ba71d63df4c Mon Sep 17 00:00:00 2001 From: Trudy Date: Sun, 9 Jun 2024 11:59:29 -0700 Subject: [PATCH] add CI/CD for nuget --- .github/workflows/nuget-main.yml | 43 ++++++ Sample/Sample.csproj | 2 +- VpnHood.Client.App.Android.Ads.UnityAds.sln | 7 +- .../AdException.cs | 13 -- .../AdLoadException.cs | 13 -- .../UnityAdService.cs | 138 ++++++++---------- ...ood.Client.App.Android.Ads.UnityAds.csproj | 2 +- 7 files changed, 114 insertions(+), 104 deletions(-) create mode 100644 .github/workflows/nuget-main.yml delete mode 100644 VpnHood.Client.App.Android.Ads.UnityAds/AdException.cs delete mode 100644 VpnHood.Client.App.Android.Ads.UnityAds/AdLoadException.cs diff --git a/.github/workflows/nuget-main.yml b/.github/workflows/nuget-main.yml new file mode 100644 index 0000000..b4cce84 --- /dev/null +++ b/.github/workflows/nuget-main.yml @@ -0,0 +1,43 @@ +name: Publish Nugets + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + + env: + BUILD_CONFIG: 'Release' + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Bump versions + uses: SiqiLu/dotnet-bump-version@2.0.0 + with: + version_files: "**/VpnHood.Client.App.Android.Ads.UnityAds.csproj" + version_mask: 0.0.1.0 + version_overwrite: "*.*.*.*" + github_token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup .NET + uses: actions/setup-dotnet@v2 + with: + dotnet-version: 8.0.x + + - name: Restore dependencies + run: dotnet restore + + - name: Build Solution + run: dotnet build --no-restore --configuration $BUILD_CONFIG + + - name: Pack All Projects + run: dotnet pack --configuration $BUILD_CONFIG -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg + + - name: Publish + run: nuget push **\*.nupkg -Source 'https://api.nuget.org/v3/index.json' -ApiKey ${{secrets.NUGET_API_KEY}} diff --git a/Sample/Sample.csproj b/Sample/Sample.csproj index 5b56276..7c05d65 100644 --- a/Sample/Sample.csproj +++ b/Sample/Sample.csproj @@ -1,7 +1,7 @@ net8.0-android - 24 + 23 Exe enable enable diff --git a/VpnHood.Client.App.Android.Ads.UnityAds.sln b/VpnHood.Client.App.Android.Ads.UnityAds.sln index e90916c..6925c0a 100644 --- a/VpnHood.Client.App.Android.Ads.UnityAds.sln +++ b/VpnHood.Client.App.Android.Ads.UnityAds.sln @@ -5,7 +5,12 @@ VisualStudioVersion = 17.10.34928.147 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VpnHood.Client.App.Android.Ads.UnityAds", "VpnHood.Client.App.Android.Ads.UnityAds\VpnHood.Client.App.Android.Ads.UnityAds.csproj", "{63761376-9057-4A2C-B45B-E25049D0FAC6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample", "Sample\Sample.csproj", "{A9B2B42A-B01B-47C1-AE52-3591349139AF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample", "Sample\Sample.csproj", "{A9B2B42A-B01B-47C1-AE52-3591349139AF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B7A98153-A1DD-4080-AC02-A4C63CBEDC5C}" + ProjectSection(SolutionItems) = preProject + .github\workflows\nuget-main.yml = .github\workflows\nuget-main.yml + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/VpnHood.Client.App.Android.Ads.UnityAds/AdException.cs b/VpnHood.Client.App.Android.Ads.UnityAds/AdException.cs deleted file mode 100644 index fb3920d..0000000 --- a/VpnHood.Client.App.Android.Ads.UnityAds/AdException.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace VpnHood.Client.App.Droid.Ads.VhUnityAds; - -public class AdException : Exception -{ - public AdException(string message, Exception innerException) : base(message, innerException) - { - - } - - public AdException(string message) : base(message) - { - } -} \ No newline at end of file diff --git a/VpnHood.Client.App.Android.Ads.UnityAds/AdLoadException.cs b/VpnHood.Client.App.Android.Ads.UnityAds/AdLoadException.cs deleted file mode 100644 index a1f219d..0000000 --- a/VpnHood.Client.App.Android.Ads.UnityAds/AdLoadException.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace VpnHood.Client.App.Droid.Ads.VhUnityAds; - -public class AdLoadException : Exception -{ - public AdLoadException(string message) : base(message) - { - } - - public AdLoadException(string message, Exception innerException) : base(message, innerException) - { - - } -} \ No newline at end of file diff --git a/VpnHood.Client.App.Android.Ads.UnityAds/UnityAdService.cs b/VpnHood.Client.App.Android.Ads.UnityAds/UnityAdService.cs index fc9e8fc..ffe1917 100644 --- a/VpnHood.Client.App.Android.Ads.UnityAds/UnityAdService.cs +++ b/VpnHood.Client.App.Android.Ads.UnityAds/UnityAdService.cs @@ -1,19 +1,19 @@ -using Com.Unity3d.Ads; +using Android.Content; +using Com.Unity3d.Ads; using VpnHood.Client.App.Abstractions; using VpnHood.Client.Device; using VpnHood.Client.Device.Droid; +using VpnHood.Common.Exceptions; using VpnHood.Common.Utils; namespace VpnHood.Client.App.Droid.Ads.VhUnityAds; public class UnityAdService(string adGameId, string adPlacementId, bool testMode = false) : IAppAdService { - private MyAdInitializationListener? _adInitializationListener; - private MyAdLoadListener? _adLoadListener; - private MyAdShowListener? _adShowListener; - private DateTime _lastLoadAdTime = DateTime.MinValue; private static bool _isUnityAdInitialized; - private static bool _isUnityAdLoaded; + public string NetworkName => "UnityAds"; + public AppAdType AdType => AppAdType.InterstitialAd; + public DateTime? AdLoadedTime { get; private set; } public static UnityAdService Create(string adGameId, string adPlacementId, bool testMode = false) { @@ -23,12 +23,25 @@ public static UnityAdService Create(string adGameId, string adPlacementId, bool public bool IsCountrySupported(string countryCode) { - throw new NotImplementedException(); + return countryCode != "IR"; } - public string NetworkName => "UnityAds"; - public AppAdType AdType => AppAdType.InterstitialAd; - public DateTime? AdLoadedTime { get; } + private async Task EnsureUnityAdInitialized(Context context, CancellationToken cancellationToken) + { + if (_isUnityAdInitialized) + return; + + var adInitializationListener = new MyAdInitializationListener(); + UnityAds.Initialize(context, adGameId, testMode, adInitializationListener); + + var cancellationTask = new TaskCompletionSource(); + cancellationToken.Register(cancellationTask.SetResult); + await Task.WhenAny(adInitializationListener.Task, cancellationTask.Task).VhConfigureAwait(); + cancellationToken.ThrowIfCancellationRequested(); + + await adInitializationListener.Task.VhConfigureAwait(); + _isUnityAdInitialized = true; + } public async Task LoadAd(IUiContext uiContext, CancellationToken cancellationToken) { @@ -37,57 +50,23 @@ public async Task LoadAd(IUiContext uiContext, CancellationToken cancellationTok if (activity.IsDestroyed) throw new AdException("MainActivity has been destroyed before loading the ad."); - // Initialize ad - if (!_isUnityAdInitialized) - { - try - { - _adInitializationListener = new MyAdInitializationListener(); - activity.RunOnUiThread(() => UnityAds.Initialize( - activity, adGameId, testMode, _adInitializationListener)); - - var cancellationTask = new TaskCompletionSource(); - cancellationToken.Register(cancellationTask.SetResult); - await Task.WhenAny(_adInitializationListener.Task, cancellationTask.Task).VhConfigureAwait(); - cancellationToken.ThrowIfCancellationRequested(); - - _isUnityAdInitialized = await _adInitializationListener.Task.VhConfigureAwait(); - - } - catch (Exception ex) when (ex is not OperationCanceledException) - { - _isUnityAdInitialized = false; - if (ex is AdLoadException) throw; - throw new AdLoadException($"Failed to load {AdType}.", ex); - } - } - - // Ad already loaded - if (_adLoadListener != null && _lastLoadAdTime.AddHours(1) < DateTime.Now) - _isUnityAdLoaded = await _adLoadListener.Task.VhConfigureAwait(); + // Initialize unity + await EnsureUnityAdInitialized(activity, cancellationToken); + // reset the last loaded ad + AdLoadedTime = null; // Load a new Ad - try - { - _adLoadListener = new MyAdLoadListener(); - activity.RunOnUiThread(() => UnityAds.Load(adPlacementId, _adLoadListener)); + var adLoadListener = new MyAdLoadListener(); + activity.RunOnUiThread(() => UnityAds.Load(adPlacementId, adLoadListener)); - var cancellationTask = new TaskCompletionSource(); - cancellationToken.Register(cancellationTask.SetResult); - await Task.WhenAny(_adLoadListener.Task, cancellationTask.Task).VhConfigureAwait(); - cancellationToken.ThrowIfCancellationRequested(); + var cancellationTask = new TaskCompletionSource(); + cancellationToken.Register(cancellationTask.SetResult); + await Task.WhenAny(adLoadListener.Task, cancellationTask.Task).VhConfigureAwait(); + cancellationToken.ThrowIfCancellationRequested(); - _isUnityAdLoaded = await _adLoadListener.Task.VhConfigureAwait(); - _lastLoadAdTime = DateTime.Now; - } - catch (Exception ex) when (ex is not OperationCanceledException) - { - _isUnityAdLoaded = false; - _lastLoadAdTime = DateTime.MinValue; - if (ex is AdLoadException) throw; - throw new AdLoadException($"Failed to load {AdType}.", ex); - } + await adLoadListener.Task.VhConfigureAwait(); + AdLoadedTime = DateTime.Now; } public async Task ShowAd(IUiContext uiContext, string? customData, CancellationToken cancellationToken) @@ -97,30 +76,37 @@ public async Task ShowAd(IUiContext uiContext, string? customData, CancellationT if (activity.IsDestroyed) throw new AdException("MainActivity has been destroyed before showing the ad."); - if (!_isUnityAdLoaded) + if (AdLoadedTime == null) throw new AdException($"The {AdType} has not been loaded."); - _adShowListener = new MyAdShowListener(); - activity.RunOnUiThread(() => UnityAds.Show(activity, adPlacementId, _adShowListener)); + try + { - // wait for show or dismiss - var cancellationTask = new TaskCompletionSource(); - cancellationToken.Register(cancellationTask.SetResult); - await Task.WhenAny(_adShowListener.Task, cancellationTask.Task).VhConfigureAwait(); - cancellationToken.ThrowIfCancellationRequested(); + var adShowListener = new MyAdShowListener(); + activity.RunOnUiThread(() => UnityAds.Show(activity, adPlacementId, adShowListener)); + + // wait for show or dismiss + var cancellationTask = new TaskCompletionSource(); + cancellationToken.Register(cancellationTask.SetResult); + await Task.WhenAny(adShowListener.Task, cancellationTask.Task).VhConfigureAwait(); + cancellationToken.ThrowIfCancellationRequested(); - await _adShowListener.Task.VhConfigureAwait(); - _isUnityAdLoaded = false; + await adShowListener.Task.VhConfigureAwait(); + } + finally + { + AdLoadedTime = null; + } } private class MyAdInitializationListener : Java.Lang.Object, IUnityAdsInitializationListener { - private readonly TaskCompletionSource _loadedCompletionSource = new(); - public Task Task => _loadedCompletionSource.Task; + private readonly TaskCompletionSource _loadedCompletionSource = new(); + public Task Task => _loadedCompletionSource.Task; public void OnInitializationComplete() { - _loadedCompletionSource.TrySetResult(true); + _loadedCompletionSource.TrySetResult(); } public void OnInitializationFailed(UnityAds.UnityAdsInitializationError? error, string? message) @@ -132,12 +118,12 @@ public void OnInitializationFailed(UnityAds.UnityAdsInitializationError? error, private class MyAdLoadListener : Java.Lang.Object, IUnityAdsLoadListener { - private readonly TaskCompletionSource _loadedCompletionSource = new(); - public Task Task => _loadedCompletionSource.Task; + private readonly TaskCompletionSource _loadedCompletionSource = new(); + public Task Task => _loadedCompletionSource.Task; public void OnUnityAdsAdLoaded(string? adPlacementId) { - _loadedCompletionSource.TrySetResult(true); + _loadedCompletionSource.TrySetResult(); } public void OnUnityAdsFailedToLoad(string? adUnitId, UnityAds.UnityAdsLoadError? error, string? message) @@ -149,12 +135,12 @@ public void OnUnityAdsFailedToLoad(string? adUnitId, UnityAds.UnityAdsLoadError? private class MyAdShowListener : Java.Lang.Object, IUnityAdsShowListener { - private readonly TaskCompletionSource _loadedCompletionSource = new(); - public Task Task => _loadedCompletionSource.Task; + private readonly TaskCompletionSource _loadedCompletionSource = new(); + public Task Task => _loadedCompletionSource.Task; public void OnUnityAdsShowStart(string? adPlacementId) { - _loadedCompletionSource.TrySetResult(true); + _loadedCompletionSource.TrySetResult(); } public void OnUnityAdsShowFailure(string? adPlacementId, UnityAds.UnityAdsShowError? error, string? message) { @@ -169,7 +155,9 @@ public void OnUnityAdsShowComplete(string? adPlacementId, UnityAds.UnityAdsShowC { } } + public void Dispose() { + GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/VpnHood.Client.App.Android.Ads.UnityAds/VpnHood.Client.App.Android.Ads.UnityAds.csproj b/VpnHood.Client.App.Android.Ads.UnityAds/VpnHood.Client.App.Android.Ads.UnityAds.csproj index dd7a5da..e699d1e 100644 --- a/VpnHood.Client.App.Android.Ads.UnityAds/VpnHood.Client.App.Android.Ads.UnityAds.csproj +++ b/VpnHood.Client.App.Android.Ads.UnityAds/VpnHood.Client.App.Android.Ads.UnityAds.csproj @@ -2,7 +2,7 @@ VpnHood Android Ad Library for UnityAds net8.0-android - 24 + 23 VpnHood.Client.App.Droid.Ads.VhUnityAds