How to gain access to KnownFolders.DocumentsLibrary - c#

I'm trying to save a string of user inputs to a file in a windows runtime app. However I'm getting the error System.UnauthorizedAccessException. How do I gain access to this Library?
static private async Task WriteDataToFileAsync(string fileName, string content)
{
byte[] data = Encoding.Unicode.GetBytes(content);
var folder = KnownFolders.DocumentsLibrary;
var file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
using (var s = await file.OpenStreamForWriteAsync())
{
await s.WriteAsync(data, 0, data.Length);
}
}

"Documents library" capability in Visual Studio 2013 has been removed since it is only available for Windows Store Company accounts. Without this capability you will get "Access is denied".
For more information, read here: http://lunarfrog.com/blog/2013/07/05/documents-library-capability-winrt/

Like this, notice under 'Extensions' I specify the file type I want to access (.txt) and then under 'Capabilities' I have added 'documentsLibrary'.
Then to actually write or access a file from there, something like this.
var file = await KnownFolders.DocumentsLibrary.CreateFileAsync("myFile.txt", CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(file, data);
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest">
<Identity Name="testapp" Publisher="CN=test.test" Version="1.5.0.3" />
<Properties>
<DisplayName>test.MetroApp</DisplayName>
<PublisherDisplayName>test.test</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Prerequisites>
<OSMinVersion>6.3.0</OSMinVersion>
<OSMaxVersionTested>6.3.0</OSMaxVersionTested>
</Prerequisites>
<Resources>
<Resource Language="x-generate" />
</Resources>
<Applications>
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="test.MetroApp.App">
<m2:VisualElements DisplayName="test.MetroApp" Square150x150Logo="Assets\test.png" Square30x30Logo="Assets\SmallLogo.png" Description="test.MetroApp" ForegroundText="light" BackgroundColor="#464646">
<m2:SplashScreen Image="Assets\test.scale-620.png" BackgroundColor="#464646" />
<m2:InitialRotationPreference>
<m2:Rotation Preference="landscape" />
</m2:InitialRotationPreference>
</m2:VisualElements>
<Extensions>
<Extension Category="windows.fileTypeAssociation">
<FileTypeAssociation Name="1">
<DisplayName>AccessTXT</DisplayName>
<SupportedFileTypes>
<FileType>.txt</FileType>
</SupportedFileTypes>
</FileTypeAssociation>
</Extension>
</Extensions>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
<Capability Name="privateNetworkClientServer" />
<Capability Name="musicLibrary" />
<Capability Name="documentsLibrary" />
</Capabilities>
</Package>

According to the docs "your app must use the File Type Association declaration in the app manifest file to explicitly declare what file types (extensions) will be accessed or created in the Documents library".

Related

Open Video From Intent Xamarin

I can't run an intent to play a video from a folder saved in external storage specifically in DCMI/subdirectory.
Using this code I get the error:
'file:///storage/emulated/0/DCIM/subdirectory/video-213102-113126.mp4 exposed beyond app through Intent.getData()'
Java.IO.File file = new Java.IO.File(file_path);
Intent intent = new Intent();
intent.AddFlags(ActivityFlags.NewTask);
intent.SetAction(Intent.ActionView);
intent.SetDataAndType(Android.Net.Uri.FromFile(file), "video/mp4");
Xamarin.Forms.Forms.Context.StartActivity(intent);
Reading I saw that I have to use a Fileprovider so I tried with this code:
Java.IO.File file = new Java.IO.File(file_path);
Android.Net.Uri photoURI = AndroidX.Core.Content.FileProvider.GetUriForFile(Android.App.Application.Context, Android.App.Application.Context.PackageName + ".provider", file);
Android.Content.Intent intent = new Android.Content.Intent(Android.Content.Intent.ActionView);
intent.SetDataAndType(photoURI, "video/*");
Xamarin.Forms.Forms.Context.StartActivity(intent);
AndroidManifest:
<application android:label="MYAPP.Android" android:theme="#style/MainTheme" android:requestLegacyExternalStorage="true">
<activity android:name=".MainActivity"
android:screenOrientation="portrait"
android:configChanges="keyboard|keyboardHidden|orientation" />
<activity android:name=".CameraActivity"
android:screenOrientation="portrait"
android:configChanges="keyboard|keyboardHidden|orientation" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths" />
</provider>
</application>
provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="."/>
</paths>
In debugging I see that the file variable is /storage/emulated/0/DCIM/subdirectory/video-213703-033712.mp4}
and photoURI is {content://com.companyname.myapp.provider/external_files/DCIM/subdirectory/video-213703-033712.mp4}
Intent is launched but the video is not played probably because it does not find the file in the path

Writing to Application.persistentDataPath on HoloLens 2 with Unity3D and accessing files afterward through device web portal

I'm working on Hololens 2 application in Unity 3D. I'm trying to write a configuration file to the device and access it later via the device portal in a web browser. Within the application itself, I'm being told that the file is being written to AppData/Local/Packages/[App Name]/LocalState/[File Name].txt. However, when I go and take a look at LocalAppData/[App Name] the folder LocalState/ doesn't even exist. I suspect this has to do with an error in the Package.appxmanifest file of the VS project generated by Unity.
Here is the relevant C# code I'm using to write to file:
void ReadResolution()
{
string path = Path.Combine(Application.persistentDataPath, mResFilename);
mExcept = $"No exceptions thrown by file IO while writing to \n\"{path}\".";
if(System.IO.File.Exists(path) && new FileInfo(path).Length > 0)
{
try
{
StreamReader reader = new StreamReader(path);
if(reader != null)
{
string content = reader.ReadToEnd();
string[] split = content.Split(' ');
mWidth = Int32.Parse(split[0]);
mHeight = Int32.Parse(split[1]);
}
}
catch (Exception e)
{
mExcept = "File Read Exception: " + e.Message;
}
}
else
{
try
{
using (TextWriter writer = File.CreateText(path))
{
string line = mWidth.ToString() + " " + mHeight.ToString();
writer.WriteLine(line);
}
}
catch (Exception e)
{
mExcept = "File Write Exception: " + e.Message;
}
}
Debug.Log(mExcept);
}
I'm using the member field mExcept to record any messages or exceptions thrown during the process. It's telling me the file is written successfully, but maybe I'm just fooling myself somehow?
Here are the relevant sections from the project's Package.appxmanifest file:
<Package xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap2="http://schemas.microsoft.com/appx/manifest/uap/windows10/2"
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
xmlns:iot="http://schemas.microsoft.com/appx/manifest/iot/windows10"
xmlns:mobile="http://schemas.microsoft.com/appx/manifest/mobile/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap uap2 uap3 uap4 mp mobile iot rescap"
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10">
.
.
.
<Capabilities>
<rescap:Capability Name="broadFileSystemAccess" />
<uap:Capability Name="documentsLibrary" />
<Capability Name="internetClient" />
<Capability Name="internetClientServer" />
<Capability Name="privateNetworkClientServer" />
<uap2:Capability Name="spatialPerception" />
<uap3:Capability Name="remoteSystem" />
<DeviceCapability Name="microphone" />
<DeviceCapability Name="gazeinput" />
<DeviceCapability Name="wiFiControl" />
<DeviceCapability Name="webcam" />
</Capabilities>
Any help is appreciated. Thanks in advance.
Ok everybody, I figured it out.
In order to write to persistent storage, VS project generated by Unity needs to have another capability included in its Package.appxmanifest file that mine was missing. Namely, you need to declare the uap capability "removableStorage", in addition to whatever else you're using. As an example, this is what the capabilities section of my manifest file now looks like:
<Capabilities>
<uap:Capability Name="documentsLibrary" />
<Capability Name="internetClient" />
<Capability Name="internetClientServer" />
<Capability Name="privateNetworkClientServer" />
<uap:Capability Name="removableStorage" />
<uap:Capability Name="videosLibrary" />
<uap:Capability Name="objects3D" />
<uap2:Capability Name="spatialPerception" />
<DeviceCapability Name="webcam" />
<DeviceCapability Name="microphone" />
<DeviceCapability Name="location" />
<DeviceCapability Name="wiFiControl" />
</Capabilities>
Also, make sure you uninstall completely any old build on your device before installing the fixed version. That was causing me problems too.
Have a nice day :)
I also used Application.persistentDataPath in Unity which had to work on Hololens 2.
But however it did not work, ie; the file was not getting saved because I made an error (The list which I wanted to save, was not initialized to a new one).
After I corrected it, the file with the list gets saved on the persistantDatapath, and works without adding the above capability.

Telerik report only have PDF option, no Excel and Word option

When I generate Telerik Report , only Export PDF is available. Even I set the config of docx and xlsx to true. Here is my config in web config.
<configSections>
<section name="Telerik.Reporting" type="Telerik.Reporting.Configuration.ReportingConfigurationSection, Telerik.Reporting, Version=8.2.14.1027, Culture=neutral, PublicKeyToken=A9D7983DFCC261BE" allowLocation="true" allowDefinition="Everywhere" />
</configSections>
<Telerik.Reporting>
<AssemblyReferences>
<add name="BusinessObject.Client" version="1.0.0.0" />
<add name="BusinessObject.Client" version="1.0.0.0" />
</AssemblyReferences>
<Extensions>
<Render>
<Extension name="PDF" visible="true"></Extension>
<Extension name="XLS" visible="false"></Extension>
<Extension name="CSV" visible="false"></Extension>
<Extension name="RTF" visible="false"></Extension>
<Extension name="XPS" visible="false"></Extension>
<Extension name="DOCX" visible="true"></Extension>
<Extension name="XLSX" visible="true"></Extension>
<Extension name="PPTX" visible="false"></Extension>
<Extension name="MHTML" visible="false"></Extension>
<Extension name="IMAGE" visible="false"></Extension>
<Extension name="HTML5" visible="false"></Extension>
<Extension name="HTML5Interactive" visible="false"></Extension>
</Render>
</Extensions>
</Telerik.Reporting>
I am using Telerik for ASP.Net
Word, PowerPoint and Excel rendering extensions require
Telerik.Reporting.OpenXmlRendering.dll and Open XML SDK 2.0 for
Microsoft Office (DocumentFormat.OpenXml.dll v.2.0.5022.0 or
above). If you want to avoid the installation of Open XML SDK you can
copy the required DocumentFormat.OpenXml assembly from C:\Program
Files (x86)\Telerik\Reporting {version}\Examples\bin folder.
For more information on the topic check out the Deploying Web Applications help article.
link: telerik.com/forums/report-exporting-word-excel-ets

Xamarin Forms File Provider not set

I am currently going through the process of Learning Xamarin.Forms. I am currently attempting to implement Camera functions using the Plugin.Media.CrossMedia library.
Implemented below:
public async Task<ImageSource> StartCamera()
{
await CrossMedia.Current.Initialize();
if (Plugin.Media.CrossMedia.Current.IsTakePhotoSupported && CrossMedia.Current.IsCameraAvailable)
{
var photo = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions() { SaveToAlbum=false, SaveMetaData=false});
if (photo != null)
return ImageSource.FromStream(() => { return photo.GetStream(); });
else
return null;
}
else
{
return null;
}
}
However upon executing the 'TakePhotoAsync' method I recieve the following error.
System.ArgumentException: Unable to get file location. This most likely means that the file provider information is not set in your Android Manifest file. Please check documentation on how to set this up in your project.
I have tried looking this up but to no avail. My AndroidManifest.xml file looks like this at the moment.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="RCPTTracker.Android" android:versionCode="1" android:versionName="1.0">
<uses-sdk />
<application android:label="RCPTTracker.Android"></application>
</manifest>
My inkling is that I need to declare something in here, but I haven't been able to find what, and all tutorials i have followed don't go through anything with setting up a File Provider.
Any suggestions?
The readme says:
If your application targets Android N (API 24) or newer, you must use version 2.6.0+.
You must also add a few additional configuration files to adhere to the new strict mode:
1.) Add the following to your AndroidManifest.xml inside the tags:
<provider android:name="android.support.v4.content.FileProvider"
android:authorities="YOUR_APP_PACKAGE_NAME.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"></meta-data>
</provider>
YOUR_APP_PACKAGE_NAME must be set to your app package name!
2.) Add a new folder called xml into your Resources folder and add a new XML file called file_paths.xml
Add the following code:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="my_images" path="Pictures" />
<external-files-path name="my_movies" path="Movies" />
</paths>
YOUR_APP_PACKAGE_NAME must be set to your app package name!
You can read more at: https://developer.android.com/training/camera/photobasics.html
In my case it was because I had put the FileProvider in the wrong place in the AndroidManifest.xml file. It needed to be inside the <Application> tags.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.myapp.app1" android:installLocation="auto">
<uses-sdk android:minSdkVersion="22" android:targetSdkVersion="27" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.BROADCAST_WAP_PUSH" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECEIVE_WAP_PUSH" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<application android:label="app1.Android">
<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="AIzaSyCZF1O9_7-MXlxYfAEIxBQkr-dR8RiwiYE" />
<!-- ADD FILE PROVIDER HERE -->
<provider android:name="android.support.v4.content.FileProvider"
android:authorities="com.myapp.app1.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"></meta-data>
</provider>
</application>
</manifest>
The problem I had was related to case-sensitivity.
On the line below
<provider android:name="android.support.v4.content.FileProvider"
android:authorities="com.myexample.myapp.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
I erroneously had a single uppercase letter on the line android:authorities="com.myexample.myapp.fileProvider". It should be:
android:authorities="com.myexample.myapp.fileprovider" <!-- all lowercase -->
Or
android:authorities="${applicationId}.fileprovider"
The package name and value for android:authorities should be lowercase. Otherwise you will get the error:
System.ArgumentException: Unable to get file location. This most
likely means that the file provider information is not set in your
Android Manifest file. Please check documentation on how to set this
up in your project.
Make sure you only have one set of <application> tags
I was stuck on this error for literally weeks... Then I realised I had duplicate application tags.
defined once like this:
<application android:label="App2.Android"></application>
the second set of <application> tags had the correct configuration lower down, but were being ignored. Removing the empty tags solved the issue for me.
Marco's solution is almost right. For it to work in my project I had to change
android:authorities="YOUR_APP_PACKAGE_NAME.fileprovider"
to
android:authorities="${applicationId}.fileprovider"
in the AndroidManifest.xml file.
Above answers resolved this issue for me. Here's what my AndroidManifest.xml looks like (using ${applicationId} for the authorities tag helps because sometimes you just don't know exactly how your app name is):
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1" android:versionName="1.0" package="com.companyname.app2">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application android:label="App2.Android" android:theme="#style/MainTheme">
<provider android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"></meta-data>
</provider>
</application>
</manifest>
<provider android:name="androidx.core.content.FileProvider"
android:authorities="APP_PACKAGE_NAME.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"></meta-data>
</provider>
Xml must be in under xml folder
With the latest version, correct XML configuration is (without adding the package name to the path)
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="my_images" path="Pictures" />
<external-files-path name="my_movies" path="Movies" />
</paths>
If you set path combining the package name like below
<external-path name="my_images" path="Android/data/YOUR_APP_PACKAGE_NAME/files/Pictures" />
It may give this type of error.
Android Support Libraries are now in the androidx.* package hierarchy instead of android.support.
So use following provider tag in you application's manifest.xml file.
<provider android:name="androidx.core.content.FileProvider"
android:authorities="YOUR_APP_PACKAGE_NAME.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"></meta-data></provider>
It must be under application tag.
In addition to these things I had to do one more thing to get rid of this error. I had manually added the xml folder and file_paths.xml into the project folder. However, I had not yet added them to the project in the solution. Once I right clicked on the Resources folder and added New Folder (xml) and Existing Item (file_paths.xml) the error went away.

Trusting unknown certificates in windows store app [duplicate]

I am trying to override the certificate validation in a Windows Store App to accept a self-signed certificate on two external services (using HttpClient) to allow the Windows 8 app to accept the certificates and establish a trust relationship for SSL
EDIT:
I implemented the approach documented here : Installing certs by using the appmanifest
and added the relevant .cer files to my application and ensured they are 'Content' and 'Copy Always'.
My package.appxmanifest Extensions section looks like this:
<Extensions>
<Extension Category="windows.certificates">
<Certificates>
<Certificate StoreName="TrustedPeople" Content="Assets\ReportingServices.cer" />
<Certificate StoreName="TrustedPeople" Content="Assets\Crm.cer" />
<Certificate StoreName="CA" Content="Assets\DigiCertHighAssurance.cer" />
<TrustFlags ExclusiveTrust="true" />
<SelectionCriteria AutoSelect="true" />
</Certificates>
</Extension>
but this still does not work.
I have tried putting the app certificates in the 'Root' StoreName but still no success. Does anyone have any ideas why this might not work please?
This is a bit of old one, but seeing as there are quite a few watchers I will give my solution.
// Create the httpClient and send the request
HttpBaseProtocolFilter aHBPF = new HttpBaseProtocolFilter();
// If you want to ignore expired Certs
aHBPF.IgnorableServerCertificateErrors.Add(ChainValidationResult.Expired);
// Untrused because this is a self signed cert that is not installed
aHBPF.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
// Host names and certs names may not match
aHBPF.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);
HttpClient httpClient = new HttpClient(aHBPF);
HttpResponseMessage response = await httpClient.SendRequestAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead).AsTask(cts.Token);
Just to save your time. I got to resolve this for 2 days of trial and error. Here you can solve it.
Add the .cer file to your project, Make the build action as "Content", copy as newer
then add this to your app manifest
<Capabilities>
<Capability Name="sharedUserCertificates" />
<Capability Name="enterpriseAuthentication" />
<Capability Name="privateNetworkClientServer" />
<Capability Name="internetClient" />
</Capabilities>
<Extensions>
<Extension Category="windows.certificates">
<Certificates>
<Certificate StoreName="Root" Content="Certificates\vibeapi.cer" />
<TrustFlags ExclusiveTrust="true" />
<SelectionCriteria AutoSelect="true" />
</Certificates>
</Extension>
</Extensions>
and to your code behind you can now access the file using this
//Testing https connection
HttpClientHandler msgHandler = new HttpClientHandler();
using (System.Net.Http.HttpClient httpClient = new System.Net.Http.HttpClient(msgHandler, true))
{
var HTTPSURL = new Uri("https://www.sample.net/");
var response = await httpClient.GetAsync(HTTPSURL);
var responseStr = await response.Content.ReadAsStringAsync();
}
see link for reference
help
It will work if you put cer file to the project root and change Content section in manifest file to Content="file.cer"

Categories

Resources