Статьи

Flickr API для Windows Phone 7 — часть 4 — активность — фотографии пользователей

В этой статье я собираюсь показать, как использовать метод flickr.activity.userPhotos . Теперь вы можете спросить — есть пара десятков методов API Flickr — я расскажу о каждом из них в отдельной статье? Ответ — нет, я остановлюсь на основных методах. Как только вы поймете, какую функциональность предлагает API, вы сможете закодировать его до конца.

Так что же с flickr.activity.userActivity ? По сути, это метод, который поднимет всю недавнюю активность ваших фотографий. Например, если кто-то прокомментировал одну из ваших фотографий, он сообщит вам, что был опубликован комментарий, покажет вам пользователя, который его опубликовал, дату и содержание комментария. Если действия отсутствуют (следовательно, нет комментариев или других видов действий), он вернет документ в формате JSON (помните, я использую JSON в этой серии?), Который не содержит данных, которые вас заинтересовали бы.

Итак, сначала я добавил класс Activity в папку Core — таким образом, я могу сосредоточить категорию активности API Flickr в одном месте.

Теперь я решил, что делегат, который я использовал ранее, мог бы пригодиться и в других классах, поэтому все, что я сделал, это взял его объявление и поместил его в пространство имен FlickrWP7.Core :

Сам класс Activity довольно прост и напоминает класс Authentication, если вы посмотрите на GetUserPhotos и структуру вызова:

public class Activity
{
    private  HelperDelegate helperDelegateInstance;

    public  string LastActivityResult { get; set; }

    public  void GetUserPhotos(string apiKey, string signature, string authToken, HelperDelegate helperDelegate, string page = "", string timeframe = "", string resultsPerPage = "" )
    {
        helperDelegateInstance = helperDelegate;

        WebClient client = new WebClient();
        client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
        string URL = string.Format("http://www.flickr.com/services/rest/?method=flickr.activity.userPhotos&api_key={0}&api_sig={1}&auth_token={2}&format=json",
                apiKey, signature,authToken);

        if (page != "")
            URL += "&page=" + page;
        if (timeframe != "")
            URL += "&timeframe=" + timeframe;
        if (resultsPerPage != "")
            URL += "&per_page=" + resultsPerPage;

        client.DownloadStringAsync(new Uri(URL));
    }

    void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
        LastActivityResult = e.Result;
        helperDelegateInstance();
    }
}

У меня есть свойство LastActivityResult — это место, где будут храниться необработанные данные JSON для последнего вызова из набора действий . Вы можете спросить — почему этот класс не статичен? Здесь сложная ситуация — есть также flickr.activity.userComments, который является членом категории действий — поэтому я мог бы захотеть сохранить свое состояние и получить другое действие — поэтому я объявлю два отдельных экземпляра для каждого вместо имея два отдельных свойства, одно из которых никогда не будет использовано. И поскольку я извлекаю те же необработанные данные в формате JSON, сейчас можно хранить их в одном свойстве. В конце концов, если вы решите, например, десериализовать данные, вы можете захотеть ввести отдельные свойства для каждого из них.

Теперь у вас может возникнуть другой вопрос — зачем тянуть необработанные данные вместо того, чтобы иметь свойство, которое будет пользовательским классом, представляющим иерархию элементов? Ответ прост — иерархия предметов может измениться. Поэтому, если я жестко закодирую его здесь, исключение будет выдаваться каждый раз, когда изменяется спецификация, и приложение не может получить необходимые данные. Необработанный JSON можно анализировать непосредственно в приложении, вне метода действия, и если Flickr решит изменить возвращаемый результат, мне нужно будет изменить только синтаксический анализ в приложении, а не ядро ​​ядра.

Вы можете видеть , что GetUserPhotos принимает три дополнительных параметра — страницы , временные рамки и resultsPerPage . Они задокументированы в спецификации вызовов, и пользователь может или не может нуждаться в них. Но если он решит указать их, URL будет построен соответственно.

Чтобы поэкспериментировать с этим классом, я создал тестовую страницу в своем приложении для Windows Phone 7. Его разметка XAML выглядит так:

<phone:PhoneApplicationPage
    x:Class="FlickrWP7.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">
 
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Button x:Name="btnFullToken" Content="Get Full Token" Height="72" HorizontalAlignment="Left" Margin="12,684,0,0" VerticalAlignment="Top" Width="230" Click="btnFullToken_Click" />
        <Button x:Name="btnUserPhotos" Content="Get User Photos" Height="72" HorizontalAlignment="Left" Margin="229,684,0,0" VerticalAlignment="Top" Width="239" Click="btnUserPhotos_Click" />
        <TextBlock TextWrapping="Wrap" Height="666" HorizontalAlignment="Left" Margin="12,12,0,0" Name="txtLog" VerticalAlignment="Top" Width="456" />
    </Grid>
 
</phone:PhoneApplicationPage>

Это простая тестовая «консоль»:

Я проверяю функциональность моих методов следующим образом:

private void btnFullToken_Click(object sender, RoutedEventArgs e)
{
    param.Add("api_key", apiKey);
    param.Add("method", "flickr.auth.getFullToken");
    param.Add("mini_token", miniToken);
    param.Add("format", "json");

    Core.Authentication.GetSignature(param, “SECRET", () =>
    {
       txtLog.Text += "Getting full token...";
        Core.Authentication.GetFullToken(
            miniToken, Core.Authentication.Signature, apiKey, () =>
            {
                txtLog.Text += "\nFull token generated\n" + Core.Authentication.FullToken;
            });
    });
}

private void btnUserPhotos_Click(object sender, RoutedEventArgs e)
{
    param["method"] = "flickr.activity.userPhotos";
    param.Remove("mini_token");
    param.Add("auth_token", Core.Authentication.FullToken);
    param.Add("timeframe", "100d");

    Core.Authentication.GetSignature(param, "SECRET", () =>
    {
        txtLog.Text += "\nGetting list of photos...";
        Core.Activity activity = new Core.Activity();

        activity.GetUserPhotos(apiKey, Core.Authentication.Signature,Core.Authentication.FullToken, () =>
        {
            txtLog.Text += "\n" + activity.LastActivityResult;
        },"","100d");
    });
}

Здесь я просто получаю подписи для каждого метода (в соответствии с указанными параметрами) и затем выполняю эти методы (некоторые из них вводятся через делегат — запускается только тогда, когда подпись фактического метода готова).

ПРИМЕЧАНИЕ: подпись привязана к используемым параметрам. Поэтому, если ваша подпись генерируется с определенным присутствующим параметром, и вы пропустите ее при вызове метода, вызов завершится неудачно. То же самое применимо, если вы используете параметр в вызове, но не используете его в подписи. В большинстве случаев, когда вы получаете код ошибки 96 — Неверная подпись, проблема заключается в использовании параметров.

apiKey и miniToken — это общедоступные поля в классе, которые должны представлять ваши уникальные идентификаторы аутентификации.

Как вы, вероятно, заметили, метод GetUserPhotos должен выполняться после GetFullToken , поскольку для получения недавних действий необходим маркер полной аутентификации.

Если вы хотите напрямую поэкспериментировать с моим существующим решением, загрузите обновленную версию (если вы следуете серии) здесь . Не забывайте, что вам нужна вспомогательная служба хеширования, чтобы она работала.