Show / Hide Table of Contents

    Using the PermissionsService with DEM

    In Xamarin.Forms solutions some application features like storage, location etc. is in need for user permissions, developer usually use PermissionsPlugin. We integrate this plugin in our solution throw the IPermissionsService interface and Configuration. DEM default permissions that user need to unable for unhindered application working is phone local storage (for cache saving), location (for showing AMT on map), media and camera using (for pdf and image downloading and uploading).

    If your application use only default permissions you just need to set PermissionPlugin platform specification.

    Android Specific

    In MainActivity.cs override

    
    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, 
                                                    Android.Content.PM.Permission[] grantResults)
    {
        PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode,
                                                                     permissions, grantResults);
    }
    

    Permissions plugin uses Current Activity Plugin, and need to set following in your Activity's OnCreate method:

    Plugin.CurrentActivity.CrossCurrentActivity.Current.Init(this, bundle);

    In AndroidManifest developer need to check list of following permissions

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/>
    <uses-permission android:name="android.permission.MANAGE_DOCUMENTS"/>
    <uses-permission android:name="android.permission.READ_USER_DICTIONARY"/>
    <uses-permission android:name="android.permission.READ_OWNER_DATA"/>
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
    <uses-permission android:name="android.permission.INSTALL_LOCATION_PROVIDER"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    

    For enabling Android file system you need to add new folder in Resource folder and call it xml in that folder you need to create three different .xml files

    my_backup_rules.xml file with following content

    <?xml version="1.0" encoding="utf-8" ?>
    <full-backup-content>
    <include domain="sharedpref" path="."/>
    <exclude domain="sharedpref" path="rs.asseco_see.dem.demoapp.xamarinessentials.xml"/>
    </full-backup-content>
    

    AndroidManifest.xaml change in line:

    <application android:label="z" 
                 android:fullBackupContent="@xml/my_backup_rules" 
                 android:supportsRtl="true" 
                 android:icon="@drawable/icon">
    </application>  
    

    provider_paths.xml file with following content

    <?xml version="1.0" encoding="utf-8" ?>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
      <external-path name="external_files" path="."/>
    <paths>ath name="external_files" path="."/>
    </paths>
    

    AndroidManifest.xml need to add following lines between

    <application></application>
    <provider android:name="android.support.v4.content.FileProvider" 
              android:authorities="rs.asseco_see.dem.demoapp.provider"
              android:exported="false" android:grantUriPermissions="true">
        <meta-data android:name="android.support.FILE_PROVIDER_PATHS" 
                   android:resource="@xml/provider_paths">
        </meta-data>
    </provider>
    

    file_paths.xml file with following content

    <?xml version="1.0" encoding="utf-8" ?>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
      <external-path name="my_images" 
                     path="Android/data/rs.asseco_see.dem.demoapp/files/Pictures"/>
      <external-path name="my_movies" 
                     path="Android/data/rs.asseco_see.dem.demoapp/files/Movies"/>
      <external-files-path name="content" path="." />
    </paths>
    

    iOS Specific

    Based on what permissions you are using, you must add information into your info.plist. Please read the Working with Security and Privacy guide for keys you will need to add.

    <key>NSLocationAlwaysUsageDescription</key>
    <string></string>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string></string>
    <key>UIBackgroundModes</key>
        <array>
        <string>location</string>
        <string>fetch</string>
        <string>remote-notification</string>
        </array>
    <key>NSCameraUsageDescription</key>
    <string>This app needs access to the camera to take photos.</string>
    <key>NSPhotoLibraryUsageDescription</key>
    <string>This app needs access to photos.</string>
    <key>NSMicrophoneUsageDescription</key>
    <string>This app needs microphone for video</string>
    <key>NSPhotoLibraryAddUsageDescription</key>
    <string>This app needs access to the photo gallery.</string>
    <key>NSLocationUsageDescription</key>
    <string>This string is optional but recommended on iOS 6 &amp; 7 and should describe how your app uses location services.
    Set this string in the Info.plist</string>
    <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
    <string>This string is required to gain permission to access location services on iOS 11+ and should describe how your app uses location services. Set this string in the Info.plist</string>
    <key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeName</key>
            <string>MKDirectionsRequest</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>com.apple.maps.directionsrequest</string>
            </array>
        </dict>
    </array>
    

    Otherwise if you want to override default configuration permissions and implement your own the lines below are here for you:

    Step 1: Configuration override in shared project

    public class CustomConfigProvider : IInitialConfigurationProvider
    {
        public Dictionary<string, object> LoadInitialConfiguration()
        {
            var customConfig = new Dictionary<string, object>();
            customConfig.Add("Permissions", new[]{Permission.Location, Permission.LocationAlways, 
                             Permission.LocationWhenInUse, Permission.Storage, 
                             Permission.MediaLibrary, Permission.Camera});
    
            return customConfig;
        }
    }
    

    Step 2: Add an interface to the shared project

    public interface IPermissionsService : IApplicationService
    {
        Task<PermissionStatus> CheckPermissions(Permission permission);
        Task<Dictionary<Permission, PermissionStatus>> RequestPermissions();
        Task<Dictionary<Permission, PermissionStatus>> RequestPermission(Permission permission);
    }
    

    Step 3: Implement our interface

    public class PermissionService : IPermissionsService
    {
        protected readonly IConfiguration configuration;
    
        public PermissionService(IConfiguration configuration)
        {
            this.configuration = configuration;
        }
    
        public Task<PermissionStatus> CheckPermissionsAsync(Permission permission)
        {
            return CrossPermissions.Current.CheckPermissionStatusAsync(permission);
        }
    
        public Task<Dictionary<Permission, PermissionStatus>> RequestPermissions()
        {
            return CrossPermissions.Current.RequestPermissionsAsync(configuration.Permissions);
        }
    
        public Task<Dictionary<Permission, PermissionStatus>> RequestPermission
                (Permission permission) {
            return CrossPermissions.Current.RequestPermissionsAsync(permission);
        }
    }
    

    Step 4: Use the service

    Example:

    In ViewModel add property

    protected readonly IPermissionsService permissions;
    

    In ViewModel constructor

    public ViewModel()
    {
        permissions = App.ResolveService<IPermissionsService>();
    }
    

    And finally in some function

            protected virtual async Task<bool> DownloadStatementAsPdf(object parametar)
            {
                if (await permissions.CheckPermissionsAsync(Permission.Storage) != PermissionStatus.Granted)
                {
                    if (await permissions.RequestPermissionAsync(Permission.Storage) != PermissionStatus.Granted)
                    {
                        return false;
                    }
                }
    
                return await App.Device.SetLoadingAsync(
                    () => DownloadStatementAsPdfInner(parametar as DataObject<Statement>), "Exporting");
            }
    

    Step 5: Native performance Android and iOS

    You will need to set permissions that you want to use on Android and iOS platforms in AndrodiManifest.xml and Info.plist

    Back to top Copyright 2020 Asseco SEE