- PVSM.RU - https://www.pvsm.ru -

VK notifer на java

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

  • Скрасить время своей реабилитации
  • Решить проблему с доставкой сообщений
  • Попробовать себя в написании программ на java

Итоги получившейся java терапии под катом

Хочется начать с того, что на java я никогда не программировал, поэтому я не претендую на гениальность своего приложения.
Поохав, устроившись поудобнее и пододвинув зарядку поближе, я начал свое первое приложение на этом чудесном языке.
Первое, что я решил сделать, это соорудить «каркас» для моего notifer'а. Все что мне было необходимо — это простое меню в трее, которое бы выдавало всплывающие сообщения.

//Создадим раскрывающееся меню
PopupMenu popup = new PopupMenu();
//Создадим элемент меню
MenuItem exitItem = new MenuItem("Выход");
//Добавим для него обработчик
exitItem.addActionListener(new ActionListener(){
	public void actionPerformed(ActionEvent e) {
		System.exit(0);
	}
});
//Добавим пункт в меню
popup.add(exitItem);
SystemTray systemTray = SystemTray.getSystemTray();
Image image = Toolkit.getDefaultToolkit().getImage("vk_icon.png");
TrayIcon trayIcon = new TrayIcon(image,"VKNotifer",popup);
trayIcon.setImageAutoSize(true);
//добавим иконку в трей
systemTray.add(trayIcon);
//тестовое сообщение
trayIcon.displayMessage("VKNotifer", "Текст",TrayIcon.MessageType.INFO);

Теперь главная задача — это получать список текущих сообщений. Для этой цели я воспользовался предоставленным api Вконтакте. С основной информацией по api можно ознакомиться здесь [1].
Первое что нужно сделать для того, чтобы иметь возможность использовать api, это создать приложение Вконтакте [2], после чего вы получите id своего приложения необходимый для получения token'а.
Второе действие для доступа к api — это получение самого token'а. Для этого необходимо в вашем приложении пройти следующие этапы:

  1. Авторизация
  2. Подтверждение запрашиваемых требований
  3. Непосредственно получение token'а

После этого, благодаря полученному token'у, вы сможете выполнять методы api. Процесс авторизации описан здесь [3]
Для этих целей я создал класс VKapi, который будет иметь два метода: Получить token и получить список сообщений.
Метод первый — получение token'а:

HttpClient httpClient = new DefaultHttpClient();
// Делаем первый запрос
HttpPost post = new HttpPost("http://oauth.vk.com/authorize?" +
		"client_id="+client_id+
		"&scope="+scope+
		"&redirect_uri="+redirect_uri+
		"&display="+display+
		"&response_type="+response_type);
HttpResponse response;
response = httpClient.execute(post);
post.abort();
//Получаем редирект
String HeaderLocation = response.getFirstHeader("location").getValue();
URI RedirectUri = new URI(HeaderLocation);
//Для запроса авторизации необходимо два параметра полученных в первом запросе
//ip_h и to_h
String ip_h= RedirectUri.getQuery().split("&")[2].split("=")[1];
String to_h=RedirectUri.getQuery().split("&")[4].split("=")[1];
// Делаем запрос авторизации
post = new HttpPost("https://login.vk.com/?act=login&soft=1"+
		"&q=1"+
		"&ip_h="+ip_h+
		"&from_host=oauth.vk.com"+
		"&to="+to_h+
		"&expire=0"+
		"&email="+email+
		"&pass="+pass);
response = httpClient.execute(post);
post.abort();
// Получили редирект на подтверждение требований приложения
HeaderLocation = response.getFirstHeader("location").getValue();
post = new HttpPost(HeaderLocation);
// Проходим по нему
response = httpClient.execute(post);
post.abort();
// Теперь последний редирект на получение токена
HeaderLocation = response.getFirstHeader("location").getValue();
// Проходим по нему
post = new HttpPost(HeaderLocation);
response = httpClient.execute(post);
post.abort();
// Теперь в след редиректе необходимый токен
HeaderLocation = response.getFirstHeader("location").getValue();
// Просто спарсим его сплитами
access_token = HeaderLocation.split("#")[1].split("&")[0].split("=")[1];

Для получения списка сообщений api Вконтакте имеет метод messages.get [4]
Метод второй — получение списка сообщений:

//формируем строку запроса
String url = "https://api.vk.com/method/"+
		"messages.get"+
		"?out=0"+
		"&access_token="+access_token
		;
String line = "";
try {
            URL url2 = new URL(url);
            BufferedReader reader = new BufferedReader(new InputStreamReader(url2.openStream()));
            line = reader.readLine();
            reader.close();

        } catch (MalformedURLException e) {
            // ...
        } catch (IOException e) {
            // ...
        }
return line;

Класс полностью:

public class VKapi {
	private String client_id = "2971510";
	private String scope = "messages";
	private String redirect_uri = "http://oauth.vk.com/blank.html";
	private String display = "popup";
	private String response_type = "token";
	private String access_token;
	private String email = "******";//тут должен быть прописан email
	private String pass = "******";//тут должен быть прописан пароль
	public void setConnection() throws IOException, URISyntaxException {
        //Ранее описанный код получения token'a
	}
	public String getNewMessage() throws ClientProtocolException, IOException, NoSuchAlgorithmException, URISyntaxException {
         //Ранее описанный код получения списка сообщений
	}
}

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

public static void main(String[] args) throws IOException, URISyntaxException, AWTException, InterruptedException, NoSuchAlgorithmException {
	//Создадим раскрывающееся меню
	PopupMenu popup = new PopupMenu();
	//Создадим элемент меню
	MenuItem exitItem = new MenuItem("Выход");
	//Добавим для него обработчик
	exitItem.addActionListener(new ActionListener(){
		public void actionPerformed(ActionEvent e) {
			System.exit(0);
		}
	});
	//Добавим пункт в меню
	popup.add(exitItem);
	SystemTray systemTray = SystemTray.getSystemTray();
	//получим картинку
	Image image = Toolkit.getDefaultToolkit().getImage("vk_icon.png");
	TrayIcon trayIcon = new TrayIcon(image,"VKNotifer",popup);
	trayIcon.setImageAutoSize(true);
	//добавим иконку в трей
	systemTray.add(trayIcon);
	trayIcon.displayMessage("VKNotifer", "Соединяемся с сервером",TrayIcon.MessageType.INFO);
	//Создадим экземпляр класса ВКапи
	VKapi vkAPI = new VKapi();
	//Получим токен
	vkAPI.setConnection();
	trayIcon.displayMessage("VKNotifer", "Соединение установлено",TrayIcon.MessageType.INFO);
	//Бескоечный цикл
	String oldMessage = vkAPI.getNewMessage();
	String newMessage;
	int i = 0;
	for (;;){
		// Запросы на сервер можно подавать раз в 3 секунды
		Thread.sleep(3000); // ждем три секунды
		if (i == 15000){  // Если прошло 45 000 сек (Время взято с запасом, токен дается на день )
			vkAPI.setConnection(); // Обновляем токен
			Thread.sleep(3000);    // Запросы шлем только раз в три секунды
			i = 0;
		}
		//Здесь отработка 
		newMessage = vkAPI.getNewMessage();
		if (!newMessage.equals(oldMessage)) {
			oldMessage = newMessage;
			trayIcon.displayMessage("VKNotifer", "Получено новое сообщение",TrayIcon.MessageType.INFO);
			Tools.playDrum(Drum.d53_Ride_Bell, 127,0);
		}
		i++;
	}
}

Кроме всплывающего окна, также используется звуковое оповещение.

Tools.playDrum(Drum.d53_Ride_Bell, 127,0);

Для этого используется библиотека из этого топика [5]

Я знаю, что это не идеальное исполнение, но самое главное — оно вполне решило мои проблемы. Спасибо за внимание.

Автор: matim


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/java/8517

Ссылки в тексте:

[1] здесь: http://vk.com/developers.php#devstep1

[2] создать приложение Вконтакте: http://vk.com/editapp?act=create

[3] здесь: http://vk.com/developers.php?id=-1_37230422&s=1

[4] messages.get: http://vk.com/developers.php?oid=-1&p=messages.get

[5] этого топика: http://habrahabr.ru/post/127840/