Java: Twitter sender – jednoduchý program pro odesílání zpráv
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.
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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í:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
//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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
//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:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//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:
1 2 3 4 5 6 7 8 9 |
//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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
//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í:
1 2 3 4 5 6 7 8 |
/** * 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ě:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
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.
1 2 3 4 5 6 7 8 9 10 |
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í:
1 2 3 4 5 6 7 8 9 10 |
//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:
1 2 3 4 5 6 7 8 9 10 11 12 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
//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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
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); } } |