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
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.
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.
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);
}
}