Udostępnij za pośrednictwem


Udostępnij

Przeglądaj przykład. Przeglądanie przykładu

W tym artykule opisano sposób używania interfejsu użytkownika aplikacji wieloplatformowej platformy .NET (.NET MAUI). IShare Ten interfejs udostępnia interfejs API do wysyłania danych, takich jak tekst lub linki internetowe, do funkcji udostępniania urządzeń.

Domyślna implementacja interfejsu IShare jest dostępna za pośrednictwem właściwości Share.Default. Zarówno interfejs IShare, jak i klasa Share znajdują się w przestrzeni nazw Microsoft.Maui.ApplicationModel.DataTransfer.

Po wysłaniu żądania udostępniania na urządzeniu zostanie wyświetlone okno udostępniania z monitem użytkownika o wybranie aplikacji do udostępnienia:

udostępnij z jednej aplikacji do innej

Rozpocznij

Aby uzyskać dostęp do funkcji Share, wymagana jest następująca konfiguracja specyficzna dla platformy:

Nie jest wymagana żadna konfiguracja.

Funkcja udostępniania działa przez wywołanie metody RequestAsync z ładunkiem danych zawierającym informacje do udostępniania innym aplikacjom. ShareTextRequest.Text i ShareTextRequest.Uri można mieszać, a każda platforma będzie obsługiwać filtrowanie na podstawie zawartości.

public async Task ShareText(string text)
{
    await Share.Default.RequestAsync(new ShareTextRequest
    {
        Text = text,
        Title = "Share Text"
    });
}

public async Task ShareUri(string uri, IShare share)
{
    await share.RequestAsync(new ShareTextRequest
    {
        Uri = uri,
        Title = "Share Web Link"
    });
}

Udostępnianie pliku

Możesz również udostępniać pliki innym aplikacjom na urządzeniu. Program .NET MAUI automatycznie wykrywa typ pliku (MIME) i inicjuje udostępnianie. Jednak systemy operacyjne mogą ograniczać typy plików, które mogą być udostępniane. Aby udostępnić pojedynczy plik, użyj typu ShareFileRequest.

Poniższy przykład kodu zapisuje plik tekstowy na urządzeniu, a następnie żąda jego udostępnienia:

public async Task ShareFile()
{
    string fn = "Attachment.txt";
    string file = Path.Combine(FileSystem.CacheDirectory, fn);

    File.WriteAllText(file, "Hello World");

    await Share.Default.RequestAsync(new ShareFileRequest
    {
        Title = "Share text file",
        File = new ShareFile(file)
    });
}

Udostępnianie wielu plików

Udostępnianie wielu plików różni się nieco od udostępniania jednego pliku. Aby udostępnić pojedynczy plik, użyj typu ShareMultipleFilesRequest.

Poniższy przykładowy kod zapisuje dwa pliki tekstowe na urządzeniu, a następnie żąda ich udostępnienia:

public async Task ShareMultipleFiles()
{
    string file1 = Path.Combine(FileSystem.CacheDirectory, "Attachment1.txt");
    string file2 = Path.Combine(FileSystem.CacheDirectory, "Attachment2.txt");

    File.WriteAllText(file1, "Content 1");
    File.WriteAllText(file2, "Content 2");

    await Share.Default.RequestAsync(new ShareMultipleFilesRequest
    {
        Title = "Share multiple files",
        Files = new List<ShareFile> { new ShareFile(file1), new ShareFile(file2) }
    });
}

Kontrolowanie lokalizacji plików

Ważne

Ta sekcja dotyczy tylko systemu Android.

W niektórych scenariuszach na Androidzie, na przykład gdy plik znajduje się w prywatnej pamięci, można go skopiować do pamięci podręcznej aplikacji, która jest następnie udostępniana za pośrednictwem systemu Android FileProvider. Może to jednak przypadkowo uwidocznić całą pamięć podręczną i dane aplikacji atakującemu. Można temu zapobiec, dodając do aplikacji plik z zastąpionymi ścieżkami plików dostawcy, oraz upewniając się, że pliki są kopiowane do lokalizacji określonej w tym pliku przed ich udostępnieniem.

Aby dodać plik, który zastępuje ścieżki plików dostawcy w Twojej aplikacji, dodaj plik o nazwie microsoft_maui_essentials_fileprovider_file_paths.xml do folderu Platforms\Android\Resources\xml w aplikacji. W związku z tym pełna względna nazwa pliku projektu powinna być Platformy\Android\Resources\xml\microsoft_maui_essentials_fileprovider_file_paths.xml. Następnie dodaj kod XML do pliku dla wymaganych ścieżek:

 <?xml version="1.0" encoding="UTF-8" ?>
 <paths>
    <external-path name="external_files" path="sharing-root" />
    <cache-path name="internal_cache" path="sharing-root" />
    <external-cache-path name="external_cache" path="sharing-root" />  
 </paths>

Aby uzyskać więcej informacji na temat ścieżek dostawcy plików, zobacz FileProvider w developer.android.com.

Przed udostępnieniem pliku upewnij się, że został on najpierw zapisany w folderze sharing-root w jednej z lokalizacji z pliku nadpisującego.

// Write into the specific sub-directory
var dir = Path.Combine(FileSystem.CacheDirectory, "sharing-root");  
Directory.CreateDirectory(dir);
var file = Path.Combine(dir, "mydata.txt");
await File.WriteAllTextAsync(file, $"My data: {count}");

// Share the file
await Launcher.OpenAsync(new OpenFileRequest
{
   Title = "My data",
   File = new ReadOnlyFile(file),
});

Możesz sprawdzić, czy plik jest poprawnie udostępniany, jeśli udostępniony identyfikator URI wyklucza katalog główny udostępniania. Jeśli na przykład udostępnisz plik <CacheDirectory>/sharing-root/mydata.txt, a udostępniony identyfikator URI jest content://com.companyname.overwritefileproviderpaths.fileProvider/internal_cache/sharing-root/mydata.txt, dostawca plików nie używa prawidłowej ścieżki. Jeśli udostępniony identyfikator URI jest content://com.companyname.overwritefileproviderpaths.fileProvider/internal_cache/mydata.txt, dostawca plików używa poprawnej ścieżki.

Ostrzeżenie

Jeśli podczas udostępniania pliku otrzymasz Java.Lang.IllegalArgumentExceptionz komunikatem podobnym do "Nie można odnaleźć ustawionego katalogu głównego zawierającego /data/data/com.companyname.overwritefileproviderpaths/cache/some-non-sharing-path/mydata.txt", najprawdopodobniej udostępniasz plik znajdujący się poza katalogiem root udostępniania.

Lokalizacja prezentacji

Ważne

Ta sekcja dotyczy tylko systemu iPadOS.

Podczas żądania udostępniania lub otwierania modułu uruchamiania w systemie iPadOS można go przedstawić w popover. Określa, gdzie pojawi się wyskakujące okienko i wskaże strzałkę bezpośrednio do. Ta lokalizacja jest często kontrolką uruchamiającą akcję. Lokalizację można określić przy użyciu właściwości PresentationSourceBounds:

await Share.RequestAsync(new ShareFileRequest
    {
        Title = Title,
        File = new ShareFile(file),
        PresentationSourceBounds = DeviceInfo.Platform == DevicePlatform.iOS && DeviceInfo.Idiom == DeviceIdiom.Tablet
                                ? new Rect(0, 20, 0, 0)
                                : Rect.Zero
    });
await Launcher.OpenAsync(new OpenFileRequest
    {
        File = new ReadOnlyFile(file),
        PresentationSourceBounds = DeviceInfo.Platform == DevicePlatform.iOS && DeviceInfo.Idiom == DeviceIdiom.Tablet
                                ? new Rect(0, 20, 0, 0)
                                : Rect.Zero
    });

Wszystkie opisane tutaj elementy działają równie dobrze dla Share i Launcher.

Oto metoda rozszerzenia, która pomaga obliczyć granice widoku:

public static class ViewHelpers
{
    public static Rect GetAbsoluteBounds(this Microsoft.Maui.Controls.View element)
    {
        Element looper = element;

        var absoluteX = element.X + element.Margin.Top;
        var absoluteY = element.Y + element.Margin.Left;

        // Add logic to handle titles, headers, or other non-view bars

        while (looper.Parent != null)
        {
            looper = looper.Parent;
            if (looper is Microsoft.Maui.Controls.View v)
            {
                absoluteX += v.X + v.Margin.Top;
                absoluteY += v.Y + v.Margin.Left;
            }
        }

        return new Rect(absoluteX, absoluteY, element.Width, element.Height);
    }
}

Można go następnie użyć podczas wywoływania RequestAsync:

public Command<Microsoft.Maui.Controls.View> ShareCommand { get; } = new Command<Microsoft.Maui.Controls.View>(Share);

async void Share(Microsoft.Maui.Controls.View element)
{
    try
    {
        await Share.Default.RequestAsync(new ShareTextRequest
        {
            PresentationSourceBounds = element.GetAbsoluteBounds(),
            Title = "Title",
            Text = "Text"
        });
    }
    catch (Exception)
    {
        // Handle exception that share failed
    }
}

Element wywołujący można przekazać po wyzwoleniu Command:

<Button Text="Share"
        Command="{Binding ShareWithFriendsCommand}"
        CommandParameter="{Binding Source={RelativeSource Self}}"/>

Aby zapoznać się z przykładem klasy ViewHelpers, zobacz przykład .NET MAUI hostowany w witrynie GitHub.

Różnice między platformami

W tej sekcji opisano różnice między platformami dotyczące API do udostępniania.