Java tutorial
/** * DirectSIDING: Log-in directo al SIDING desde tu dispositivo Android. * La idea original de DirectSIDING fue de Pedro Pablo Aste Kompen. * * Copyright (C) 2013 Lukas Zorich * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.directsiding.android; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.security.KeyStore; import javax.net.ssl.HttpsURLConnection; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.cookie.Cookie; import android.annotation.SuppressLint; import android.app.Activity; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.net.http.SslError; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.SystemClock; import android.support.v4.app.NavUtils; import android.support.v4.app.NotificationCompat; import android.text.Spannable; import android.text.SpannableString; import android.view.View; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.AnimationUtils; import android.webkit.CookieManager; import android.webkit.CookieSyncManager; import android.webkit.DownloadListener; import android.webkit.SslErrorHandler; import android.webkit.WebChromeClient; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.ProgressBar; import android.widget.Toast; import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.app.SherlockActivity; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuItem; import com.actionbarsherlock.view.Window; @SuppressLint("setJavaScriptEnabled") public class WebActivity extends SherlockActivity { private WebView webView; private ProgressBar mProgressBar; private NotificationManager mNotifyManager; private NotificationCompat.Builder mBuilder; private static int actualNotifyId = 0; private static final int LOGOUT_MILI_TIME = 3600000; private static final int[] downloadAnimationIcons = { R.drawable.stat_sys_download_anim0, R.drawable.stat_sys_download_anim1, R.drawable.stat_sys_download_anim2, R.drawable.stat_sys_download_anim3, R.drawable.stat_sys_download_anim4, R.drawable.stat_sys_download_anim5 }; private long lastTimeStamp; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); setContentView(R.layout.activity_web); // Le ponemos la font Signika al titulo del Action Bar SpannableString s = new SpannableString(getString(R.string.app_name)); s.setSpan(new TypefaceSpan(this, LoginActivity.PATH_SIGNIKA_FONT), 0, s.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // Agregamos lo necesario al Action Bar ActionBar actionBar = getSupportActionBar(); actionBar.setTitle(s); actionBar.setDisplayShowHomeEnabled(true); actionBar.setHomeButtonEnabled(true); // Obtenemos la url a la que el usuario va a ingresar String url = getIntent().getExtras().getString(LoginActivity.EXTRA_URL); // Obtenemos la cookie y la agregamos al webview Cookie sessionCookie = LoginOpActivity.cookie; CookieSyncManager.createInstance(this); CookieManager cookieManager = CookieManager.getInstance(); if (sessionCookie != null) { //cookieManager.removeSessionCookie(); String cookieString = sessionCookie.getName() + "=" + sessionCookie.getValue() + "; domain=" + sessionCookie.getDomain(); cookieManager.setCookie(LoginActivity.POST_URL, cookieString); CookieSyncManager.getInstance().sync(); } mProgressBar = (ProgressBar) findViewById(R.id.progressBar_webView); webView = (WebView) findViewById(R.id.webView_ing); webViewConfig(); webView.loadUrl(url); //webView.loadUrl("http://www.google.com"); // guardamos el tiempo en el que se creo la actividad lastTimeStamp = SystemClock.elapsedRealtime(); } /** * Configuracin del WebView */ private void webViewConfig() { webView.getSettings().setBuiltInZoomControls(true); // Para HoneyComb o mayor, sacamos los controles del zoom if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { webView.getSettings().setDisplayZoomControls(false); } webView.getSettings().setJavaScriptEnabled(true); webView.setWebChromeClient(new WebChromeClient() { public void onProgressChanged(WebView view, int progress) { mProgressBar.setProgress(progress); } }); webView.setWebViewClient(new DirectSidingWebViewClient()); webView.setDownloadListener(new DownloadListener() { public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) { String filename = getFileName(contentDisposition); Toast.makeText(WebActivity.this, "Iniciando descarga ...", Toast.LENGTH_SHORT).show(); new DownloadFile(WebActivity.actualNotifyId++, filename).execute(url); } }); } private String getFileName(String contentDisposition) { String aux = contentDisposition.split("; ")[1]; return aux.substring("filename=\"".length(), aux.length() - 1); } @Override protected void onResume() { super.onResume(); // Si la actividad estubo inactiva mas de dos horas, el SIDING deslogea automaticamente al usuario, // entonces para que no pase eso, iniciamos la InitActivity para que se autologee if (SystemClock.elapsedRealtime() - lastTimeStamp > LOGOUT_MILI_TIME) { startActivity(new Intent(this, InitActivity.class)); finish(); } } @Override protected void onPause() { super.onPause(); // guardamos el tiempo en el que salio de la actividad lastTimeStamp = SystemClock.elapsedRealtime(); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: if (getParent() != null) { NavUtils.navigateUpFromSameTask(this); } else { Intent i = new Intent(getApplicationContext(), LoginActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(i); finish(); } return true; case R.id.action_settings: Intent i = new Intent(getApplicationContext(), ConfigActivity.class); i.putExtra(DirectSIDING.EXTRA_WHICH_ACTIVITY, getString(R.string.WebActivity)); startActivity(i); return true; default: return super.onOptionsItemSelected(item); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getSupportMenuInflater().inflate(R.menu.web, menu); return true; } @Override public void onBackPressed() { if (webView.canGoBack()) webView.goBack(); else super.onBackPressed(); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); ((DirectSIDING) getApplication()).detach(this); } @Override public void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); ((DirectSIDING) getApplication()).attach(this); } private class DirectSidingWebViewClient extends WebViewClient { /** * API 8 PARA ARRIBA */ @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { handler.proceed(); } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); getSherlock().setProgressBarIndeterminateVisibility(true); View v = findViewById(R.id.progressBar_webView); v.clearAnimation(); v.setVisibility(View.VISIBLE); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); getSherlock().setProgressBarIndeterminateVisibility(false); Animation animation = AnimationUtils.loadAnimation((Activity) view.getContext(), R.anim.progressbar_alpha_anim); animation.setAnimationListener(new AnimationListener() { @Override public void onAnimationEnd(Animation animation) { View v = findViewById(R.id.progressBar_webView); v.setVisibility(View.INVISIBLE); } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationStart(Animation animation) { } }); animation.reset(); View v = findViewById(R.id.progressBar_webView); if (v != null) { v.clearAnimation(); v.startAnimation(animation); } } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.endsWith("logout.phtml")) { // si pone salir en el SIDING, volvemos a la LoginActivity if (getParent() != null) { NavUtils.navigateUpFromSameTask((Activity) view.getContext()); } else { Intent i = new Intent(getApplicationContext(), LoginActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(i); finish(); } return true; } else if (url.equals("http://www.ing.puc.cl/")) { // si entra a esa pagina, es porque fallo el login (datos incorrectos) Toast.makeText(getApplicationContext(), R.string.LoginFailed, Toast.LENGTH_SHORT).show(); Intent i = new Intent(getApplicationContext(), LoginActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); i.putExtra(LoginActivity.EXTRA_LOGINFAILED, true); startActivity(i); finish(); return true; } else if (!url.startsWith("https://intrawww.ing.puc.cl/siding")) { // si abre un link fuera del dominio del SIDING, lo abro con el browser Uri uri = Uri.parse(url); Intent intent = new Intent(Intent.ACTION_VIEW, uri); startActivity(intent); return true; } return false; } } /** * Clase que se encarga de descargar el archivo. El proceso devuelve un String[] de tres elementos. * El primer elemento es el tipo de archivo, el segunda es el path en donde se descargo el archivo y el tercero la cantidad descargada. * @author Lukas Zorich * */ private class DownloadFile extends AsyncTask<String, String, String[]> { private int _notifyId; private int icono; private long lastMilli; private String mFileName; private static final int DOWNLOAD_ANIMATION_UPDATE = 500; private static final String ERROR_FILENOTFOUNDEXCEPTION = "FileNotFound"; private static final String ERROR_IOEXCEPTION = "IOException"; private static final String ERROR = "Error"; public DownloadFile(int notifyId, String filename) { this._notifyId = notifyId; icono = 0; mFileName = filename; } @Override protected void onPreExecute() { mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mBuilder = new NotificationCompat.Builder(WebActivity.this); mBuilder.setContentTitle("Descargando archivo ...").setContentText(mFileName + " - 0.0 Mb") .setSmallIcon(downloadAnimationIcons[0]).setProgress(0, 0, true); Intent notificationIntent = new Intent(); //notificationIntent.setDataAndType(Uri.fromFile(file), urlConnection.getContentType()); PendingIntent pendingIntent = PendingIntent.getActivity(WebActivity.this, 0, notificationIntent, 0); mBuilder.setContentIntent(pendingIntent); mNotifyManager.notify(_notifyId, mBuilder.build()); lastMilli = SystemClock.elapsedRealtime(); } @SuppressLint("NewApi") @Override protected String[] doInBackground(String... params) { try { URL url = new URL(params[0]); HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); setSSLFactory(urlConnection); urlConnection.setRequestMethod("GET"); urlConnection.setDoOutput(true); urlConnection.addRequestProperty("Cookie", LoginOpActivity.cookie.getName() + "=" + LoginOpActivity.cookie.getValue()); urlConnection.connect(); String aux = urlConnection.getHeaderField("Content-Disposition").split("; ")[1]; String filename = aux.substring("filename=\"".length(), aux.length() - 1); File file = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) { file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), filename); } else { file = new File(Environment.getExternalStorageDirectory() + "Download/", filename); } //file.mkdirs(); //nos aseguramos que el directorio existe /*// hacemos la notificacion mBuilder.setContentText(filename + " - 0.0 Mb"); Intent notificationIntent = new Intent(); //notificationIntent.setDataAndType(Uri.fromFile(file), urlConnection.getContentType()); PendingIntent pendingIntent = PendingIntent.getActivity(WebActivity.this, 0, notificationIntent, 0); mBuilder.setContentIntent(pendingIntent); mNotifyManager.notify(_notifyId, mBuilder.build());*/ FileOutputStream fileOutput = new FileOutputStream(file); InputStream inputStream = urlConnection.getInputStream(); int downloadedSize = 0; byte[] buffer = new byte[1024]; int bufferLength = 0; while ((bufferLength = inputStream.read(buffer)) > 0) { fileOutput.write(buffer, 0, bufferLength); downloadedSize += bufferLength; // actualizamos el tamao descargado en la notificacion y actualizamos el icono con la animacin if (SystemClock.elapsedRealtime() - lastMilli >= DOWNLOAD_ANIMATION_UPDATE) { mBuilder.setContentText( filename + " - " + String.format("%.1f", downloadedSize / (1000.0 * 1000)) + " Mb") .setSmallIcon(downloadAnimationIcons[(++icono) % downloadAnimationIcons.length]); mNotifyManager.notify(_notifyId, mBuilder.build()); lastMilli = SystemClock.elapsedRealtime(); } } fileOutput.close(); return new String[] { urlConnection.getContentType(), file.getAbsolutePath(), String.format("%.1f", downloadedSize / (1000.0 * 1000)) }; } catch (FileNotFoundException e) { return new String[] { ERROR_FILENOTFOUNDEXCEPTION }; } catch (MalformedURLException e) { return new String[] { ERROR_IOEXCEPTION }; } catch (IOException e) { return new String[] { ERROR_IOEXCEPTION }; } catch (Exception e) { return new String[] { ERROR }; } } @Override protected void onPostExecute(String[] result) { if (result.length > 1) { File file = new File(result[1]); if (file.exists()) { mBuilder.setContentTitle(file.getName()) .setContentText("Descarga finalizada - " + result[2] + " Mb") .setSmallIcon(downloadAnimationIcons[0]).setAutoCancel(true).setProgress(0, 0, false); Intent notificationIntent = new Intent(Intent.ACTION_VIEW); notificationIntent.setDataAndType(Uri.fromFile(file), result[0]); PendingIntent pendingIntent = PendingIntent.getActivity(WebActivity.this, 0, notificationIntent, 0); mBuilder.setContentIntent(pendingIntent); mNotifyManager.notify(_notifyId, mBuilder.build()); Toast.makeText(WebActivity.this, "Descarga finalizada", Toast.LENGTH_SHORT).show(); } } else { if (result[0] == ERROR_FILENOTFOUNDEXCEPTION) { Toast.makeText(getApplicationContext(), R.string.FileNotFound, Toast.LENGTH_SHORT).show(); mNotifyManager.cancel(_notifyId); } else if (result[0] == ERROR_IOEXCEPTION) { mBuilder.setContentTitle("ERROR").setContentText("No se pudo descargar el archivo") .setSmallIcon(downloadAnimationIcons[0]) .setContentIntent(PendingIntent.getActivity(WebActivity.this, 0, new Intent(), 0)) .setAutoCancel(true).setProgress(0, 0, false); mNotifyManager.notify(_notifyId, mBuilder.build()); Toast.makeText(getApplicationContext(), R.string.ErrorConexion, Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getApplicationContext(), "Hubo un error", Toast.LENGTH_SHORT).show(); } } } private void setSSLFactory(HttpsURLConnection connection) { try { KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); MySSLSocketFactory sf = new MySSLSocketFactory(trustStore); sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); connection.setSSLSocketFactory(sf.getDefaultSocketFactory()); } catch (Exception e) { } } } }