CARRERA INFORMATICA INDUSTRIAL ESCUELA INDUSTRIAL SUPERIOR “PEDRO DOMINGO MURILLO” PROGRAMACION DE SISTEMAS MOVILES (PSM-400) Integrantes Área Título del proyecto Apellido Y Nombre(s): Jorge Luis Chambilla Conde Apellido Y Nombre(s): CID: 7092957 CID: PSM-400(Programacion de sistemas Moviles) Registros de usuario y control Introducción Primeramente este proyecto se basara en hacer registros de usuario tomando datos,foto y la fecha en la cual se registro en tiempo real y guardarlo en una lista para ser controlado Procedimiento Primeramente se nesecitara de las herramientas las cuales son: Android studio versión 4.1.1 luego paginas externas que serian canva.com para la realización de fondos,photoshop para crear iconos que usara Android y fundamentos de la programación en java para crear el proyecto. El modelo a presentar será el siguiente: listado Descripción del proyecto Revision Guardado Código Con el Main se pondría el código mas que todo consta en el llamado de la lista del guardado de los registros. package apps.IrvinTheSenpai.proyectsqlite; import import import import import androidx.annotation.NonNull; androidx.appcompat.app.ActionBar; androidx.appcompat.app.AppCompatActivity; androidx.appcompat.widget.SearchView; androidx.recyclerview.widget.RecyclerView; import import import import import android.content.Intent; android.os.Bundle; android.view.Menu; android.view.MenuItem; android.view.View; import com.google.android.material.floatingactionbutton.FloatingActionButton; public class MainActivity extends AppCompatActivity { //Views private FloatingActionButton addRecordBtn; //RecyclerView private RecyclerView recordsRv; //DB Helper private MyDbHelper dbHelper; //Action Bar ActionBar actionBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //Inicializar Vista addRecordBtn = findViewById(R.id.addRecordBtn); recordsRv = findViewById(R.id.recordsRv); //Inicializamos db helper Clase dbHelper = new MyDbHelper(this); //Inicializacion ActionBar actionBar = getSupportActionBar(); actionBar.setTitle("Registros"); // Cargando Registros loadRecords(); // Click para Iniciar a añadir y grabar en la activity addRecordBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //Iniciar la Activity Intent intent = new Intent(MainActivity.this, AgregarRegistroActivity.class); intent.putExtra("isEditMode", false);//desea establecer nuevos datos, set false. startActivity(intent); } }); } private void loadRecords(){ AdapterRecord adapterRecord = new AdapterRecord(MainActivity.this, dbHelper.getAllRecords(Constants.C_ADDED_TIMESTAMP + " DESC")); recordsRv.setAdapter(adapterRecord); //Establecer el numero de Registros actionBar.setSubtitle("Total: "+dbHelper.getRecordsCount()); } private void searchRecords(String query){ AdapterRecord adapterRecord = new AdapterRecord(MainActivity.this, dbHelper.searchRecords(query)); recordsRv.setAdapter(adapterRecord); } @Override protected void onResume(){ super.onResume(); loadRecords();// Refresca o actualiza la lista de registros } @Override public boolean onCreateOptionsMenu(Menu menu){ //inflate menu getMenuInflater().inflate(R.menu.menu_main, menu); //searchView MenuItem item = menu.findItem(R.id.action_search); final SearchView searchView = (SearchView)item.getActionView(); searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { // buscar cuando se hace clic en el botón de búsqueda en el teclado searchRecords(query); return true; } @Override public boolean onQueryTextChange(String newText) { // busca mientras escribes searchRecords(newText); return true; } }); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(@NonNull MenuItem item){ //maneja elementos del menu return super.onOptionsItemSelected(item); } } Para dar el modelo y llamado de layouts la clase seria ModelRecord package apps.IrvinTheSenpai.proyectsqlite; /* Modelo de la clase para RecyclerView*/ public class ModelRecord { //Variables String id, name, image, bio, phone, email, dob, addedTime, updatedTime; //Constructor public ModelRecord(String id, String name, String image, String bio, String phone, String email, String dob, String addedTime, String updatedTime) { this.id = id; this.name = name; this.image = image; this.bio = bio; this.phone = phone; this.email = email; this.dob = dob; this.addedTime = addedTime; this.updatedTime = updatedTime; } //Getter y Setter public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getImage() { return image; } public void setImage(String image) { this.image = image; } public String getBio() { return bio; } public void setBio(String bio) { this.bio = bio; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getDob() { return dob; } public void setDob(String dob) { this.dob = dob; } public String getAddedTime() { return addedTime; } public void setAddedTime(String addedTime) { this.addedTime = addedTime; } public String getUpdatedTime() { return updatedTime; } public void setUpdatedTime(String updatedTime) { this.updatedTime = updatedTime; } } clase details para el control del toolbar package apps.IrvinTheSenpai.proyectsqlite; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import import import import import import import android.content.Intent; android.database.Cursor; android.database.sqlite.SQLiteDatabase; android.net.Uri; android.os.Bundle; android.text.format.DateFormat; android.widget.TextView; import java.util.Calendar; import java.util.Locale; import de.hdodenhof.circleimageview.CircleImageView; public class DetalleRegistroActivity extends AppCompatActivity { //vistas private CircleImageView profileIv; private TextView bioTv, nameTv, phoneTv, emailTv, dobTv, addedTimeTv, updatedTimeTv; //ActionBar private ActionBar actionBar; // private String recordID; //BDHelper private MyDbHelper dbHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_detalle_registro); //setting up actionbar with title and back button actionBar = getSupportActionBar(); actionBar.setTitle("Detalle del Registro"); actionBar.setDisplayShowHomeEnabled(true); actionBar.setDisplayHomeAsUpEnabled(true); //obtener la identificación de registro del adaptador mediante la intención Intent intent = getIntent(); recordID = intent.getStringExtra("RECORD_ID"); //Inicializacion BD Helper Clase dbHelper = new MyDbHelper(this); //Inicializamos las vistas profileIv = findViewById(R.id.profileIv); bioTv = findViewById(R.id.bioTv); nameTv = findViewById(R.id.nameTv); phoneTv = findViewById(R.id.phoneTv); emailTv = findViewById(R.id.emailTv); dobTv = findViewById(R.id.dobTv); addedTimeTv = findViewById(R.id.addedTimeTv); updatedTimeTv = findViewById(R.id.updateTimeTv); showRecordDetails(); } private void showRecordDetails() { //obtener detalles de registro //consulta para seleccionar el registro basado en la identificación del registro String selectQuery = " SELECT * FROM " + Constants.TABLE_NAME + " WHERE " + Constants.C_ID +" =\""+ recordID+"\""; SQLiteDatabase db = dbHelper.getWritableDatabase(); Cursor cursor = db.rawQuery(selectQuery, null); // mantener comprobando toda la base de datos para ese registro if (cursor.moveToFirst()){ do { //Obtenner datos String id = ""+ cursor.getInt(cursor.getColumnIndex(Constants.C_ID)); String name = ""+ cursor.getString(cursor.getColumnIndex(Constants.C_NAME)); String image = ""+ cursor.getString(cursor.getColumnIndex(Constants.C_IMAGE)); String bio = ""+ cursor.getString(cursor.getColumnIndex(Constants.C_BIO)); String phone = ""+ cursor.getString(cursor.getColumnIndex(Constants.C_PHONE)); String email = ""+ cursor.getString(cursor.getColumnIndex(Constants.C_EMAIL)); String dob = ""+ cursor.getString(cursor.getColumnIndex(Constants.C_DOB)); String timestampAdded = ""+ cursor.getString(cursor.getColumnIndex(Constants.C_ADDED_TIMESTAMP)); String timestampUpdated = ""+ cursor.getString(cursor.getColumnIndex(Constants.C_UPDATED_TIMESTAMP)); //Convertir marca de tiempo a dd/mm/yyyy hh:mm por ejemplo 10/04/2020 08:22 AM Calendar calendar1 = Calendar.getInstance(Locale.getDefault()); calendar1.setTimeInMillis(Long.parseLong(timestampAdded)); String timeAdded = ""+ DateFormat.format("dd/MM/yyyy hh:mm:aa", calendar1); Calendar calendar2 = Calendar.getInstance(Locale.getDefault()); calendar2.setTimeInMillis(Long.parseLong(timestampUpdated)); String timeupdated = ""+ DateFormat.format("dd/MM/yyyy hh:mm:aa", calendar2); //Establecer datos nameTv.setText(name); bioTv.setText(bio); phoneTv.setText(phone); emailTv.setText(email); dobTv.setText(dob); addedTimeTv.setText(timeAdded); updatedTimeTv.setText(timeupdated); // si el usuario no adjunta la imagen, imageUri será nulo, por lo tanto, // configure una imagen predeterminada en ese caso if (image.equals("null")){ // no hay imagen en el registro, establecer predeterminado profileIv.setImageResource(R.drawable.ic_person_black); } else { // tener imagen en el registro profileIv.setImageURI(Uri.parse(image)); } }while(cursor.moveToNext()); } db.close(); } @Override public boolean onSupportNavigateUp(){ onBackPressed();//ir a la actividad anterior return super.onSupportNavigateUp(); } } Clase para agregar registro seria package apps.IrvinTheSenpai.proyectsqlite; import import import import import import import androidx.annotation.NonNull; androidx.annotation.Nullable; androidx.appcompat.app.ActionBar; androidx.appcompat.app.AlertDialog; androidx.appcompat.app.AppCompatActivity; androidx.core.app.ActivityCompat; androidx.core.content.ContextCompat; import import import import import import import import import import import import android.Manifest; android.content.ContentValues; android.content.DialogInterface; android.content.Intent; android.content.pm.PackageManager; android.net.Uri; android.os.Bundle; android.provider.MediaStore; android.view.View; android.widget.Button; android.widget.EditText; android.widget.Toast; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.theartofdev.edmodo.cropper.CropImage; import com.theartofdev.edmodo.cropper.CropImageView; import de.hdodenhof.circleimageview.CircleImageView; public class AgregarRegistroActivity extends AppCompatActivity { //View private CircleImageView profileIv; private EditText nameEt,phoneEt,emailEt,dobEt,bioEt; private FloatingActionButton saveBtn; //Actionbar private ActionBar actionBar; //Permiso de la clase Constants private static final int CAMERA_REQUEST_CODE = 100; private static final int STORAGE_REQUEST_CODE = 101; //selección de imagen Constants private static final int IMAGE_PICK_CAMERA_CODE = 102; private static final int IMAGE_PICK_GALLERY_CODE = 103; // matrices de permisos private String[] cameraPermissions; // cámara y almacenamiento private String [] storagePermissions;// solo almacenamiento // variables (constain datos para guardar) private Uri imageUri; private String id, name, phone, email, dob, bio, addedTime, updatedTime; private boolean isEditMode = false; //db helper private MyDbHelper dbHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_agregar_registro); //Inicializacion actionBar = getSupportActionBar(); //Titulo actionBar.setTitle("Agregar Registro"); //Boton Negro actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setDisplayShowHomeEnabled(true); profileIv = findViewById(R.id.profileIv); nameEt = findViewById(R.id.nameEt); phoneEt = findViewById(R.id.phoneEt); emailEt = findViewById(R.id.emailEt); dobEt = findViewById(R.id.dobEt); bioEt = findViewById(R.id.bioEt); saveBtn = findViewById(R.id.saveBtn); //obtener los datos de la intencion Intent intent = getIntent(); isEditMode = intent.getBooleanExtra("isEditMode", false); //establer la vista de los datos if (isEditMode) { //Actualizar datos actionBar.setTitle("Actualizar Registro"); id = intent.getStringExtra("ID"); name = intent.getStringExtra("NAME"); phone = intent.getStringExtra("PHONE"); email = intent.getStringExtra("EMAIL"); dob = intent.getStringExtra("DOB"); bio = intent.getStringExtra("BIO"); imageUri = Uri.parse(intent.getStringExtra("IMAGE")); addedTime = intent.getStringExtra("ADDEDTIME"); updatedTime = intent.getStringExtra("UPDATEDTIME"); //set View data nameEt.setText(name); phoneEt.setText(phone); emailEt.setText(email); dobEt.setText(dob); bioEt.setText(bio); //sino se selecciona una imagen al agregr datos; el valor de la imagen ser "NULL" if (imageUri.toString().equals("null")) { //sino ahi imagen , set default profileIv.setImageResource(R.drawable.ic_person_black); } else { profileIv.setImageURI(imageUri); } } else { //agregar datos actionBar.setTitle("Agregar Registro"); } //Inicializar BD Helper dbHelper = new MyDbHelper(this); //Inicializamos Permisos arrays cameraPermissions = new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}; storagePermissions = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}; profileIv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // muestra el cuadro de diálogo de selección de imagen imagePickDialog(); } }); saveBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { inputData(); } }); } private void inputData(){ //get data name = ""+nameEt.getText().toString().trim(); phone = ""+phoneEt.getText().toString().trim(); email = ""+emailEt.getText().toString().trim(); dob = ""+dobEt.getText().toString().trim(); bio = ""+bioEt.getText().toString().trim(); if (isEditMode){ //actualizar datos String timestamp = ""+System.currentTimeMillis(); dbHelper.updateRecord( ""+id, ""+name, ""+imageUri, ""+bio, ""+phone, ""+email, ""+dob, ""+addedTime,//este dato no cambia fecha registro ""+timestamp//Fecha de actualizacion cambia ); Toast.makeText(this, "Actualizando... ", Toast.LENGTH_SHORT).show(); } else{ //new datos //guarda en la base de datos String timestamp = ""+System.currentTimeMillis(); long id = dbHelper.insertRecord( ""+name, ""+imageUri, ""+bio, ""+phone, ""+email, ""+dob, ""+timestamp, ""+timestamp ); Toast.makeText(this, "Registro agregado contra ID: "+id, Toast.LENGTH_SHORT).show(); } } private void imagePickDialog(){ // opciones para mostrar en el diálogo String[] options = {"Camara", "Galeria"}; //dialogo AlertDialog.Builder builder = new AlertDialog.Builder(this); //Titulo builder.setTitle("Seleccionar imagen"); // establecer elementos / opciones builder.setItems(options, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // manejar clicks if (which==0){ //click en camara if (!checkCameraPermission()){ requestCameraPermission(); } else{ // permiso ya otorgado PickFromCamera(); } } else if (which==1){ if (!checkStoragePermission()){ requestStoragePermission(); } else{ // permiso ya otorgado PickFromGallery(); } } } }); // Crear / mostrar diálogo builder.create().show(); } private void PickFromGallery() { // intento de elegir la imagen de la galería, la imagen se devolverá en el método onActivityResult Intent galleryIntent = new Intent(Intent.ACTION_PICK); galleryIntent.setType("image/*"); startActivityForResult(galleryIntent, IMAGE_PICK_GALLERY_CODE); } private void PickFromCamera() { ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.TITLE, "Titulo de la Imagen"); values.put(MediaStore.Images.Media.DESCRIPTION, "Descripción de la imagen"); //put image Uri imageUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); // Intento de abrir la cámara para la imagen Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); startActivityForResult(cameraIntent, IMAGE_PICK_CAMERA_CODE); } private boolean checkStoragePermission(){ //comprobar si el permiso de almacenamiento está habilitado o no boolean result = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == (PackageManager.PERMISSION_GRANTED); return result; } private void requestStoragePermission(){ // solicita el permiso de almacenamiento ActivityCompat.requestPermissions(this, storagePermissions, STORAGE_REQUEST_CODE); } private boolean checkCameraPermission(){ // verifica si el permiso de la cámara está habilitado o no boolean result = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == (PackageManager.PERMISSION_GRANTED); boolean result1 = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == (PackageManager.PERMISSION_GRANTED); return result && result1; } private void requestCameraPermission(){ // solicita el permiso de la cámara ActivityCompat.requestPermissions(this, cameraPermissions, CAMERA_REQUEST_CODE); } @Override public boolean onSupportNavigateUp(){ onBackPressed(); //regrese haciendo clic en el botón de barra de acción return super.onSupportNavigateUp(); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); // resultado del permiso permitido / denegado switch (requestCode){ case CAMERA_REQUEST_CODE:{ if (grantResults.length>0){ boolean cameraAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED; boolean storageAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED; if(cameraAccepted && storageAccepted){ // ambos permisos permitidos PickFromCamera(); } else{ Toast.makeText(this, "Se requieren permisos de cámara y almacenamiento", Toast.LENGTH_SHORT).show(); } } } break; case STORAGE_REQUEST_CODE:{ if (grantResults.length>0){ // si se permite devolver verdadero de lo contrario falso boolean storageAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED; if (storageAccepted){ // permiso de almacenamiento permitido PickFromGallery(); } else{ Toast.makeText(this, "Se requiere permiso de almacenamiento", Toast.LENGTH_SHORT).show(); } } } break; } } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { //image picked from camera or gallery will be received hare if (resultCode == RESULT_OK){ //Image is picked if(requestCode == IMAGE_PICK_GALLERY_CODE){ //Picked from gallery //crop image CropImage.activity(data.getData()) .setGuidelines(CropImageView.Guidelines.ON) .setAspectRatio(1, 1) .start(this); } else if(requestCode == IMAGE_PICK_CAMERA_CODE){ //Picked from camera //crop Image CropImage.activity(imageUri) .setGuidelines(CropImageView.Guidelines.ON) .setAspectRatio(1, 1) .start(this); } else if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE){ //Croped image received CropImage.ActivityResult result = CropImage.getActivityResult(data); if (resultCode == RESULT_OK){ Uri resultUri = result.getUri(); imageUri = resultUri; //set Image profileIv.setImageURI(resultUri); } else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE){ //ERROR Exception error = result.getError(); Toast.makeText(this, ""+error, Toast.LENGTH_SHORT).show(); } } } super.onActivityResult(requestCode, resultCode, data); } } EJECUCIONES Agregando registro Registro guardado exitosamente Revisamos el registro Buscando registro CONCLUSIONES Esta sera parte de mi Proyecto para la parte de registros ya que esta aplicacion se ira basando y Armando a la aplicacion Fitnes que tengo planeada con este funcionamiento de agregar registros guardarlos y revisarlos. Observaciones (lo llena el docente) 3/12/2020 Fecha de Entrega Firma Revisado