Xamarin.Forms open downloaded pdf directly - xamarin

I'm able to save a pdf file locally on the phone in the downloads folder. Now I want to be able to open the file in the generic pdf viewer. This is the file I have for example:
When opening directly from the downloads folder I'm getting this view:
How can I open the document in the same viewer as soon as the document is downloaded?
I tried this:
Device.OpenUri(new System.Uri("file:///storage/emulated/0/Download/740067_Invoice_Food.pdf"));
But nothing is happening.

Try this approach, maybe you'll need to change folder path using Environment.SpecialFolder
var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var filename = Path.Combine(documents, "MyPDF.pdf");
Device.OpenUri(new Uri(filename));

First specify fileprovider into android manifest file
Something like this
<application android:label="The name of your project" android:supportsRtl="true" android:icon="#drawable/register">
<provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="#xml/provider_paths"></meta-data>
</provider>
</application>
Next, add provider_paths.xml file into xml folder
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
Now you should call native method for each platform by 'DependencyService' to open pdf file
Do it according to this GREAT Doc
https://officialdoniald.azurewebsites.net/2019/09/24/xamarin-forms-save-and-open-pdf-file/

Related

Preserving ICommand during Linking

In my Xamarin.Forms code I use ICommand several times for creating hyperlinks.
The code works fine during debugging, but the command gets removed during release by the linker.
I created an XML file in the root of my Android project with its Build Action set to LinkDescription, that has the following code:
<?xml version="1.0" encoding="utf-8" ?>
<linker>
<assembly fullname="System">
<type fullname="System.Windows.Input.ICommand"></type>
</assembly>
</linker>
I expected that would preserve the command, but no; the links again don't work during release. Am I doing something wrong?
I don't know why the XML solution did not work, but here is what worked in my case:
Using the [Preserve] attribute before each ICommand had the desired effect during Release!
You've got the wrong assembly. The easiest way to figure out the right assembly is to CTRL + Click the symbol ICommand in a Xamarin project, which will open a decompiler window with the assembly in a #region at the top of the file.
#region Assembly netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
// C:\Program Files\dotnet\sdk\NuGetFallbackFolder\netstandard.library\2.0.3\build\netstandard2.0\ref\netstandard.dll
#endregion
Now change the XML to:
<?xml version="1.0" encoding="utf-8" ?>
<linker>
<assembly fullname="netstandard">
<type fullname="System.Windows.Input.ICommand" />
</assembly>
</linker>

Prevent content files to be added on Nuget restore

We have some executables which we need to create our setups. So we have packed
the external dependencies which are some .exe files into a nuget package. But on NuGet restore they are added to project root.
How can we achieve this ?
Have searched around but haven't found any solution so far.
Since we use nuspec file, this is what i have it as:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>VCRedistributable</id>
<version>$version$</version>
<title>VCRedistributable</title>
<authors>--</authors>
<owners>--</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>InstallVCRedistributable assemblies</description>
<contentFiles>
<files include="**" exclude="**" buildAction="None" copyToOutput="false"
/>
</contentFiles>
</metadata>
<files>
<file src="VC\x86\*.*" target="content\x86" />
<file src="VC\x64\*.*" target="content\x64" />
</files>
Any ideas ?
Prevent content files to be added on Nuget restore
You should target to the tools folder instead of content folder.
So, your .nupsec file should be:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>VCRedistributable</id>
<version>$version$</version>
<title>VCRedistributable</title>
<authors>--</authors>
<owners>--</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>InstallVCRedistributable assemblies</description>
</metadata>
<files>
<file src="VC\x86\*.*" target="tools\x86" />
<file src="VC\x64\*.*" target="tools\x64" />
</files>
</package>
That because the content directory is a convention-based working directory, which contents are copied to the project root:
Convention-based working directory:
Besides, if you nuget package just include external some .exe files, you do not have to add the contentFiles label, this label is used for the content file for packagereference.
<contentFiles>
<files include="**" exclude="**" buildAction="None" copyToOutput="false"
/>
</contentFiles>
If you are interested in, you can check this document for some more details.
Update:
Is it good convention to create our own folder structure other than
NuGet defined since based on the tools folder description from above
it seems they will be accessible via Package Manager Console.
Of course, you can use your own folder structure other than NuGet defined. But you need to notice that there will be a limit to do this. You can NOT just include your own folder structure, you need also need add a NuGet defined folder structure in your .nuspec, otherwise, nuget will install failed with the error like:
Could not install package 'MyCustomPackage 1.0.0'. You are trying to
install this package into a project that targets
'.NETFramework,Version=v4.6.1', but the package does not contain any
assembly references or content files that are compatible with that
framework.
Because nuget did not detect that you added assembly references or content files to the project.
Hope this helps.

Xcode / Cordova build: how to automate the population of "Linked Frameworks and Libraries"

After I cordova platform rm ios and cordova platform add ios, once I prepare my app I have to go into Xcode and manually relink all of the required frameworks and libraries.
Is there a way to automate this or at the very least, save this list so I can add it easily?
As far as I know, you can't specify frameworks within the config.xml.
You can specify them within a plugin's plugin.xml,
so one workaround would be to create a barebones dummy plugin consisting of just a plugin.xml with a list of all the frameworks your app needs; something like this:
<?xml version="1.0" encoding="UTF-8"?>
<plugin
xmlns="http://apache.org/cordova/ns/plugins/1.0"
id="my-custom-frameworks-plugin"
version="0.0.1">
<engines>
<engine name="cordova" version=">=3.0.0" />
</engines>
<platform name="ios">
<framework src="MapKit.framework" />
<framework src="Social.framework" />
</platform>
</plugin>
You'd then add the plugin to your app using it's local path: cordova plugin add /path/to/my/plugin
And then specify it using a <plugin> element in your config.xml:
<plugin name="my-custom-frameworks-plugin" version="0"/>
Each time you remove then add the platform, the plugin will be re-added and the referenced frameworks added to the XCode .plist file.
Alternatively, you could write a custom after_platform_add hook to read <framework> elements directly from the config.xml and update the .plist file.

Enforcing files in a folder have build action = Embedded Resource with target files

The Visual Studio project has a folder containing sql scripts and all files in it must have the build action set to Embedded Resource. While adding new files, developers often forget to change the build action.
I want to create a target file that throws an error a compile time if any of the files in the folder do not have the correct build action.
I have seen something similar done before.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0"
DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="MakeSureSqlFilesAreSetToCopyAlways" BeforeTargets="PrepareForBuild">
<Error Condition="!('%(Content.CopyToOutputDirectory)' == 'Always')"
Text="This Content file is not configured to Copy Always: [%(Content.FullPath)]" />
</Target>
</Project>
This block of code checks if the files are set to copy always. How do I check build action?
Would appreciate some links to further reading on this topic as well.
Thanks in advance.
Assuming that script files are in a folder called Scripts, the following target file will raise an error if there's any file with build action set to Content and if their path contains the word Scripts.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0"
DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="MakeSureSqlFilesAreSetToEmbeddedAsResource" BeforeTargets="PrepareForBuild">
<Error Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('%(Content.FullPath)', 'Scripts'))"
Text="This Content file is not configured as Embedded Resource: [%(Content.FullPath)]" />
</Target>
</Project>
If you're dealing with developers who forget to set their scripts as Embedded Resource, the above should be enough (though not comprehensive), mainly because Visual Studio sets the build action for new files to Content by default. If you want to make it bullet proof simply repeat the Error tag and replace Content with all possible build actions (except EmbeddedResource).

Incorrect version number apk

I have the following problem.
We have build an app with mono for android. The first version was no problem.
versionnumber was 1.0 and that is correct.
Meanwhile we have an update ready for this app. I changed the versionnumber in the manifest from '1' to '2'
and the versionname from '1.0' to '1.1'. But after I install the app on my phone I still see version '1.0'.
Also when I try to update de app in the market I get the error:
"The new apk's versioncode (1) already exists." (I'm sure I changed the versioncode to '2' in the manifest.)
What is going wrong?
Goldhorn
Did you change versionCumber or versionCode?
The correct attribute is versionCode (I don't know about versionNumber):
android:versionCode="1" android:versionName="0.1"
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="preferExternal"
package="com.jamwarehouse.apps.evolution"
android:versionCode="1"
android:versionName="0.1">
<application android:label="Evolution">
</application>
<uses-sdk android:minSdkVersion="4" />
</manifest>
Anyway, if you are using Mono for Android, you shouldn't need to edit the AndroidManifest.xml at all. You use C# attributes on your classes and you edit the version details via the project properties:
[Activity(Label = "Timeband", MainLauncher = true, Icon = "#drawable/icon")]
public class TimebandActivity : Activity
{
...
}
Note: I did notice that if I edited a field and then pressed close of the tab, it didn't save. You have to click out of the text boxes first, then close/save.
I Have found the problem.
I had to include my AndroidManifest.xml in my .csproj file. After that I had to add some more configurations from the C# code to the androidmanifest. I now use both the C# attributes and a manual AndroidManifest (which will be combined by Mono for Android).

Resources