Skip to content

Commit

Permalink
Fix for Android release builds not loading libpdfium correctly (#46)
Browse files Browse the repository at this point in the history
  • Loading branch information
sungaila authored Oct 11, 2023
1 parent 5d23c47 commit c839acd
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 112 deletions.
2 changes: 1 addition & 1 deletion src/Console/Console.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<AssemblyName>PDFtoImage.Console</AssemblyName>
<RootNamespace>PDFtoImage.Console</RootNamespace>
<StartupObject>PDFtoImage.Console.Program</StartupObject>
<Version>2.4.1</Version>
<Version>2.4.2</Version>
<Configurations>Debug;Release;ReleaseSigned</Configurations>
</PropertyGroup>

Expand Down
15 changes: 7 additions & 8 deletions src/PDFtoImage/PDFtoImage.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

<!-- NuGet -->
<PropertyGroup>
<VersionPrefix>2.4.1</VersionPrefix>
<VersionPrefix>2.4.2</VersionPrefix>
<VersionSuffix></VersionSuffix>
<Authors>David Sungaila</Authors>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
Expand All @@ -21,8 +21,7 @@
<PackageProjectUrl>https://github.com/sungaila/PDFtoImage</PackageProjectUrl>
<PackageIconUrl>https://raw.githubusercontent.com/sungaila/PDFtoImage/master/etc/Icon_128.png</PackageIconUrl>
<Description>A .NET library to render PDF files into images.</Description>
<PackageReleaseNotes>- Fixed an issue where password protected PDF files could not be opened.
- Added PDF specific Exception classes (e.g. PdfPasswordProtectedException).</PackageReleaseNotes>
<PackageReleaseNotes>- Fixed an issue where Android release builds would fail to load libpdfium.</PackageReleaseNotes>
<PackageTags>PDF Bitmap Image Convert Conversion C# PDFium SkiaSharp Skia PNG JPG JPEG WEBP Xamarin Android MonoAndroid MAUI WASM WebAssembly</PackageTags>
<RepositoryUrl>https://github.com/sungaila/PDFtoImage.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
Expand Down Expand Up @@ -84,15 +83,15 @@
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)'=='net462' or '$(TargetFramework)'=='net481'">
<PackageReference Include="bblanchon.PDFium.Win32" Version="119.0.6029" PrivateAssets="analyzers" />
<PackageReference Include="bblanchon.PDFium.Win32" Version="120.0.6056" PrivateAssets="analyzers" />
<PackageReference Include="SkiaSharp.NativeAssets.Win32" Version="2.88.6" PrivateAssets="analyzers" />
</ItemGroup>

<!-- .NET packages -->
<ItemGroup Condition="'$(TargetFramework)'=='net6.0' or '$(TargetFramework)'=='net7.0'">
<PackageReference Include="bblanchon.PDFium.Linux" Version="119.0.6029" PrivateAssets="analyzers" />
<PackageReference Include="bblanchon.PDFium.macOS" Version="119.0.6029" PrivateAssets="analyzers" />
<PackageReference Include="bblanchon.PDFium.Win32" Version="119.0.6029" PrivateAssets="analyzers" />
<PackageReference Include="bblanchon.PDFium.Linux" Version="120.0.6056" PrivateAssets="analyzers" />
<PackageReference Include="bblanchon.PDFium.macOS" Version="120.0.6056" PrivateAssets="analyzers" />
<PackageReference Include="bblanchon.PDFium.Win32" Version="120.0.6056" PrivateAssets="analyzers" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.88.6" PrivateAssets="analyzers" />
<PackageReference Include="SkiaSharp.NativeAssets.macOS" Version="2.88.6" PrivateAssets="analyzers" />
<PackageReference Include="SkiaSharp.NativeAssets.Win32" Version="2.88.6" PrivateAssets="analyzers" />
Expand All @@ -101,7 +100,7 @@

<!-- Android packages -->
<ItemGroup Condition="'$(TargetFramework)'=='net7.0-android' or '$(TargetFramework)'=='monoandroid10.0'">
<PackageReference Include="bblanchon.PDFium.Android" Version="119.0.6029" PrivateAssets="analyzers" />
<PackageReference Include="bblanchon.PDFium.Android" Version="120.0.6056" PrivateAssets="analyzers" />
<PackageReference Include="SkiaSharp.NativeAssets.Android" Version="2.88.6" PrivateAssets="analyzers" />
</ItemGroup>

Expand Down
218 changes: 118 additions & 100 deletions src/PDFtoImage/PdfiumViewer/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,52 @@

namespace PDFtoImage.PdfiumViewer
{
internal static partial class NativeMethods
{
static NativeMethods()
{
// Load the platform dependent Pdfium.dll if it exist.
internal static partial class NativeMethods
{
static NativeMethods()
{
string? path = null;
try
{
#if NET7_0_OR_GREATER
string workingDirectory = Assembly.GetExecutingAssembly().Location;
if (string.IsNullOrWhiteSpace(workingDirectory))
workingDirectory = Environment.ProcessPath!;
if (string.IsNullOrWhiteSpace(workingDirectory))
workingDirectory = AppContext.BaseDirectory;
string workingDirectory = Assembly.GetExecutingAssembly().Location;
if (string.IsNullOrWhiteSpace(workingDirectory))
workingDirectory = Environment.ProcessPath!;
if (string.IsNullOrWhiteSpace(workingDirectory))
workingDirectory = AppContext.BaseDirectory;
#elif NET6_0_OR_GREATER
var workingDirectory = Assembly.GetExecutingAssembly().GetName(false).CodeBase;
if (string.IsNullOrWhiteSpace(workingDirectory))
workingDirectory = Environment.ProcessPath!;
if (string.IsNullOrWhiteSpace(workingDirectory))
workingDirectory = AppContext.BaseDirectory;
var workingDirectory = Assembly.GetExecutingAssembly().GetName(false).CodeBase;
if (string.IsNullOrWhiteSpace(workingDirectory))
workingDirectory = Environment.ProcessPath!;
if (string.IsNullOrWhiteSpace(workingDirectory))
workingDirectory = AppContext.BaseDirectory;
#else
var workingDirectory = Assembly.GetExecutingAssembly().GetName(false).CodeBase;
if (string.IsNullOrWhiteSpace(workingDirectory))
workingDirectory = Process.GetCurrentProcess().MainModule!.FileName!;
if (string.IsNullOrWhiteSpace(workingDirectory))
workingDirectory = AppContext.BaseDirectory;
var workingDirectory = Assembly.GetExecutingAssembly().GetName(false).CodeBase;
if (string.IsNullOrWhiteSpace(workingDirectory))
workingDirectory = Process.GetCurrentProcess().MainModule!.FileName!;
if (string.IsNullOrWhiteSpace(workingDirectory))
workingDirectory = AppContext.BaseDirectory;
#endif

LoadNativeLibrary(Path.GetDirectoryName(new Uri(workingDirectory).LocalPath)!);
}
path = Path.GetDirectoryName(new Uri(workingDirectory).LocalPath);
}
catch (Exception) { }

LoadNativeLibrary(path);
}

private static void LoadNativeLibrary(string path)
{
private static void LoadNativeLibrary(string? path = null)
{
#if ANDROID || MONOANDROID
LoadNativeLibraryAndroid();
#elif NET6_0_OR_GREATER
LoadNativeLibraryNetCore(path);
LoadNativeLibraryNetCore(path);
#elif NETFRAMEWORK
LoadNativeLibraryNetFX(path);
#else
throw new PlatformNotSupportedException("Unkown framework and/or platform.");
#endif
}
}

#if ANDROID || MONOANDROID
private static void LoadNativeLibraryAndroid()
Expand All @@ -64,86 +70,98 @@ private static void LoadNativeLibraryAndroid()
Java.Lang.JavaSystem.LoadLibrary("pdfium");
}
#elif NET6_0_OR_GREATER
private static void LoadNativeLibraryNetCore(string path)
{
if (path == null)
return;

string runtimeIdentifier;
string pdfiumLibName;

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
runtimeIdentifier = RuntimeInformation.ProcessArchitecture switch
{
Architecture.X86 => "win-x86",
Architecture.X64 => "win-x64",
Architecture.Arm64 => "win-arm64",
_ => throw new PlatformNotSupportedException("Only x86-64, x86 and arm64 are supported on Windows.")
};
pdfiumLibName = "pdfium.dll";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
runtimeIdentifier = RuntimeInformation.ProcessArchitecture switch
{
Architecture.X64 => "linux-x64",
Architecture.Arm => "linux-arm",
Architecture.Arm64 => "linux-arm64",
_ => throw new PlatformNotSupportedException("Only x86-64, arm and arm64 are supported on Linux.")
};
pdfiumLibName = "libpdfium.so";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
runtimeIdentifier = RuntimeInformation.ProcessArchitecture switch
{
Architecture.X64 => "osx-x64",
Architecture.Arm64 => "osx-arm64",
_ => throw new PlatformNotSupportedException("Only x86-64 and arm64 are supported on macOS.")
};
pdfiumLibName = "libpdfium.dylib";
}
else
{
throw new NotSupportedException("Only win-x86, win-x64, win-arm64, linux-x64, linux-arm, linux-arm64, osx-x64, and osx-arm64 are supported.");
}

LoadLibrary(path, runtimeIdentifier, pdfiumLibName);
}
private static void LoadNativeLibraryNetCore(string? path)
{
if (path == null)
return;

string runtimeIdentifier;
string pdfiumLibName;

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
runtimeIdentifier = RuntimeInformation.ProcessArchitecture switch
{
Architecture.X86 => "win-x86",
Architecture.X64 => "win-x64",
Architecture.Arm64 => "win-arm64",
_ => throw new PlatformNotSupportedException("Only x86-64, x86 and arm64 are supported on Windows.")
};
pdfiumLibName = "pdfium.dll";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
runtimeIdentifier = RuntimeInformation.ProcessArchitecture switch
{
Architecture.X64 => "linux-x64",
Architecture.Arm => "linux-arm",
Architecture.Arm64 => "linux-arm64",
_ => throw new PlatformNotSupportedException("Only x86-64, arm and arm64 are supported on Linux.")
};
pdfiumLibName = "libpdfium.so";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
runtimeIdentifier = RuntimeInformation.ProcessArchitecture switch
{
Architecture.X64 => "osx-x64",
Architecture.Arm64 => "osx-arm64",
_ => throw new PlatformNotSupportedException("Only x86-64 and arm64 are supported on macOS.")
};
pdfiumLibName = "libpdfium.dylib";
}
else if (OperatingSystem.IsMacCatalyst())
{
throw new NotSupportedException("Mac Catalyst is not supported.");
}
else if (OperatingSystem.IsIOS())
{
throw new NotSupportedException("iOS and Mac Catalyst are not supported.");
}
else if (OperatingSystem.IsTvOS())
{
throw new NotSupportedException("tvOS is not supported.");
}
else
{
throw new NotSupportedException("Only win-x86, win-x64, win-arm64, linux-x64, linux-arm, linux-arm64, osx-x64, and osx-arm64 are supported.");
}

LoadLibrary(path, runtimeIdentifier, pdfiumLibName);
}
#endif

#if !MONOANDROID && !ANDROID
private static string? _pdfiumLibPath;
private static string? _pdfiumLibPath;
#endif

#if NET6_0_OR_GREATER && !ANDROID
private static void LoadLibrary(string path, string runtimeIdentifier, string pdfiumLibName)
{
if (File.Exists(Path.Combine(path, pdfiumLibName)))
{
// dotnet publish with a given runtime identifier (not portable) will put PDFium into the root folder
_pdfiumLibPath = Path.Combine(path, pdfiumLibName);
}
else
{
// in any other case there should be a runtimes folder
_pdfiumLibPath = Path.Combine(path, "runtimes", runtimeIdentifier, "native", pdfiumLibName);
}

NativeLibrary.SetDllImportResolver(typeof(NativeMethods).Assembly, ImportResolver);
NativeLibrary.Load(_pdfiumLibPath, Assembly.GetExecutingAssembly(), default);
}

private static IntPtr ImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
{
if (_pdfiumLibPath != null && libraryName != null && libraryName.Contains("pdfium"))
return NativeLibrary.Load(_pdfiumLibPath, assembly, searchPath);

return IntPtr.Zero;
}
private static void LoadLibrary(string path, string runtimeIdentifier, string pdfiumLibName)
{
if (File.Exists(Path.Combine(path, pdfiumLibName)))
{
// dotnet publish with a given runtime identifier (not portable) will put PDFium into the root folder
_pdfiumLibPath = Path.Combine(path, pdfiumLibName);
}
else
{
// in any other case there should be a runtimes folder
_pdfiumLibPath = Path.Combine(path, "runtimes", runtimeIdentifier, "native", pdfiumLibName);
}

NativeLibrary.SetDllImportResolver(typeof(NativeMethods).Assembly, ImportResolver);
NativeLibrary.Load(_pdfiumLibPath, Assembly.GetExecutingAssembly(), default);
}

private static IntPtr ImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
{
if (_pdfiumLibPath != null && libraryName != null && libraryName.Contains("pdfium"))
return NativeLibrary.Load(_pdfiumLibPath, assembly, searchPath);

return IntPtr.Zero;
}
#elif NETFRAMEWORK
private static void LoadNativeLibraryNetFX(string path)
private static void LoadNativeLibraryNetFX(string? path)
{
if (path == null)
return;
Expand Down Expand Up @@ -185,5 +203,5 @@ private static void LoadNativeLibraryNetFX(string path)
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPWStr)] string lpLibFileName);
#endif
}
}
}
6 changes: 3 additions & 3 deletions src/WebConverter/WebConverter.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<AssemblyName>PDFtoImage.WebConverter</AssemblyName>
<RootNamespace>PDFtoImage.WebConverter</RootNamespace>
<StartupObject>PDFtoImage.WebConverter.Program</StartupObject>
<Version>2.4.1</Version>
<Version>2.4.2</Version>
<RunAOTCompilation>true</RunAOTCompilation>
<WasmNativeStrip>true</WasmNativeStrip>
<PublishTrimmed>true</PublishTrimmed>
Expand All @@ -34,8 +34,8 @@
<ItemGroup>
<PackageReference Include="ByteSize" Version="2.1.1" />
<PackageReference Include="Markdig.Signed" Version="0.33.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.11" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.11" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.12" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.12" PrivateAssets="all" />
<PackageReference Include="SkiaSharp.NativeAssets.WebAssembly" Version="2.88.6" />
<PackageReference Include="Thinktecture.Blazor.FileHandling" Version="2.0.0" />
<PackageReference Include="Thinktecture.Blazor.WebShare" Version="2.0.0" />
Expand Down

0 comments on commit c839acd

Please sign in to comment.