В этой статье я собираюсь показать, как использовать метод 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 , поскольку для получения недавних действий необходим маркер полной аутентификации.
Если вы хотите напрямую поэкспериментировать с моим существующим решением, загрузите обновленную версию (если вы следуете серии) здесь . Не забывайте, что вам нужна вспомогательная служба хеширования, чтобы она работала.