Статьи

Создайте приложение для поиска в Twitter: выберите и проанализируйте канал JSON в Twitter

Эта серия из двух частей познакомит вас с основами работы с веб-сервисами RESTful с помощью Android SDK. Попутно вы узнаете, как выполнять поиск по общедоступному API Twitter!

В этом уроке мы будем использовать AsyncTask для получения твитов JSON, их анализа, а затем отображения в пользовательском интерфейсе. Несмотря на то, что код в этом руководстве относится только к Twitter, применяемые принципы применяются для извлечения многих других веб-каналов и API-интерфейсов с использованием архитектуры RESTful.

Этот учебный курс по Android Twitter Search состоит из двух частей:


Мы собираемся использовать AsyncTask для получения, анализа и отображения ленты твитов в поисковом запросе пользователя. Используя AsyncTask, мы можем перенести обработку в фоновый поток, результаты которого все еще доступны для отображения в интерфейсе приложения. В своем классе Activity добавьте внутренний класс AsyncTask после метода searchTwitter :

1
2
3
private class GetTweets extends AsyncTask<String, Void, String> {
         
}

Класс AsyncTask является абстрактным, что означает, что вы должны создать подкласс, чтобы использовать его. Такие подклассы должны реализовывать один конкретный метод, который мы добавим дальше. В то же время, Eclipse будет отображать сообщения об ошибках (пока просто игнорируйте их).

AsyncTask использует три универсальных типа, как вы можете видеть из начальной строки объявления класса. Первый указывает тип параметра — в нашем случае это строка, так как мы собираемся передать созданную нами строку URL. Средний тип предназначен для модулей прогресса, которые мы не будем использовать в этом руководстве, поэтому мы просто указываем void. Единицы прогресса могут использоваться для индикации хода выполнения фоновых задач. Третий тип — это другая строка, которую возвращает фоновый процесс. В нашем случае это будет извлеченный текст фида JSON.


Внутри вашего класса AsyncTask добавьте следующий метод, который мы переопределяем из родительского класса:

1
2
3
4
@Override
protected String doInBackground(String… twitterURL) {
             
}

Тип параметра — строка, соответствующий первому типу, который мы указали в открывающей строке объявления класса. Эта строка будет URL-адресом API поиска в Твиттере, который мы создали в прошлый раз. Внутри этого метода мы указываем, какой фоновый процесс мы хотим выполнить AsyncTask. Метод также возвращает значение типа string, чтобы соответствовать тому, что мы указали в качестве третьего параметра в строке открытия объявления класса. Эта возвращенная строка будет получена в качестве параметра для второго метода, который мы реализуем позже.

Совет: если вы не знакомы с абстрактными классами или универсальными типами, не беспокойтесь — на самом деле мы просто следуем шаблону. Как и для большей части платформы Android, вы можете узнать, как использовать эти ресурсы из примеров в Руководстве разработчика и, в данном случае, Справочника по API .


Результатом поиска в Твиттере будет строка, которую мы будем строить из полученного нами ответа. Внутри метода doInBackground начните с создания String Builder:

1
StringBuilder tweetFeedBuilder = new StringBuilder();

Хотя мы используем одну строку URL, метод получит массив объектов указанного типа (строка), поэтому давайте пройдемся по нему:

1
2
3
for (String searchURL : twitterURL) {
                 
}

На самом деле цикл будет повторяться только один раз, но вы можете расширить свой код для получения нескольких поисковых каналов, поэтому сейчас мы будем использовать цикл. Внутри цикла создайте HTTP-клиент для выполнения запроса:

1
HttpClient tweetClient = new DefaultHttpClient();

Теперь нам нужно отлавливать исключения ввода-вывода, что неизменно имеет место, когда вы пытаетесь получить данные из любого места за пределами вашего приложения. Добавьте блоки try и catch :

1
2
3
4
5
6
7
try {
                     
}
catch(Exception e) {
    tweetDisplay.setText(«Whoops — something went wrong!»);
    e.printStackTrace();
}

Если есть ошибка ввода / вывода, мы просто пишем сообщение в пользовательский интерфейс. Внутри блока try создайте объект HTTP Get для выдачи запроса, передав URL-адрес поиска:

1
HttpGet tweetGet = new HttpGet(searchURL);

Теперь мы можем выполнить запрос и сохранить результаты в объекте HTTP Response:

1
HttpResponse tweetResponse = tweetClient.execute(tweetGet);

Мы сможем использовать объект ответа для доступа к содержанию и состоянию ответного сообщения, полученного из Twitter.


Прежде чем мы попытаемся обработать ответное сообщение, давайте проверим статус. Все еще внутри блока try :

1
StatusLine searchStatus = tweetResponse.getStatusLine();

Если ответ в порядке, мы можем продолжить и попытаться проанализировать твиты, в противном случае мы выведем сообщение об ошибке пользователю:

1
2
3
4
5
if (searchStatus.getStatusCode() == 200) {
                         
}
else
    tweetDisplay.setText(«Whoops — something went wrong!»);

Внутри блока оператора if теперь мы можем получить HTTP-сущность и содержимое сообщения в качестве входного потока:

1
2
HttpEntity tweetEntity = tweetResponse.getEntity();
InputStream tweetContent = tweetEntity.getContent();

Теперь мы можем начать вносить содержимое сообщения в программу, используя Reader для входного потока, а не Buffered Reader для управления входящими данными:

1
2
InputStreamReader tweetInput = new InputStreamReader(tweetContent);
BufferedReader tweetReader = new BufferedReader(tweetInput);

Давайте прочитаем данные по одной строке за раз, добавляя каждую строку в созданный нами String Builder:

1
2
3
4
String lineIn;
while ((lineIn = tweetReader.readLine()) != null) {
    tweetFeedBuilder.append(lineIn);
}

Это будет добавлять в String Builder до тех пор, пока все полученные данные не будут обработаны. Теперь перейдите в конец метода doInBackground , после блока catch — верните строку, в которую мы встроили результаты:

1
return tweetFeedBuilder.toString();

На этом метод doInBackground завершен — он выполняет выборку твита и импортирует его в приложение, так что теперь мы можем его проанализировать и отобразить.


Теперь, когда AsyncTask получил канал твита, мы можем его проанализировать и отобразить в пользовательском интерфейсе приложения. Для этого мы можем реализовать другой метод класса AsyncTask, добавленный после doInBackground , все еще внутри объявления класса AsyncTask:

1
2
3
protected void onPostExecute(String result) {
             
}

Обратите внимание, что этот метод получает строковый параметр, который мы указали в качестве третьего типа в строке объявления начального класса и что мы вернули из doInBackground на последнем шаге. Строка — это текст JSON, представляющий последние твиты по запросу пользователя, полученному из Twitter. Нам нужно будет проанализировать этот текст, чтобы получить доступ к содержимому твитов и отобразить их в пользовательском интерфейсе.

Мы будем встраивать текст твита в строку для отображения, поэтому запустите метод onPostExecute , создав еще один String Builder:

1
StringBuilder tweetResultBuilder = new StringBuilder();

Методы обработки JSON могут генерировать исключения, поэтому добавьте блоки try и catch следующим образом:

1
2
3
4
5
6
7
try {
                 
}
catch (Exception e) {
    tweetDisplay.setText(«Whoops — something went wrong!»);
    e.printStackTrace();
}

Здесь вы должны заметить закономерность — как и в любой программе, в которой вы пытаетесь извлекать и обрабатывать внешние данные, вы должны уделять особое внимание обработке потенциальных ошибок.

Внутри блока try создайте объект JSON, передав текстовую строку JSON:

1
JSONObject resultObject = new JSONObject(result);

Внутри текстовой строки JSON находится массив, содержащий твиты, а также некоторые другие данные — выполните запрос Twitter, вставив URL-адрес поиска в адресную строку браузера, как, например, в прошлый раз:

1
http://search.twitter.com/search.json?q=android

Возможно, вам придется скопировать и вставить полученный текст в текстовый редактор, чтобы эффективно его прочитать. Если вы посмотрите текст JSON, вы увидите следующий раздел, который отмечает начало массива твитов:

1
«results»:[

Нам нужно получить этот массив твитов, используя его имя: «results». Получите массив «results» из объекта JSON:

1
JSONArray tweetArray = resultObject.getJSONArray(«results»);

Теперь мы можем просмотреть твиты и подготовить их к показу.


Если вы снова посмотрите на текст JSON, полученный через браузер (или, необязательно, в Eclipse, если вы запишете его в журнал Android во время работы приложения), вы увидите содержимое, возвращаемое для каждого твита в массиве. В этом уроке мы будем только выписывать имя пользователя аккаунта и содержание самого твита. Вы можете расширить приложение, чтобы включить любую информацию, которую вы хотите. В тексте, возвращаемом из Twitter, имя пользователя представлено как «from_user», а содержимое твита называется «text» — посмотрите на содержимое JSON, чтобы проверить это и узнать, какие еще элементы данных находятся в нем.

В вашем блоке try , после извлечения массива твитов, добавьте цикл for для итерации твитов:

1
2
3
for (int t=0; t<tweetArray.length(); t++) {
                     
}

Внутри цикла получите каждый элемент в виде объекта JSON:

1
JSONObject tweetObject = tweetArray.getJSONObject(t);

Теперь извлеките имя пользователя из этого объекта, добавив его в String Builder вместе с дополнительным текстом для отображения:

1
tweetResultBuilder.append(tweetObject.getString(«from_user»)+»: «);

Класс JSON Object предоставляет метод getString для этой цели; есть также альтернативный метод get . Теперь получите и добавьте содержимое твита:

1
tweetResultBuilder.append(tweetObject.get(«text»)+»\n\n»);

Теперь перейдите к блоку catch внутри метода onPostExecute . Если обработка сработала, мы отображаем результат в текстовом представлении, в противном случае мы отображаем сообщение об ошибке:

1
2
3
4
if(tweetResultBuilder.length()>0)
    tweetDisplay.setText(tweetResultBuilder.toString());
else
    tweetDisplay.setText(«Sorry — no tweets found for your search!»);

Наш класс AsyncTask завершен.


У нас есть AsyncTask для выполнения нашей обработки; нам просто нужно позвонить по этому поводу. Вернитесь к вашему методу searchTwitter , внутри блока try и после того, как мы построили строку URL поискового запроса. Создайте экземпляр нового класса AsyncTask и вызовите для него метод execute , передав строку URL:

1
new GetTweets().execute(searchURL);

Обратите внимание, что мы передаем строку, которую мы указали в объявлении AsyncTask и в методе doInBackground .

Это базовое приложение завершено — вы можете проверить его в эмуляторе и на устройствах Android. Попробуйте это с различными поисковыми запросами, такими как хэштеги. Конечно, вы можете расширить приложение, чтобы отображать больше информации из твитов и даже ссылаться на Twitter по кликам пользователей. При существующем положении вещей пользователь может прокручивать возвращенную ленту твитов и выполнять повторные поиски по своему усмотрению.

Запуск приложения

В этих двух уроках мы изучали получение твитов из API поиска в Twitter. Вы можете использовать те же шаблоны проектирования для извлечения данных из других веб-ресурсов. Если ваши приложения будут включать более сложные, непрерывные процессы извлечения данных, вы можете обратиться к поставщикам контента и, возможно, к услугам, чтобы максимизировать эффективность. Как и в случае любых внешних операций на основе данных, вы не можете предполагать, что получение необходимой информации будет успешным, поэтому необходим уровень обработки ошибок. Возможность доступа к интернет-данным, безусловно, является одним из ключевых преимуществ мобильных вычислений, поэтому эти методы являются жизненно важным компонентом в наборе инструментов любого разработчика Android.