Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions UI/AndroidUpdate/AndroidUpdate.slnx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Solution>
<Project Path="src/AndroidUpdate.Android/AndroidUpdate.Android.csproj" />
</Solution>
33 changes: 33 additions & 0 deletions UI/AndroidUpdate/src/AndroidUpdate.Android/AndroidApp.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Android.App;
using Android.Runtime;
using AndroidUpdate.ViewModels;
using Avalonia;
using Avalonia.Android;

namespace AndroidUpdate.Android;

[global::Android.App.Application]
public class AndroidApp : AvaloniaAndroidApplication<App>
{
protected AndroidApp(nint javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
// Read real app version from package manager as early as possible
try
{
var pkgInfo = PackageManager?.GetPackageInfo(PackageName!, 0);
if (pkgInfo?.VersionName != null)
App.DeviceVersion = pkgInfo.VersionName;
}
catch { /* fallback to default "1.0.0.0" */ }
}

protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
{
// Register the Android-specific handler factory before Avalonia starts
App.HandlerFactory = (packageInfo, currentVersion) =>
new Services.AndroidUpdateHandler(packageInfo, currentVersion);

return base.CustomizeAppBuilder(builder)
.WithInterFont();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0-android</TargetFramework>
<SupportedOSPlatformVersion>23</SupportedOSPlatformVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>latest</LangVersion>
<ApplicationId>com.generalupdate.androidupdate</ApplicationId>
<ApplicationVersion>7</ApplicationVersion>
<ApplicationDisplayVersion>1.0.0.0</ApplicationDisplayVersion>
<ApplicationTitle>AndroidUpdate</ApplicationTitle>
<AndroidPackageFormat>apk</AndroidPackageFormat>
<AndroidEnableProfiledAot>false</AndroidEnableProfiledAot>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Avalonia" Version="12.0.3" />
<PackageReference Include="Avalonia.Android" Version="12.0.3" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="12.0.3" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="12.0.3" />
<PackageReference Include="AvaloniaUI.DiagnosticsSupport" Version="2.2.1">
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="Xamarin.AndroidX.Core.SplashScreen" Version="1.0.1.15" />
<AndroidResource Include="Icon.png">
<Link>Resources\drawable\Icon.png</Link>
</AndroidResource>
<AndroidResource Include="Resources\xml\file_paths.xml" />
<AndroidResource Include="Resources\xml\network_security_config.xml" />
</ItemGroup>

<!-- Reference the compiled GeneralUpdate.Avalonia.Android DLL -->
<ItemGroup>
<Reference Include="GeneralUpdate.Avalonia.Android">
<HintPath>libs\GeneralUpdate.Avalonia.Android.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
14 changes: 14 additions & 0 deletions UI/AndroidUpdate/src/AndroidUpdate.Android/App.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AndroidUpdate"
x:Class="AndroidUpdate.App"
RequestedThemeVariant="Default">

<Application.DataTemplates>
<local:ViewLocator/>
</Application.DataTemplates>

<Application.Styles>
<FluentTheme />
</Application.Styles>
</Application>
59 changes: 59 additions & 0 deletions UI/AndroidUpdate/src/AndroidUpdate.Android/App.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System;
using System.Net.Http;
using AndroidUpdate.ViewModels;
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;

namespace AndroidUpdate;

public partial class App : Avalonia.Application
{
/// <summary>
/// Static factory for creating platform-specific update handlers.
/// Set by the Android project (or other platform projects) during startup.
/// </summary>
public static Func<UpdatePackageDto, string, IAndroidUpdateHandler>? HandlerFactory { get; set; }

/// <summary>
/// The device's currently installed app version.
/// Set by the platform project on startup; falls back to "1.0.0.0".
/// </summary>
public static string DeviceVersion { get; set; } = "1.0.0.0";

public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}

public override void OnFrameworkInitializationCompleted()
{
var httpClient = new HttpClient();
httpClient.Timeout = TimeSpan.FromSeconds(30);

MainViewViewModel CreateViewModel() =>
new(httpClient, (pkg, ver) =>
{
if (HandlerFactory == null)
throw new InvalidOperationException(
"HandlerFactory not set. Ensure the platform project initializes it.");
return HandlerFactory(pkg, ver);
});

if (ApplicationLifetime is IActivityApplicationLifetime singleViewFactory)
{
// Android: use MainViewFactory for Activity-based lifetime
singleViewFactory.MainViewFactory = () =>
new Views.MainView { DataContext = CreateViewModel() };
}
else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform)
{
singleViewPlatform.MainView = new Views.MainView
{
DataContext = CreateViewModel()
};
}

base.OnFrameworkInitializationCompleted();
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions UI/AndroidUpdate/src/AndroidUpdate.Android/MainActivity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Android.App;
using Android.Content.PM;
using Avalonia;
using Avalonia.Android;

namespace AndroidUpdate.Android;

[Activity(
Label = "AndroidUpdate",
Theme = "@style/MyTheme.NoActionBar",
MainLauncher = true,
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)]
public class MainActivity : AvaloniaMainActivity
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.generalupdate.androidupdate"
android:versionCode="7"
android:versionName="1.0.0.0">
<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="36" />
<application android:label="AndroidUpdate"
android:theme="@style/MyTheme.NoActionBar"
android:networkSecurityConfig="@xml/network_security_config">
<!-- FileProvider for APK installation -->
<provider android:name="androidx.core.content.FileProvider"
android:authorities="com.generalupdate.androidupdate.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
<!-- Required for APK installation on Android 8+ -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<!-- Internet access for downloading updates -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- Write external storage for download directory -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector
android:name="vector"
android:width="128dp"
android:height="128dp"
android:viewportWidth="128"
android:viewportHeight="128">
<group
android:name="wrapper"
android:translateX="21"
android:translateY="21">
<group android:name="group">
<path
android:name="path"
android:pathData="M 74.853 85.823 L 75.368 85.823 C 80.735 85.823 85.144 81.803 85.761 76.602 L 85.836 41.76 C 85.225 18.593 66.254 0 42.939 0 C 19.24 0 0.028 19.212 0.028 42.912 C 0.028 66.357 18.831 85.418 42.18 85.823 L 74.853 85.823 Z"
android:strokeWidth="1"/>
<path
android:name="path_1"
android:pathData="M 43.059 14.614 C 29.551 14.614 18.256 24.082 15.445 36.743 C 18.136 37.498 20.109 39.968 20.109 42.899 C 20.109 45.831 18.136 48.301 15.445 49.055 C 18.256 61.716 29.551 71.184 43.059 71.184 C 47.975 71.184 52.599 69.93 56.628 67.723 L 56.628 70.993 L 71.344 70.993 L 71.344 44.072 C 71.357 43.714 71.344 43.26 71.344 42.899 C 71.344 27.278 58.68 14.614 43.059 14.614 Z M 29.51 42.899 C 29.51 35.416 35.576 29.35 43.059 29.35 C 50.541 29.35 56.607 35.416 56.607 42.899 C 56.607 50.382 50.541 56.448 43.059 56.448 C 35.576 56.448 29.51 50.382 29.51 42.899 Z"
android:strokeWidth="1"
android:fillType="evenOdd"/>
<path
android:name="path_2"
android:pathData="M 18.105 42.88 C 18.105 45.38 16.078 47.407 13.579 47.407 C 11.079 47.407 9.052 45.38 9.052 42.88 C 9.052 40.381 11.079 38.354 13.579 38.354 C 16.078 38.354 18.105 40.381 18.105 42.88 Z"
android:strokeWidth="1"/>
</group>
</group>
</vector>
</aapt:attr>
<target android:name="path">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:duration="1000"
android:valueFrom="#00ffffff"
android:valueTo="#161c2d"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="path_1">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:duration="1000"
android:valueFrom="#00ffffff"
android:valueTo="#f9f9fb"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="path_2">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:duration="1000"
android:valueFrom="#00ffffff"
android:valueTo="#f9f9fb"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
</animated-vector>
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector
android:name="vector"
android:width="128dp"
android:height="128dp"
android:viewportWidth="128"
android:viewportHeight="128">
<group
android:name="wrapper"
android:translateX="21"
android:translateY="21">
<group android:name="group">
<path
android:name="path"
android:pathData="M 74.853 85.823 L 75.368 85.823 C 80.735 85.823 85.144 81.803 85.761 76.602 L 85.836 41.76 C 85.225 18.593 66.254 0 42.939 0 C 19.24 0 0.028 19.212 0.028 42.912 C 0.028 66.357 18.831 85.418 42.18 85.823 L 74.853 85.823 Z"
android:fillColor="#00ffffff"
android:strokeWidth="1"/>
<path
android:name="path_1"
android:pathData="M 43.059 14.614 C 29.551 14.614 18.256 24.082 15.445 36.743 C 18.136 37.498 20.109 39.968 20.109 42.899 C 20.109 45.831 18.136 48.301 15.445 49.055 C 18.256 61.716 29.551 71.184 43.059 71.184 C 47.975 71.184 52.599 69.93 56.628 67.723 L 56.628 70.993 L 71.344 70.993 L 71.344 44.072 C 71.357 43.714 71.344 43.26 71.344 42.899 C 71.344 27.278 58.68 14.614 43.059 14.614 Z M 29.51 42.899 C 29.51 35.416 35.576 29.35 43.059 29.35 C 50.541 29.35 56.607 35.416 56.607 42.899 C 56.607 50.382 50.541 56.448 43.059 56.448 C 35.576 56.448 29.51 50.382 29.51 42.899 Z"
android:fillColor="#00ffffff"
android:strokeWidth="1"
android:fillType="evenOdd"/>
<path
android:name="path_2"
android:pathData="M 18.105 42.88 C 18.105 45.38 16.078 47.407 13.579 47.407 C 11.079 47.407 9.052 45.38 9.052 42.88 C 9.052 40.381 11.079 38.354 13.579 38.354 C 16.078 38.354 18.105 40.381 18.105 42.88 Z"
android:fillColor="#00ffffff"
android:strokeWidth="1"/>
</group>
</group>
</vector>
</aapt:attr>
<target android:name="path_2">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:startOffset="100"
android:duration="900"
android:valueFrom="#00ffffff"
android:valueTo="#161c2d"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="path">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:duration="500"
android:valueFrom="#00ffffff"
android:valueTo="#f9f9fb"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="path_1">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:startOffset="100"
android:duration="900"
android:valueFrom="#00ffffff"
android:valueTo="#161c2d"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
</animated-vector>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<item>
<color android:color="@color/splash_background"/>
</item>

<item android:drawable="@drawable/icon"
android:width="120dp"
android:height="120dp"
android:gravity="center" />

</layer-list>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="splash_background">#212121</color>
</resources>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8" ?>
<resources>

<style name="MyTheme">
</style>

<style name="MyTheme.NoActionBar" parent="@style/Theme.AppCompat.NoActionBar">
<item name="android:windowActionBar">false</item>
<item name="android:windowBackground">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowSplashScreenBackground">@color/splash_background</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/avalonia_anim</item>
<item name="android:windowSplashScreenAnimationDuration">1000</item>
<item name="postSplashScreenTheme">@style/MyTheme.Main</item>

</style>
<style name="MyTheme.Main"
parent ="MyTheme.NoActionBar">
<item name="android:windowIsTranslucent">true</item>
</style>
</resources>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="splash_background">#FFFFFF</color>
</resources>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8" ?>
<resources>

<style name="MyTheme">
</style>

<style name="MyTheme.NoActionBar" parent="@style/Theme.AppCompat.DayNight.NoActionBar">
<item name="android:windowActionBar">false</item>
<item name="android:windowBackground">@drawable/splash_screen</item>
<item name="android:windowNoTitle">true</item>
</style>
</resources>
Loading
Loading