Java tutorial
/******************************************************************************* * Copyright (c) 2014 Antonio Isaac Roldn Pea. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html * * Contributors: * Antonio Isaac Roldn Pea - initial API and implementation ******************************************************************************/ package es.uja.photofirma.android; import java.io.File; import java.io.IOException; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.mime.MultipartEntity; import org.apache.http.entity.mime.content.ContentBody; import org.apache.http.entity.mime.content.FileBody; import org.apache.http.entity.mime.content.StringBody; import org.apache.http.util.EntityUtils; import android.location.Location; import android.location.LocationManager; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.telephony.TelephonyManager; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; /** * Controla la actividad y navegacin durante el funcionamiento por CameraActivity: * Contiene las operaciones bsicas para la captura, generacin de firma, comprobacin y subida al servidor * de los archivos involucrados * @author Antonio Isaac Roldn Pea * */ public class CameraActivity extends Activity { //Parmetros de referencia a los archivos involucrados en el proceso private String photoLocation = null; private String signedFileLocation = null; PhotoMaker PhotoCapture; //Nombre del directorio oficial de la aplicacin public static final String APP_FOLDER = "/Photo@Firma/"; public static final int REQUEST_IMAGE_CAPTURE = 1; //Conjunto de codigos para la coordinacion con @firma public static final int APP_FIRMA_REQUEST_CODE = 8; // codigo de llamada a @firma public static final int RESULT_ERROR = 0X00000010; // codigo de operacion con @firma fallida //Intent Filter @firma ACTION *.OPEN, accin de apertura de @firma public static final String APP_FIRMA_OPEN_ACTION = "es.gob.afirma.android.OPEN"; // accion de apertura de @firma //Parametros de entrada a @firma public static final String APP_FIRMA_EXTRA_FILE_PATH = "EXTRA_FILE_PATH"; //Direccion de conexin para la subida de contenido private static String URL_CONTENT_UPLOAD = ""; //=AppConfigurationParams.URL_CONTENT_UPLOAD; //Registo de eventos private Logger logger = new Logger(); //Elementos visuales de informacion private LinearLayout lyerr, lysuc, lyinf, lycan, lyupl, lyudone, lyuerr; private ImageView lycpt; private TextView errorText; //Informacion de usuario private String userName = null; private int userId = -1; private String userEmail = null; private String imeiNumber = null; private TelephonyManager telephonyManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.camera_activity); logger.appendLog(100, "login usuario satisfactorio"); //Definicin de elementos visuales involucrados lycpt = (ImageView) findViewById(R.id.cameraActivityCameraPhotoTap); lyerr = (LinearLayout) findViewById(R.id.cameraActivityErrorHeader); lysuc = (LinearLayout) findViewById(R.id.cameraActivitySuccessHeaderTextView); lycan = (LinearLayout) findViewById(R.id.cameraActivityCancelHeader); lyinf = (LinearLayout) findViewById(R.id.cameraActivityInfoHeader); lyupl = (LinearLayout) findViewById(R.id.cameraActivityUploadingHeader); lyudone = (LinearLayout) findViewById(R.id.cameraActivitySuccesUploadHeader); lyuerr = (LinearLayout) findViewById(R.id.cameraActivityErrorUploadHeader); errorText = (TextView) findViewById(R.id.cameraActivityErrorTextView); //gestor de servicios de telefonia, para la obtencin del IMEI del terminal telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); if (telephonyManager == null) { imeiNumber = getString(R.string.no_imei_available); } else { imeiNumber = telephonyManager.getDeviceId(); } //Deteccin de los parametros necesarios tras un login exitoso if (getIntent().hasExtra("userName") && getIntent().hasExtra("userId") && getIntent().hasExtra("userEmail")) { userName = getIntent().getExtras().getString("userName"); userId = getIntent().getExtras().getInt("userId"); userEmail = getIntent().getExtras().getString("userEmail"); } else { Toast.makeText(getApplicationContext(), getString(R.string.no_user_data_found), Toast.LENGTH_LONG) .show(); } final AlertDialog alertDialog = new AlertDialog.Builder(this).create(); alertDialog.setTitle("Aviso de privacidad"); alertDialog.setMessage(getString(R.string.privacy_alert)); alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { alertDialog.dismiss(); } }); alertDialog.show(); SharedPreferences prefs = getSharedPreferences("prefsfile", Context.MODE_PRIVATE); String myPrefServerIp = prefs.getString("prefIpAddress", "10.0.3.2"); URL_CONTENT_UPLOAD = "https://" + myPrefServerIp + "/photo@firmaServices/content_upload.php"; } /** * Muestra la cabecera de error en la subida de datos */ public void showUpErrorHeader() { hideAllHeaders(); lyuerr.setVisibility(LinearLayout.VISIBLE); lycpt.setImageResource(R.drawable.camera512r); } /** * Muestra la cabecera de exito en la subida de datos */ public void showUpCompletedHeader() { hideAllHeaders(); lyudone.setVisibility(LinearLayout.VISIBLE); } /** * Muestra la cabecera de subida de datos en progreso */ public void showUploadingHeader() { hideAllHeaders(); lyupl.setVisibility(LinearLayout.VISIBLE); } /** * Muestra la cabecera de exito en la creacin de una firma */ public void showSuccessHeader() { hideAllHeaders(); lysuc.setVisibility(LinearLayout.VISIBLE); lycan.setVisibility(LinearLayout.VISIBLE); lycpt.setImageResource(R.drawable.camera512g); } /** * Muestra la cabecera de informacin */ public void showInfoHeader() { hideAllHeaders(); lyinf.setVisibility(LinearLayout.VISIBLE); lycpt.setImageResource(R.drawable.camera512b); } /** * Muestra la cabecera de error o cancelacin del proceso */ public void showErrorHeader() { hideAllHeaders(); lyerr.setVisibility(LinearLayout.VISIBLE); lycpt.setImageResource(R.drawable.camera512r); errorText.setText(getString(R.string.camera_activity_error_header_text_view)); } /** * Oculta todas las cabeceras visibles */ public void hideAllHeaders() { lyuerr.setVisibility(LinearLayout.INVISIBLE); lyudone.setVisibility(LinearLayout.INVISIBLE); lyupl.setVisibility(LinearLayout.INVISIBLE); lyerr.setVisibility(LinearLayout.INVISIBLE); lysuc.setVisibility(LinearLayout.INVISIBLE); lycan.setVisibility(LinearLayout.INVISIBLE); lyinf.setVisibility(LinearLayout.INVISIBLE); } /** * Se ejecuta al pulsar sobre el boton para abrir la captura de fotos, inicia la captura y almacena la fotografa realizada */ public void onTakeAPhoto(View view) { logger.appendLog(300, "el usuario abre la aplicacion de fotos"); //Se crea nueva instancia de la clase PhotoMaker() para automatizar el proceso de trabajo con fotografas PhotoCapture = new PhotoMaker(); File imagen = PhotoCapture.savePhoto(); photoLocation = imagen.getAbsolutePath(); //Se redirige al usuario a la app de captura de fotografas Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); takePictureIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(imagen)); if (takePictureIntent.resolveActivity(getPackageManager()) != null) { // Toast.makeText(getApplicationContext(), getString(R.string.privacy_alert), Toast.LENGTH_LONG).show(); startActivityForResult(takePictureIntent, CameraActivity.REQUEST_IMAGE_CAPTURE); } } /** * Controla los accesos y retornos a las aplicaciones de caputura de fotografas y '@firma', se establece * para cada caso tanto la situacion de exito como la de fracaso. */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // Vuelta de @firma, el resultCode indica exito o fracaso, en cada caso se toman unas medidas diferentes if (requestCode == CameraActivity.APP_FIRMA_REQUEST_CODE && resultCode == CameraActivity.RESULT_ERROR) { logger.appendLog(402, "el usuario deniega el uso del certificado"); showErrorHeader(); } //Vuelta de @firma, la firma fue realizada con exito, se almacena la ruta al archivo if (requestCode == CameraActivity.APP_FIRMA_REQUEST_CODE && resultCode == RESULT_OK) { logger.appendLog(200, "@firma realiz la firma adecuadamente"); signedFileLocation = data.getExtras().getString("signedfilelocation"); showSuccessHeader(); } //Si la captura de la fotografa tuvo exito if (requestCode == CameraActivity.REQUEST_IMAGE_CAPTURE & resultCode == RESULT_OK) { logger.appendLog(101, "el usuario captura foto"); //Se obtienen los datos del servicio de localizacin geografica LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); // Aade los geoTags a la foto realizada anteriormente if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) && location != null) { PhotoCapture.addExifData(photoLocation, location); logger.appendLog(102, "el usuario aade exif"); logger.appendLog(103, "gps data: " + location); } logger.appendLog(104, "buscando @firma"); //Se comprueba si est la app @firma Intent intent = getPackageManager().getLaunchIntentForPackage("es.gob.afirma"); if (intent == null) { //Si no se encuentra instalada se notifica al usuario logger.appendLog(400, "@firma no instalada"); showErrorHeader(); errorText.setText(getString(R.string.camera_activity_no_afirma_present)); } else { //Si se encuentra, entonces se abre para dar comienzo al proceso de firma logger.appendLog(201, "abriendo @firma"); Intent i = new Intent(APP_FIRMA_OPEN_ACTION); i.putExtra(CameraActivity.APP_FIRMA_EXTRA_FILE_PATH, photoLocation); startActivityForResult(i, APP_FIRMA_REQUEST_CODE); } } //Si la captura de fotos fue cancelada if (requestCode == CameraActivity.REQUEST_IMAGE_CAPTURE && resultCode == CameraActivity.RESULT_CANCELED) { showInfoHeader(); logger.appendLog(105, "cierra la app de photo sin captura"); } //Si la captura de fotos fue cancelada if (requestCode == CameraActivity.REQUEST_IMAGE_CAPTURE && resultCode == CameraActivity.RESULT_ERROR) { showInfoHeader(); logger.appendLog(403, "Se produjo un error en la app de Cmara"); } } /** * Se ejecuta cuando el usario confirma la fotografia realizada y permite el uso del certificado seleccionado para generar * la firma del archivo. * */ public void onSubmitPhoto(View view) { logger.appendLog(302, "el usuario acepta la captura y pretende enviar"); //Se verifica que exiten todos los datos necesarios antes de comenzar el proceso de subida if (new File(photoLocation).exists() && new File(signedFileLocation).exists() && userName != null && userId != -1 && userEmail != null && logger != null && imeiNumber != null) { logger.appendLog(106, "enviando archvios al servidor"); showUploadingHeader(); new ContentUpload().execute(URL_CONTENT_UPLOAD, photoLocation, signedFileLocation, userName, String.valueOf(userId), userEmail, String.valueOf(logger.getJson()), imeiNumber); } else { logger.appendLog(401, "faltan datos en el proceso de subida"); showErrorHeader(); errorText.setText(getString(R.string.no_files_found)); } } /** * Realiza la operacin de subida de datos al servidor, negocia la conexin http o https y adjunta * los datos generados durante todo el proceso * */ private class ContentUpload extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... data) { String res = null; try { HttpClient httpclient = new DoConnection().getNewHttpClient(); HttpPost httppost = new HttpPost(data[0]); //Mensaje multiparte, permite aadir datos de diferente naturaleza en un mismo mensaje MultipartEntity mpEntity = new MultipartEntity(); File foto = new File(data[1]); File firma = new File(data[2]); // ContentBody fotoContent= new FileBody(foto,"image/jpg"); ContentBody fotoContent = new FileBody(foto); ContentBody firmaContent = new FileBody(firma); // ContentBody firmaContent= new FileBody(firma, "signedfile/csig"); //Se adjuntan los datos generados mpEntity.addPart("imagen", fotoContent); mpEntity.addPart("firma", firmaContent); mpEntity.addPart("user_name", new StringBody(data[3])); mpEntity.addPart("user_id", new StringBody(data[4])); mpEntity.addPart("user_email", new StringBody(data[5])); mpEntity.addPart("events", new StringBody(data[6])); mpEntity.addPart("imei", new StringBody(data[7])); httppost.setEntity(mpEntity); HttpResponse response = httpclient.execute(httppost); res = EntityUtils.toString(response.getEntity()); } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return res; } @Override protected void onPostExecute(String result) { //se verifica que haya una respuesta vlida if (result == null) { logger.appendLog(500, "sin respuesta del servidor"); showUpErrorHeader(); } else { //Se procesa la respuesta del servidor y se extraen datos logger.appendLog(202, "respuesta del servidor recibida"); JsonParse jresult = new JsonParse(); jresult.getResponseFromServer(result); if (jresult.getStatus() == true) { //Si la operacion ha sido correcta se notifica al usuario del exito del proceso de subida logger.appendLog(203, "subida completada satisfactoriamente"); showUpCompletedHeader(); File f = new File(photoLocation); String photoName = f.getName().toString(); String logUrl = Environment.getExternalStorageDirectory() + CameraActivity.APP_FOLDER + photoName + ".log"; // String g=String.valueOf(logger.getJson()); // Log.d("log", logger.getJson().toString()); // Log.d("json", jresult.getDescription()); logger.logWrite(logUrl); logger.logStop(); } else if (jresult.getStatus() == false) { //Si la operacin no es vlida, se ha producido un error y se muestra la informacin al usuario logger.appendLog(501, "se produjo un error en la subida de datos"); showUpErrorHeader(); } } } } /** * Se ejecuta al presionar el boton de cancelar, permite vaciar las variables de los elementos a subir, y eliminar * los archivos relacionados * */ public void onCancel(View view) { logger.appendLog(303, "el usuario cancela el proceso"); File p = new File(photoLocation); File f = new File(signedFileLocation); p.delete(); f.delete(); photoLocation = null; signedFileLocation = null; Toast.makeText(getApplicationContext(), getString(R.string.camera_activity_on_cancel_text), Toast.LENGTH_LONG).show(); showInfoHeader(); } /** * El botn back se configura para cerrar sesin */ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { Intent mainActivity = new Intent(CameraActivity.this, MainActivity.class); startActivity(mainActivity); overridePendingTransition(R.anim.right_in, R.anim.right_out); super.finish(); Toast.makeText(getApplicationContext(), getString(R.string.close_session_message), Toast.LENGTH_LONG) .show(); } return false;// super.onKeyDown(keyCode, event); } }