Всем снова привет! Я вернулся.
Уже несколько человек ждет пост о публикации записей на свою стену вконтакте. И вот эта статья. В ней будет много кода, теории вообще не будет, потому что все довольно просто и тем не менее данный пост может быть полезен тем, кто ломает голову о том как решить данную задачу.
Поехали.
Прежде всего искал доступные варианты. Их не оказалось, поэтому обратил внимание на готовые решения для твиттера и фэйсбук и на примере последнего написал несколько классов для Вконтакте.
Идея данного примера взята из Facebook SDK, доступного по адресу: Facebook SDK
Проект(звучит сильно конечно, ок… проектик) состоит из трех классов(ссылка на репу в конце статьи): VkSession — класс сохранения/получения параметров вконтакте(токен, user_id и т.д.), VkDialog — класс пользовательского диалога, VkApp — класс, объединяющий в себе все классы и выполняющий основную работу.
На самом деле тут и описывать то нечего. У Вконтакте есть документация по API — Дока по API. Находим функцию wall.post — Тыц. Читаем и разбираемся.
Важно понять принципы работы OAuth. В данном случае нужно получить идентификатор приложения(есть соответствующая форма) и далее работать с API, передавая данный ID. При работе с API Вконтакте будет посылать нам AccessToken, который нужно сохранять. Данный токен живет всего 24 часа, поэтому его необходимо проверять и сохранять время получения токена. Данные параметры я объединил в класс VkSession:
Как видите, ничего сложного. Полученные настройки сохраняем в SharedPreferences. Ну и все.
Далее, самое интересное. Класс VkApp, а точнее наиболее интересные его части с пояснениями:
Поясняю. Когда мы посылаем запрос, вконтакте отправляет ответ и ридеректит нас на адрес api.vkontakte.ru/blank.html, по суте это пустая страница(точную суть работы уже не припомню, писал код давно, так что имейте ввиду). Важно перехватывать данный адрес и реагировать на него нужным образом. Далее, идет собственно строка запроса со всеми нужными параметрами: наш идентификатор, scope(права доступа), тип дисплея, адрес ридеректа, вообщем все это есть в доке. Читайте!
Продолжаем:
В Андроид есть удобный набор классов от Apache для выполнения запросов, получения, разбор ответом и т.д. — HttpClient. В данном случае мы формируем GET-запрос и далее получаем ответ.
Диалог состоит из WebView и для него переопределяется клиент:
В коде клиента мы ловим посылаемые адреса от вконтакте к приложению и реагируем нужным образом. Все также просто. Конечно данный код стоит доработать и не следует смело его копировать не разобравшись. Что-то поменяется на сервере и приложение будет реагировать неправильно. Кстати, в добавлении скажу, что Facebook SDK тоже сыпется, на телефонах HTC чаще всего.
Надеюсь кому-то данная статейка будет полезной!
Как обычно, интересные предложения, замечания и прочее пишем в личку.
Код доступен здесь — репа
Уже несколько человек ждет пост о публикации записей на свою стену вконтакте. И вот эта статья. В ней будет много кода, теории вообще не будет, потому что все довольно просто и тем не менее данный пост может быть полезен тем, кто ломает голову о том как решить данную задачу.
Поехали.
Предистория
Прежде всего искал доступные варианты. Их не оказалось, поэтому обратил внимание на готовые решения для твиттера и фэйсбук и на примере последнего написал несколько классов для Вконтакте.
Идея данного примера взята из Facebook SDK, доступного по адресу: Facebook SDK
Как это работает?
Проект(звучит сильно конечно, ок… проектик) состоит из трех классов(ссылка на репу в конце статьи): VkSession — класс сохранения/получения параметров вконтакте(токен, user_id и т.д.), VkDialog — класс пользовательского диалога, VkApp — класс, объединяющий в себе все классы и выполняющий основную работу.
На самом деле тут и описывать то нечего. У Вконтакте есть документация по API — Дока по API. Находим функцию wall.post — Тыц. Читаем и разбираемся.
Важно понять принципы работы OAuth. В данном случае нужно получить идентификатор приложения(есть соответствующая форма) и далее работать с API, передавая данный ID. При работе с API Вконтакте будет посылать нам AccessToken, который нужно сохранять. Данный токен живет всего 24 часа, поэтому его необходимо проверять и сохранять время получения токена. Данные параметры я объединил в класс VkSession:
package vkontakte;
import android.content.Context;
import android.content.SharedPreferences;
public class VkSession {
private SharedPreferences _prefs;
private final String PREFS_NAME = "Vk:Settings";
private Context _context;
private SharedPreferences.Editor _editor;
public VkSession(){}
public VkSession(Context context){
_context = context;
_prefs = _context.getSharedPreferences(PREFS_NAME, 0);
_editor = _prefs.edit();
}
public void saveAccessToken(String accessToken, String expires, String userId){
_editor.putString("VkAccessToken", accessToken);
_editor.putString("VkExpiresIn", expires);
_editor.putString("VkUserId", userId);
_editor.putLong("VkAccessTime", System.currentTimeMillis());
_editor.commit();
}
public String[] getAccessToken(){
String[] params = new String[4];
params[0] = _prefs.getString("VkAccessToken", "");
params[1] = _prefs.getString("VkExpiresIn", "");
params[2] = _prefs.getString("VkUserId", "");
params[3] = String.valueOf(_prefs.getLong("VkAccessTime",0));
return params;
}
public void resetAccessToken(){
_editor.putString("VkAccessToken", "");
_editor.putString("VkExpiresIn", "");
_editor.putString("VkUserId", "");
_editor.putLong("VkAccessTime", 0);
_editor.commit();
}
}
Как видите, ничего сложного. Полученные настройки сохраняем в SharedPreferences. Ну и все.
Далее, самое интересное. Класс VkApp, а точнее наиболее интересные его части с пояснениями:
public class VkApp {
//constants for OAUTH AUTHORIZE in Vkontakte
public static final String CALLBACK_URL = "http://api.vkontakte.ru/blank.html";
private static final String OAUTH_AUTHORIZE_URL = "http://api.vkontakte.ru/oauth/authorize?client_id=2020214&scope=8192&redirect_uri=http://api.vkontakte.ru/blank.html&display=touch&response_type=token";
private Context _context;
private VkDialogListener _listener;
private VkSession _vkSess;
private String VK_API_URL = "https://api.vkontakte.ru/method/";
private String VK_POST_TO_WALL_URL = VK_API_URL + "wall.post?";
...
Поясняю. Когда мы посылаем запрос, вконтакте отправляет ответ и ридеректит нас на адрес api.vkontakte.ru/blank.html, по суте это пустая страница(точную суть работы уже не припомню, писал код давно, так что имейте ввиду). Важно перехватывать данный адрес и реагировать на него нужным образом. Далее, идет собственно строка запроса со всеми нужными параметрами: наш идентификатор, scope(права доступа), тип дисплея, адрес ридеректа, вообщем все это есть в доке. Читайте!
Продолжаем:
//parse vkontakte JSON response
private boolean parseResponse(String jsonStr){
boolean errorFlag = true;
JSONObject jsonObj = null;
try {
jsonObj = new JSONObject(jsonStr);
JSONObject errorObj = null;
if( jsonObj.has("error") ) {
errorObj = jsonObj.getJSONObject("error");
int errCode = errorObj.getInt("error_code");
if( errCode == 14){
errorFlag = false;
}
}
}
catch (JSONException e) {
e.printStackTrace();
}
return errorFlag;
}
//publicate message to vk users' wall
public boolean postToWall(String message) {
boolean errorFlag = true;
String[] params = _vkSess.getAccessToken();
String accessToken = params[0];
String ownerId = params[2];
//set request uri params
VK_POST_TO_WALL_URL += "owner_id="+ownerId+"&message="+Uri.encode(message)+"&access_token="+accessToken;
//send request to vkontakte api
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(VK_POST_TO_WALL_URL);
try {
HttpResponse response = client.execute(request);
HttpEntity entity = response.getEntity();
String responseText = EntityUtils.toString(entity);
//parse response for error code or not
errorFlag = parseResponse(responseText);
}
catch(ClientProtocolException cexc){
cexc.printStackTrace();
}
catch(IOException ioex){
ioex.printStackTrace();
}
return errorFlag;
}
В Андроид есть удобный набор классов от Apache для выполнения запросов, получения, разбор ответом и т.д. — HttpClient. В данном случае мы формируем GET-запрос и далее получаем ответ.
Диалог состоит из WebView и для него переопределяется клиент:
private class VkWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith(VkApp.CALLBACK_URL) & ( !url.contains("error") )) {
mListener.onComplete(url);
VkDialog.this.dismiss();
return true;
}
else if(url.contains("error")){
VkDialog.this.dismiss();
return false;
}
else {
view.loadUrl(url);
return true;
}
}
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
mListener.onError(description);
VkDialog.this.dismiss();
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
if( url.contains("error") ) {
VkDialog.this.dismiss();
return;
}
else if( url.contains("access_token")) {
VkDialog.this.dismiss();
mListener.onComplete(url);
return;
}
mSpinner.show();
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
mSpinner.dismiss();
}
}
В коде клиента мы ловим посылаемые адреса от вконтакте к приложению и реагируем нужным образом. Все также просто. Конечно данный код стоит доработать и не следует смело его копировать не разобравшись. Что-то поменяется на сервере и приложение будет реагировать неправильно. Кстати, в добавлении скажу, что Facebook SDK тоже сыпется, на телефонах HTC чаще всего.
Надеюсь кому-то данная статейка будет полезной!
Как обычно, интересные предложения, замечания и прочее пишем в личку.
Код доступен здесь — репа