package misc; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.Reader; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.ProtocolException; import java.net.URL; import java.net.URLEncoder; import java.util.Date; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.logging.Level; import java.util.logging.Logger; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSession; import models.Notification; import models.Report; import models.User; public class C2DM { public String token; public boolean wasLastStatusOK = true; private String obtainToken() throws IOException { // Create the post data // Requires a field with the email and the password StringBuilder builder = new StringBuilder(); builder.append("Email=").append("park.alert.codebits@gmail.com"); builder.append("&Passwd=").append("parkalertappcodebits"); builder.append("&accountType=GOOGLE"); builder.append("&source=MyLittleExample"); builder.append("&service=ac2dm"); // Setup the Http Post byte[] data = builder.toString().getBytes(); URL url = new URL("https://www.google.com/accounts/ClientLogin"); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setUseCaches(false); con.setDoOutput(true); con.setRequestMethod("POST"); con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); con.setRequestProperty("Content-Length", Integer.toString(data.length)); // Issue the HTTP POST request OutputStream output = con.getOutputStream(); output.write(data); output.close(); // Read the response BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream())); String line = null; String auth_key = null; while ((line = reader.readLine()) != null) { if (line.startsWith("Auth=")) { auth_key = line.substring(5); } } // Finally get the authentication token // To something useful with it return auth_key; } private final static String AUTH = "authentication"; private static final String UPDATE_CLIENT_AUTH = "Update-Client-Auth"; public static final String PARAM_REGISTRATION_ID = "registration_id"; public static final String PARAM_DELAY_WHILE_IDLE = "delay_while_idle"; public static final String PARAM_COLLAPSE_KEY = "collapse_key"; private static final String UTF8 = "UTF-8"; private static final Integer DEFAULT_BACKOFF = 30000; public void sendMessage(Report report, User dest, String message) { Notification notif = new Notification(dest, report.user, new Date(), report.latitude, report.longitude, "c2dm"); notif.save(); dest.notifications.add(notif); dest.save(); message += ":"+notif.id+":"+notif.latitude+":"+notif.longitude; final Logger LOGGER = Logger.getLogger("MessageLog"); LOGGER.setLevel(Level.INFO); LOGGER.info("Sent notif number "+notif.id); try { StringBuilder postDataBuilder = new StringBuilder(); postDataBuilder.append(PARAM_REGISTRATION_ID).append("=").append(dest.c2dmID); postDataBuilder.append("&").append(PARAM_COLLAPSE_KEY).append("=").append("0"); postDataBuilder.append("&").append("data.payload").append("=").append(URLEncoder.encode(message, UTF8)); byte[] postData = postDataBuilder.toString().getBytes(UTF8); // Hit the dm URL. URL url = new URL("https://android.clients.google.com/c2dm/send"); HttpsURLConnection.setDefaultHostnameVerifier(new CustomizedHostnameVerifier()); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); conn.setDoOutput(true); conn.setUseCaches(false); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); conn.setRequestProperty("Content-Length", Integer.toString(postData.length)); conn.setRequestProperty("Authorization", "GoogleLogin auth=" + token); OutputStream out = conn.getOutputStream(); out.write(postData); out.close(); int responseCode = conn.getResponseCode(); handleResponseCode(report, dest,responseCode,conn); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private void handleResponseCode(Report report, User user, int responseCode, HttpsURLConnection conn) throws IOException { switch(responseCode) { case 200: { wasLastStatusOK = true; System.out.println(responseCode); BufferedReader b = new BufferedReader(new InputStreamReader(conn.getInputStream())); String s = b.readLine(); System.out.println(s); String error = s; if(s!=null) { error = s.replace("Error=", ""); } // TODO: meter o comportamento if(error.equals("QuotaExceeded")) { System.out.println("QuotaExceeded"); } else if(error.equals("DeviceQuotaExceeded")) { System.out.println("DeviceQuotaExceeded"); } else if(error.equals("InvalidRegistration")) { System.out.println("InvalidRegistration"); } else if(error.equals("NotRegistered")) { System.out.println("NotRegistered"); } else if(error.equals("MessageTooBig")) { System.out.println("MessageTooBig"); } else if(error.equals("MissingCollapseKey")) { System.out.println("MissingCollapseKey"); } break; } case 401: { if(!wasLastStatusOK) { SMSUtils.sendSMS(user,report); final Logger LOGGER = Logger.getLogger("MessageLog"); LOGGER.setLevel(Level.INFO); LOGGER.info("Sending to: "+"+351"+user.cellphone); return; } try { System.out.println("401"); token = obtainToken(); wasLastStatusOK = false; sendMessage(report, user, "Reportado um funcionário perto do seu carro!"); } catch (IOException e) { e.printStackTrace(); } break; } case 503: { System.out.println(responseCode); Integer backoff = Integer.parseInt(conn.getHeaderField("Retry-After")); backoff(backoff); } default : { System.out.println("Default?!"); } } } private static void backoff(Integer backoff) { if(backoff==null) backoff = DEFAULT_BACKOFF; try { Thread.sleep(backoff); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } backoff*=2; } private static class CustomizedHostnameVerifier implements HostnameVerifier { public boolean verify(String hostname, SSLSession session) { return true; } } }