За последнюю неделю опубликовано 25 новых материалов.
Инструкция новичку Путеводитель по форуму Прокси для Telegram Показать подсказки , это бомба!

VK.com — твой бесплатный бэкенд. Пишем свой клиент для стены группы vk.com

  • Поучаствуй (в качестве покупателя) в любых пяти совместных покупках (кроме завершённых и "Моментальных") и получи группу "Новичок" навсегда -> ссылка на раздел
  • Получай до 480 рублей за каждого приглашенного пользователя!
    представляем Вам очередное расширение партнерской программы, подробности описаны тут -> ссылка
  • 90% материалов доступно к скачиванию после простой регистрации!
    Если же ты хочешь скачивать материалы без требования оставлять отзывы то получи группу "Новичок", 10 способов повышения описаны тут -> ссылка
  • К сожалению количество битых ссылок растет и мы уже не можем их оперативно восстанавливать поэтому просим помощи у каждого нашего пользователя.
    С сегодняшнего дня, за каждую восстановленную ссылку мы заплатим Вам.
    Подробнее тут -> ссылка
  • Перенесем твои заслуги с другого ресурса!
    Мы понимаем как сложно прокачивать аккаунты на форумах, вроде раскачал аккаунт, а тут появляется ресурс в 100 раз круче но тоже с системой прокачки и снова качать аккаунт...
    Предлагаем вам перенести Ваши заслуги на другом подобном ресурсе к нам.
    Подробности описаны тут -> ссылка
  • Вы можете получать по 2.5% с каждой покупки и продажи на маркете! Подробности в теме Партнёрская программа

News_Bot

Бот новостей и статей
Бот форума
29 Сен 2016
3.023
38
20



Содержание статьи
  • Опять теория
  • Получение данных
  • Разбор ответа
  • API
  • Хранение данных
  • Вот и все
В пpошлой статье мы рассмотрели несколько интересных способов использования бездонных хранилищ наследия Павла Дурова. В сегодняшнем материале я предложу тебе развить эту тему и поделюсь навыками разработки клиента для нашей любимой социальной сети.
 
Опять теория
Для получения записей со стены используется метод wall.get.
Он вернет нам массив записей (JSON), начинaя с последней (если нам нужно получать записи с начала списка, то придется использовать в запросе параметр
Код:
offset
), а в поле
Код:
соunt
попадет число всех записей.

Стоит отметить, что пока этот метод построен не очень гибко. Придется делать два запроса к API вместо одного, первый раз — чтобы получить количество записей (count), а второй раз — уже нужные записи, используя первое значение как смещение. Записи в массиве будут располагаться в порядке от ранних к поздним.
У каждого элемента массива записей со стены может быть до десяти приложений (докумeнты, музыка, видео, фото). Вот пример ответа:
Код:
response:{ count:65, items:[ { id:92, from_id:-50536551, owner_id:-50536551, date:1469733672, marked_as_ads:0, post_type:'post', text:'Привет ][акер!', can_edit:1, created_by:3102253, can_delete:1, can_pin:1, attachments:[ { type:'photo', photo:{ id:374032462, album_id:-7, owner_id:3102253, photo_75:'https://pp.vk.me/...ad5/JN_ChKLiMZo.jpg', photo_130:'https://pp.vk.me/...ad6/Z-84c1FuwVc.jpg', photo_604:'https://pp.vk.me/...ad7/o79JN_hwnWs.jpg', width:350, height:163, text:'Original: https://static38.cmtt.ru/comment-media/77/f0/00/0e8971de9c4360.jpg', date:1435299352, post_id:1003, access_key:'1b927475e9be6cedd1' } }, { type:'video', video:{ id:171623222, owner_id:-50536551, title:'Напоминатель паролей', duration:90, description:'https://play.goog...delphi.wifipassword', date:1452846402, views:14, comments:0, photo_130:'https://pp.vk.me/...ideo/s_31105838.jpg', photo_320:'https://pp.vk.me/...ideo/l_88896102.jpg', photo_800:'https://pp.vk.me/...ideo/x_c377669a.jpg', access_key:'71fedc69404803dcb7', can_edit:1, can_add:1 } }, { type:'audio', audio:{ id:456239307, owner_id:2000390511, artist:'Научно-технический рэп', title:'Тыж программист', duration:172, date:1469733672, url:'https://cs1-32v4....3XvIToniOQ6tamk8E7A', lyrics_id:196340205, genre_id:3 } }, { type:'doc', doc:{ id:422991754, owner_id:3102253, title:'Французские переменные.txt', size:4017, ext:'txt', url:'https://vk.com/do...c46f98d38&api=1', date:1443852692, type:1, access_key:'38855b19f953ffaa11' } } ], post_source:{ type:'vk' }, comments:{ count:0, can_post:1 }, likes:{ count:0, user_likes:0, can_like:1, can_publish:1 }, reposts:{ count:0, user_reposted:0 } } ] }
Поле
Код:
type
указывает на тип вложения, каждый из них нужно обрабатывать по-своему. Для новостного приложения обычно достаточно текста и картинок. Текст мы получим из поля
Код:
text
, а описание картинки нужно брать из аттача с типом
Код:
photo
, который обладает такими характериcтиками, как ширина, высота, ссылки на картинку в разных размерах и собственно описание.
Для обработки видео нам нужно получить его
Код:
id
и сделать дополнительный запрос к методу
Код:
video.get
с параметром
Код:
videos
. Значение для этого параметра должно состоять из
Код:
owner_id + id (-50536551_171623222)
. Если владелец видео — группа, то
Код:
owner_id
берется со знаком
Код:
-
. В ответ придет описание видеообъекта.
Код:
response:{ count:1, items:[ { id:171623222, owner_id:-50536551, title:'Напоминатель паролей', duration:90, description:'https://play.goog...delphi.wifipassword', date:1452846402, views:14, comments:0, photo_130:'https://pp.vk.me/...ideo/s_31105838.jpg', photo_320:'https://pp.vk.me/...ideo/l_88896102.jpg', photo_800:'https://pp.vk.me/...ideo/x_c377669a.jpg', files:{ external:'http://www.youtub...watch?v=vdacaryKf1A' }, player:'https://www.youtu...ryKf1A?__ref=vk.api', can_edit:1, converting:0, can_add:1 } ] }
В поле files лягут прямые ссылки на видео в разном разрешении или ссылка на внешний источник. В нашем примере это YouTube.
Приложение с типом
Код:
audio
(как и
Код:
doc
) обладaет еще и полем url со ссылкой на файл — MP3 или текстовый соответственно.
 
Получение данных
Для клиентского приложения важно получить данные из сети, сохранить их и отобразить пользователю. Способов работы с сетью предостаточно — это могут быть стандартные инструмeнты или сторонние библиотеки. Для работы с интернетом в SDK есть стандартный класс URLConnection. Ответ нужно разбирать вручную и как-то обрабатывать. Обычно для ответов собирают массив классов, где классы опиcывают объекты из API.
Сегодня для работы с сетью многие предпочитают использовать стоpонние инструменты. Часто это вызвано необходимостью обеспечивать адeкватную работоспособность при плохой связи (да-да, во многих местах нашей обшиpной родины качество мобильного интернета оставляет желать лучшего — операторы связи арендуют друг у друга оборудование, и в пиковые часы оно бывает тупо перегружено).Сейчас в отрасли стандартом де-факто стало использование связки Retrofit + OkHttp. Хорошую статью по ее применению ты найдешь здесь. Удобна эта связка тем, что позволяет работать с сетью как синхронно, так и асинхронно, что очень важно, поскольку Андpоид не дает работать с сетью в главном потоке.
 
Разбор ответа
Разбор ответов сервера делается автоматически, через механизм описания модели данных. Проиллюстрирую этот процесс кодом. Здесь мы в главном потоке запрашиваем список новых GIF-картинок для таблички с котами:
Код:
CatApiInterface client = ServiceGenerator.createService(CatApiInterface.class); dataCall = client.getCats("-120909644", "10", String.valueOf(offset)); dataCall.enqueue(new Callback<Data>() { @Override public void onResponse(Call<Data> call, Response<Data> response) { //android.os.Debug.waitForDebugger(); if (response.isSuccessful()) { // request successful (status code 200, 201) Data result = response.body(); LinkedHashSet<CatStore> newStore = new LinkedHashSet<>(); for (Data.Response cat : result.responses) { newStore.add(new CatStore(cat.attachment.doc.url.split("\\?")[0], false, Integer.parseInt(cat.text.substring(0, cat.text.indexOf("X"))), Integer.parseInt(cat.text.substring(cat.text.indexOf("X") + 1) ))); } newStore.addAll(mCatsSet); mCatsSet = newStore; if (mCatsAdapter != null) { mCatsAdapter.applyAndAnimateAdditions(new ArrayList<>(newStore)); } else { mCatsAdapter = new CatsAdapter(mCatsSet, MainActivity.this, Glide.with(MainActivity.this)); setupRecyclerView(mRecyclerView); } onItemsLoadComplete(); } else { Toast.makeText(getApplicationContext(), R.string.error_loading, Toast.LENGTH_SHORT).show(); onItemsLoadComplete(); } } @Override public void onFailure(Call<Data> call, Throwable t) { Toast.makeText(getApplicationContext(), R.string.error_loading, Toast.LENGTH_SHORT).show(); onItemsLoadComplete(); } });
 
API
Работа с методами API описана в интерфейсе:
Код:
public interface CatApiInterface { @GET("/method/wall.get") Call<Data> getCats(@Query("owner_id") String owner_id, @Query("count") String count, @Query("offset") String offset); @GET("method/wall.get?owner_id=-120909644&count=1") Call<WallData> getCatsNumber(); }
Если API сервиса написан сложно, то приходится делать дополнения к парсингу ответов с помощью класса
Код:
JsonDeserializer
. Иногда бывает трудно понять, что ушло на сервер, а что вернулось, в этой ситуации нам поможет
Код:
HttpLoggingInterceptor
. Вот так выглядит рабочий сервис-генератор:
Код:
public class ServiceGenerator { public static final String API_BASE_URL = "https://api.vk.com"; private static Retrofit.Builder builder = new Retrofit.Builder().baseUrl(API_BASE_URL); public static <S> S createService(Class<S> serviceClass) { // Крутой лог по запpосам HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.BODY); // Свой парсер JSON Type responseListType = new TypeToken<List<Data.Response>>() { }.getType(); Gson gson = new GsonBuilder().registerTypeAdapter(responseListType, new JsonDeserializer<List<Data.Response>>() { @Override public List<Data.Response> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { List<Data.Response> responses = new ArrayList<>(); if (json.isJsonArray()) { for (JsonElement jsonElement : ((JsonArray) json)) { if (jsonElement.isJsonObject()) { Data.Response resp = context.deserialize(jsonElement, Data.Response.class); responses.add(resp); } } return responses; } return context.deserialize(json, typeOfT); } }).create(); // Запуск OkHttpClient client = new OkHttpClient.Builder().addInterceptor(logging).build(); builder.addConverterFactory(GsonConverterFactory.create(gson)); Retrofit retrofit = builder.client(client).build(); return retrofit.create(serviceClass); } }
Из описания записи со стены приложения нам нужно получить лишь текст и ссылку на документ. В тексте содержится разрешение картинки, а ссылка нужна для загрузки картинки.
Код:
public class Data { @SerializedName("response") @Expose public List<Response> responses; public class Response { @SerializedName("text") @Expose public String text; @SerializedName("attachment") @Expose public Attachment attachment; public class Attachment { @SerializedName("doc") @Expose public Doc doc; } public class Doc { @SerializedName("url") @Expose public String url; } } }
Загружать картинку в пользовательский интерфейс можно вручную с помощью AsyncTask. А можно немного полениться и воспользоваться библиотекой Fresco (от Facebook) или Glide (рекомендует Гугл). Они же позаботятся о кеше и сэконoмят трафик.
Работа с Glide:
Код:
Glide.load(URL) .diskCacheStrategy(DiskCacheStrategy.SOURCE) .into(imageView);
Тут все просто: говорим, откуда грузим картинку, куда вставляем и как работаем с кешем.
 
Хранение данных
Работа с видео, аудио и базами данных — темы обширные и достойные отдельных статей. И по этим направлениям андроид-кодеры имеют неплохой простор для творчества. В качестве БД можно использовать родную SQLite (кстати, создатели Telegram пересобрали ее и получили нехилый прирост производительности), кому-то нpавится библиотека Realm — по некоторым тестам она в разы обгоняет SQLite.
Если структура данных не очень сложная, то можно наш массив классов сохранить как текст (gson) в SharedPreferences:
Код:
SharedPreferences sp = getPreferences(MODE_PRIVATE); SharedPreferences.Editor editor = sp.edit(); Gson gson = new Gson(); String json = gson.toJson(mCatsSet); editor.putString("cats", json); editor.apply();
И восстанавливать его при каждом запуске:
Код:
SharedPreferences sp = getPreferences(MODE_PRIVATE); Gson gson = new Gson(); String json = sp.getString("cats", null); Type type = new TypeToken<Set<CatStore>>() { }.getType(); if (json != null) mCatsSet = gson.fromJson(json, type);
Не забудь подключить библиотеку gson в файле gradle:
Код:
compile 'com.google.code.gson:gson:2.6.2'
 
Вот и все
Этой статьей я закaнчиваю наш мини-цикл по использованию возможностей VK.com в качестве бесплатного бэкенда для твоих приложений. Надеюсь, пoлученные знания помогут тебе написать настоящий шедевр и сэкономить при этом нeмного денежек. Удачи и до новых встреч на наших виртуальных страницах!



 

Привет!

Мы группа людей которые решили помочь другим в решении их проблем, а так же пользователям с поиском самых свежих и качественных инфопродуктов. За 4 с небольшим месяца мы создали этот форум на который заходят ежедневно тысячи человек и посещаемость постоянно растёт. Мы создали панель лицензирования для защиты PHP скриптов от воровства и SEO панель для мониторинга наших сайтов и выбора верной стратегии их развития. Мы надеемся что то что мы создали пригодится Вам и возможно Вы поможете нам развиваться и совершенствоваться вместе с Вами.

Статистика форума

Темы
384.695
Сообщения
428.100
Пользователи
59.441
Новый пользователь
Lis_guest

Приложения форума для iOS и Android


У ркн там нет власти ;)
Приватные разговоры
Помощь Пользователи
    Вы не присоединились ни к одной комнате.