http://www.zaachi.com/cs/items/java-twitter-sender-jednoduchy-program-na-odesilani-zprav.html

Java: Twitter sender – jednoduchý program pro odesílání zpráv

Publikováno: 08.03.2008 10:06:58

Jak vytvořit jednoduchý program, který je schopný se připojit na Twitter pod uživatelským účtem a aktualizovat status.

Uděláme si jednoduchý program, který se dokáže připojit na Twitter a aktualizovat profil daného twitter sender uživatele. V grafickém rozhraní bude možnost nastavit uživatelského jména a hesla k účtu. Pod těmito údaji se program připojí a nastaví nový aktuální status.

GUI bude opravdu jednoduché, v němž bude možné vyplnit uživatelské údaje a text nové zprávy.

Navíc je program rozšířen o možnost minimalizace do tray, kterou jsem ukázal v minulém článku . Program bude schopen uživateli vypsat jednoduché informace o úspěchu nebo neúspěchu operace.

Grafické rozhraní – Twitter_Sender

Jako první si napíšeme grafické rozhraní k programu.

Grafické rozhraní bude muset obsahovat komponenty pro zadání uživatelského jména, jeho hesla. Dále textové pole pro napsání nové zprávy a pole pro výpis hlášení.

Vytvoříme jednoduché okno JFrame o rozměrech 300x240px:

public class TS_GUI extends JFrame {
	public TS_GUI() {
		//titulek okna
		setTitle("Twitter Sender");
		//nastaveni rozmeru okna
		setSize(new Dimension(300, 240));
		//umisteni okna
		Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
		setLocation(screen.width / 3, screen.height / 3);
		//defaultni operace pro zavreni
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//znemozneni zmeny rozmeru okna
		this.setResizable(false);
		
		//container pro frame
		Container cont = getContentPane();
		//Vytvoreni Flow Layoutu pro frame
		FlowLayout fl = new FlowLayout();
		cont.setLayout(fl);
	}
}

A nyní můžeme do okna přidávat grafické prvky v podobě JtextFieldů a Jlabelů. JTExtField využijeme jak pro zadání přihlašovacích údajů, tak pro zadávání nové zprávy. Pro výpis statusu použijeme JtextAreu, protože bude obsahovat více než jeden řádek informací:

//Popisek pro buttony
JLabel name = new JLabel("Login/password: ");
JLabel l = new JLabel("/");
//buttony pro jmeno a heslo
final JTextField user_name = new JTextField(7);
final JPasswordField password = new JPasswordField(7);
cont.add(name);
cont.add(user_name);
cont.add(l);
cont.add(password);

//TextField pro text
final JTextField area = new JTextField(24);
area.setBorder(BorderFactory.createTitledBorder("New Status Message"));
//tlacitko pro odeslani
JButton button = new JButton("send message");
button.setPreferredSize(new Dimension(270, 20));

//area pro status
final JTextArea status = new JTextArea(4, 24);
status.setBorder(BorderFactory.createTitledBorder("sending status"));
status.setEditable(false);
JScrollPane scr = new JScrollPane(status);

//label pro informace
final JLabel label = new JLabel("Autor: Jiří Zachar - zaachi@gmail.com");
Font font = new Font("Arial", Font.TYPE1_FONT, 10);
label.setFont(font);

Pro odeslání formuláře nám slouží tlačítko button, ke kterému musíme přidat pro odeslání ActionListener.

Před odesláním zkontrolujeme některé věci jako prázdné inputy pro jméno a heslo, nebo délku textu v poli se zprávou, která může být maximálně 160 znaků. Pro odeslání vytvoříme novou instanci třídy Twitter_Sender, ktreou si napíšeme později.

//Action listener pro button
button.addActionListener(new ActionListener() {
	public void actionPerformed(ActionEvent arg0) {
		//kontrola jmena
		if (user_name.getText().trim().length() == 0) {
			joptionpane("Login name is empty");
			return;
		}
		//kontrola hesla
		if (password.getText().trim().length() == 0) {
			joptionpane("Password is empty");
			return;
		}
		//kontrola zpravy
		if (area.getText().trim().length() == 0) {
			joptionpane("String status message is empty");
			return;
		}
		//kontrola zpravy na delku
		if (area.getText().trim().length() >= 160) {
			joptionpane("Text is too long. Maximum chars is 160.");
			return;
		}
		
		//vytvoreni nove instance Twitter_Sender pro odeslani
		new Twitter_Sender(user_name.getText().trim(), password
				.getText().trim(), area.getText().trim(), status);
		
		//vymazani hodnot
		area.setText("");
		label.setText("Chars: 0");
	}
});

Můžeme si ještě vytvořit KeyListener pro textové pole zprávy a například do labelu s informacemi pro uživatele psát počet znaků, které uživatel napsal:

//Key Listener pro textove pole
area.addKeyListener(new KeyListener() {
	public void keyPressed(KeyEvent arg0) {	
	}

	public void keyReleased(KeyEvent arg0) {
		label.setText("Chars: " + area.getText().trim().length() );
	}

	public void keyTyped(KeyEvent arg0) {
	}

});

Nakonec všechny komponenty umístíme do framu:

//umisteni komponent do framu
cont.add(area);
status.setBackground(Color.getColor("gray"));
cont.add(button);
cont.add(scr);
cont.add(label);
setVisible(true);

trayicon();

Všiměte si volání metody trayicon, která umožní uživateli minimalizovat program do tray tak aby nezabíral na ploše místo. Tuto problematiku jsem probral v minulém článku , takže zde je pouze daná metoda:

//tray ikona
private void trayicon() {
	if (SystemTray.isSupported()) {
		SystemTray tray = SystemTray.getSystemTray();
		Image image = Toolkit.getDefaultToolkit().getImage("trayicon.gif");

		PopupMenu popup = new PopupMenu();

		MenuItem exit = new MenuItem("Exit");

		exit.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				System.exit(0);
			}
		});

		popup.add(exit);

		TrayIcon trayIcon = new TrayIcon(image, "TS_GUI", popup);
		try {
			tray.add(trayIcon);
		} catch (AWTException e) {
			;
		}
		trayIcon.addMouseListener(new MouseListener() {
			public void mouseClicked(MouseEvent arg0) {
				if (arg0.getButton() == 1)
					setvisible();
			}

			public void mouseEntered(MouseEvent arg0) {
			}

			public void mouseExited(MouseEvent arg0) {
			}

			public void mousePressed(MouseEvent arg0) {
			}

			public void mouseReleased(MouseEvent arg0) {
			}

		});
	} else {
		;
	}

}

private void setvisible() {
	if (this.isVisible() == true) {
		this.setVisible(false);
	} else {
		this.setVisible(true);
	}
}

Tray ikona se chová velice jednoduše. Obsahuje pouze popup menu pro vypnutí celého programu. Po kliknutí na ikonu se program minimalizuje nebo maximalizuje v závislosti na nastavení aktuální hodnoty Visible.

Z grafického rozhraní nám zůstává poslední metoda, kterou program používá, a to pro vypisování chybových hlášení:

/**
 * Joption pane pro zobrazovani hlaseni
 * @param message
 */
private void joptionpane(String message) {
	JOptionPane.showMessageDialog(null, message, "Warning",
			JOptionPane.WARNING_MESSAGE);
}

Na konci článku se nachází kompletní zdrojový kód celé třídy.

Class Twitter_Sender

Pokud je grafické rozhraní hotové, nezbývá než jej zpracovat.

V Action Listeneru tlačítka pro odeslání jsme vytvářeli novou instanci třídy Twitter_Sender, kterou si nyní napíšeme.

Jako vstupní proměnné si do třídy předáváme jméno, heslo, zprávu a ukazatel na JTExtAreu pro výpis statusu.

Pro update statusu nám slouží adresa http://twitter.com/statuses/update.json, kterou budeme v programu používat.

Před odesláním statusu bude potřeba aby se program přihlásil na daný uživatelský účet dle zadaných hodnot v textových polích.

Nejprve si vytvoříme novou třídu, ve které vytvoříme ze vstupních proměnných proměnné globální, abychom k nim mohli přistupovat v celé třídě:

public class Twitter_Sender {
	public String url = "http://twitter.com/statuses/update.json";

	private String name = null;

	private String pass = null;

	private String message = null;

	private JTextArea status;

	/**
	 * 
	 * @param name
	 * @param password
	 * @param message
	 * @param status
	 */
	public Twitter_Sender(String name, String password, String message,
			JTextArea status) {
		//nastaveni promennych
		this.name = name;
		this.pass = password;
		this.message = message;
		this.status = status;
	}
}

Při zpracovávání uživateslkých dat budeme postupně do stavového pole vypisovat uživateli informace o prováděném úkonu.

Jako první se musíme připojit na příslušnou URL adresu. Pro tuto operaci si napíšeme zvláštní metodu, která bude vracet identifikátor spojení.

Metoda pouze otevře nové spojení s danou url adresou:

private HttpURLConnection connection() {
	URL senddata;
	try {
		//vytvoreni nove URL
		senddata = new URL(url);
		HttpURLConnection con = null;
		try {
			//otevreni url
			con = (HttpURLConnection) senddata.openConnection();
		} catch (IOException e) {
			e.printStackTrace();
		}
		//vraci ID spojeni
		return con;
	} catch (MalformedURLException e) {
		e.printStackTrace();
	}
	return null;
}

Použití metody je asi jasné. Stačí vytvořit novou proměnnou typu HttpURLConnection a návratovou hodnotu z metody do této proměnné předat.

HttpURLConnection con;
//pripojeni pro update
this.status.append("Connection to twitter:  ");
con = connection();
if (con == null) {
	this.status.append("Disconnectedn");
	return;
}
//informace pro uzivatele
this.status.append("Connectedn");

Nyní provedeme základní nastavení spojení a pokusíme se na serveru přihlásit pod uživateslkým účtem.

Pro tuto operaci si opět můžeme udělat vlastní metodu, kterou pouze zavoláme.

Nejprve volání příslušné metody a nastavení spojení:

//zakladni nastaveni spojeni
con.setDoOutput(true);
con.setRequestMethod("POST");
con.setDoInput(true);

//informace pro uzivatele
this.status.append("Login: ");
//identifikace uzivatele
user(con);
this.status.append("Logedn");

Metoda pro identifikaci uživatele se jmenuje user a jako vstupní parametr je identifikátor spojení.

Metoda připravý data pro identifikaci, zakóduje je pomocí base64 a odešle na server pomocí setRequestProperty:

private void user(HttpURLConnection con) {
	//priprava dat pro identifikaci uzivatele
	String userPassword = this.name + ":" + this.pass;
	//zakodovani dat do BASE64
	String encoding = new sun.misc.BASE64Encoder().encode(userPassword
			.getBytes());
	//odeslani hlavicky
	con.setRequestProperty("Content-Type",
			"application/x-www-form-urlencoded");
	//identifikace uzivatele
	con.setRequestProperty("Authorization", "Basic " + encoding);
}

Pokud jsme přihlášení, musíme si připravit data pro odeslání na server. Pomocí setRequestProperty odešleme příslušné hlavičky a nakonec odešleme data pomocí OutputStreamu:

//priprava dat pro odeslani
StringBuilder datatosending = new StringBuilder();
//nastaveni POST promenne "status"
datatosending.append("status");
datatosending.append("=");
datatosending.append(this.message);

//infromace pro uzivatele
this.status.append("Sending message: ");

//odeslani hlavicky
con.setRequestProperty("Content-Length", ""
		+ datatosending.length());
//vytvoreni outputStreamu pro odelsani
OutputStream os = (OutputStream) con.getOutputStream();
//odeslani dat
os.write(datatosending.toString().getBytes());
os.close();
con.getInputStream();
this.status.append("Sendedn");

A tím je celý program hotový.

Program slouží pouze pro odesílání nového statusu na Twitter, ale nebylo by problém jej rozšířit i například o novou registraci, mazání zpráv a podobně. Stačilo by se pouze připojovat na příslušné URL adresy a odesílat správná data.

Nakonec opět celý kód, který je rozdělen na dvě třídy:

TS_GUI

import java.awt.AWTException;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

/**
 * 
 * @author zaachi
 * 
 */
public class TS_GUI extends JFrame {
	public TS_GUI() {
		//titulek okna
		setTitle("Twitter Sender");
		//nastaveni rozmeru okna
		setSize(new Dimension(300, 240));
		//umisteni okna
		Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
		setLocation(screen.width / 3, screen.height / 3);
		//defaultni operace pro zavreni
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//znemozneni zmeny rozmeru okna
		this.setResizable(false);
		
		//container pro frame
		Container cont = getContentPane();
		//Vytvoreni Flow Layoutu pro frame
		FlowLayout fl = new FlowLayout();
		cont.setLayout(fl);
		
		//Popisek pro buttony
		JLabel name = new JLabel("Login/password: ");
		JLabel l = new JLabel("/");
		//buttony pro jmeno a heslo
		final JTextField user_name = new JTextField(7);
		final JPasswordField password = new JPasswordField(7);
		cont.add(name);
		cont.add(user_name);
		cont.add(l);
		cont.add(password);
		
		//TextField pro text
		final JTextField area = new JTextField(24);
		area.setBorder(BorderFactory.createTitledBorder("New Status Message"));
		//tlacitko pro odeslani
		JButton button = new JButton("send message");
		button.setPreferredSize(new Dimension(270, 20));
		
		//area pro status
		final JTextArea status = new JTextArea(4, 24);
		status.setBorder(BorderFactory.createTitledBorder("sending status"));
		status.setEditable(false);
		JScrollPane scr = new JScrollPane(status);
		
		//label pro informace
		final JLabel label = new JLabel("Autor: Jiří Zachar - zaachi@gmail.com");
		Font font = new Font("Arial", Font.TYPE1_FONT, 10);
		label.setFont(font);
		
		//Action listener pro button
		button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				//kontrola jmena
				if (user_name.getText().trim().length() == 0) {
					joptionpane("Login name is empty");
					return;
				}
				//kontrola hesla
				if (password.getText().trim().length() == 0) {
					joptionpane("Password is empty");
					return;
				}
				//kontrola zpravy
				if (area.getText().trim().length() == 0) {
					joptionpane("String status message is empty");
					return;
				}
				//kontrola zpravy na delku
				if (area.getText().trim().length() >= 160) {
					joptionpane("Text is too long. Maximum chars is 160.");
					return;
				}
				
				//vytvoreni nove instance Twitter_Sender pro odeslani
				new Twitter_Sender(user_name.getText().trim(), password
						.getText().trim(), area.getText().trim(), status);
				
				//vymazani hodnot
				area.setText("");
				label.setText("Chars: 0");
			}
		});
		//Key Listener pro textove pole
		area.addKeyListener(new KeyListener() {
			public void keyPressed(KeyEvent arg0) {	
			}
		
			public void keyReleased(KeyEvent arg0) {
				label.setText("Chars: " + area.getText().trim().length() );
			}
		
			public void keyTyped(KeyEvent arg0) {
			}
		
		});
		//umisteni komponent do framu
		cont.add(area);
		status.setBackground(Color.getColor("gray"));
		cont.add(button);
		cont.add(scr);
		cont.add(label);
		setVisible(true);
		
				trayicon();
	}

	//tray ikona
	private void trayicon() {
		if (SystemTray.isSupported()) {
			SystemTray tray = SystemTray.getSystemTray();
			Image image = Toolkit.getDefaultToolkit().getImage("trayicon.gif");
	
			PopupMenu popup = new PopupMenu();
	
			MenuItem exit = new MenuItem("Exit");
	
			exit.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					System.exit(0);
				}
			});
	
			popup.add(exit);
	
			TrayIcon trayIcon = new TrayIcon(image, "TS_GUI", popup);
			try {
				tray.add(trayIcon);
			} catch (AWTException e) {
				;
			}
			trayIcon.addMouseListener(new MouseListener() {
				public void mouseClicked(MouseEvent arg0) {
					if (arg0.getButton() == 1)
						setvisible();
				}
	
				public void mouseEntered(MouseEvent arg0) {
				}
	
				public void mouseExited(MouseEvent arg0) {
				}
	
				public void mousePressed(MouseEvent arg0) {
				}
	
				public void mouseReleased(MouseEvent arg0) {
				}
	
			});
		} else {
			;
		}
	
	}
	
	private void setvisible() {
		if (this.isVisible() == true) {
			this.setVisible(false);
		} else {
			this.setVisible(true);
		}
	}

	/**
	 * Joption pane pro zobrazovani hlaseni
	 * @param message
	 */
	private void joptionpane(String message) {
		JOptionPane.showMessageDialog(null, message, "Warning",
				JOptionPane.WARNING_MESSAGE);
	}

	/**
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		new TS_GUI();

	}

}

Twitter_Sender

import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import javax.swing.JTextArea;

/**
 * 
 * @author zaachi
 *
 */
public class Twitter_Sender {
	public String url = "http://twitter.com/statuses/update.json";

	private String name = null;

	private String pass = null;

	private String message = null;

	private JTextArea status;

	/**
	 * 
	 * @param name
	 * @param password
	 * @param message
	 * @param status
	 */
	public Twitter_Sender(String name, String password, String message,
			JTextArea status) {
		//nastaveni promennych
		this.name = name;
		this.pass = password;
		this.message = message;
		this.status = status;

		try {
			HttpURLConnection con;
			//pripojeni pro update
			this.status.append("Connection to twitter:  ");
			con = connection();
			if (con == null) {
				this.status.append("Disconnectedn");
				return;
			}
			//informace pro uzivatele
			this.status.append("Connectedn");

			//zakladni nastaveni spojeni
			con.setDoOutput(true);
			con.setRequestMethod("POST");
			con.setDoInput(true);
			
			//informace pro uzivatele
			this.status.append("Login: ");
			//identifikace uzivatele
			user(con);
			this.status.append("Logedn");
			
			//priprava dat pro odeslani
			StringBuilder datatosending = new StringBuilder();
			//nastaveni POST promenne "status"
			datatosending.append("status");
			datatosending.append("=");
			datatosending.append(this.message);
			
			//infromace pro uzivatele
			this.status.append("Sending message: ");
			
			//odeslani hlavicky
			con.setRequestProperty("Content-Length", ""
					+ datatosending.length());
			//vytvoreni outputStreamu pro odelsani
			OutputStream os = (OutputStream) con.getOutputStream();
			//odeslani dat
			os.write(datatosending.toString().getBytes());
			os.close();
			con.getInputStream();
			this.status.append("Sendedn");
		} catch (Exception e) {
			//informace pro uzivatele
			this.status.append(String.valueOf(e).replace(":", ":n"));
		}
	}

	/**
	 * 
	 * @return
	 */
	private HttpURLConnection connection() {
		URL senddata;
		try {
			//vytvoreni nove URL
			senddata = new URL(url);
			HttpURLConnection con = null;
			try {
				//otevreni url
				con = (HttpURLConnection) senddata.openConnection();
			} catch (IOException e) {
				e.printStackTrace();
			}
			//vraci ID spojeni
			return con;
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 
	 * @param con
	 */
	private void user(HttpURLConnection con) {
		//priprava dat pro identifikaci uzivatele
		String userPassword = this.name + ":" + this.pass;
		//zakodovani dat do BASE64
		String encoding = new sun.misc.BASE64Encoder().encode(userPassword
				.getBytes());
		//odeslani hlavicky
		con.setRequestProperty("Content-Type",
				"application/x-www-form-urlencoded");
		//identifikace uzivatele
		con.setRequestProperty("Authorization", "Basic " + encoding);
	}

}