Problems Deleting Alarm

2

I have a problem with my Alarms, I can add them and modify them, but do not delete them. I create a person with image, name and alarm, at the time of deleting it, only the image and name are deleted, the alarm always remains activated.

To delete the person I do it like this (delete image and name, but NO the alarm)

@Override
public boolean onContextItemSelected(android.view.MenuItem item) {
    AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();

    switch (item.getItemId()) {
        case R.id.menu_contextual_editar_persona:
            editarPersona((int)info.id);
            return true;
        case R.id.menu_contextual_eliminar_persona:
            eliminarPersona((int)info.id);
            recuperarTodasPersonas();
            return true;
        default:
            return super.onContextItemSelected((android.view.MenuItem) item);
    }
}

I leave here my MainActivity complete if any more data is needed:

public class MainActivity extends AppCompatActivity {

    // Objetos.
    private DatabaseHandler baseDatos;
    private ImagenAdapter cursorAdapter;
    private ListView listViewPersonas;


    // Constantes privadas.
    private int CODIGO_RESULT_EDITAR_PERSONA = 0;
    private static final String SAMPLE_DB_NAME = "BDBIRTHDAY_INFO";
    private static final String SAMPLE_TABLE_NAME = "Personas";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listViewPersonas = (ListView) findViewById(R.id.listViewPersonas);
        // Se recuperan todas las personas de la base de datos.
        recuperarTodasPersonas();
        // Asociamos los menús contextuales al listViewPersonas.
        registerForContextMenu(listViewPersonas);
    }
    /**
     * Metodo publico que se sobreescribe. En este metodo crearmos el menu contextual
     * para el ListView de personas.
     */
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo){
        super.onCreateContextMenu(menu, v, menuInfo);
        android.view.MenuInflater inflater = getMenuInflater();
        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
        inflater.inflate(R.menu.opciones_personas, menu);
    }

    /**
     * Metodo publico que se sobreescribe. En este metodo colocamos las acciones de las opciones del menu contextual
     * para el ListView de personas.
     */
    @Override
    public boolean onContextItemSelected(android.view.MenuItem item) {
        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();

        switch (item.getItemId()) {
            case R.id.menu_contextual_editar_persona:
                editarPersona((int)info.id);
                return true;
            case R.id.menu_contextual_eliminar_persona:
                eliminarPersona((int)info.id);
                recuperarTodasPersonas();
                return true;
            default:
                return super.onContextItemSelected((android.view.MenuItem) item);
        }
    }

    @Override
    protected void onStart(){
        super.onStart();
    }

    @Override
    protected void onResume(){
        super.onResume();;
    }

    /**
     * Metodo privado que recupera todos las personas existentes de la base de datos.
     */
    private void recuperarTodasPersonas() {
        try{
            baseDatos = new DatabaseHandler(this);

            // Devuelve todas las personas en el objeto Cursor.
            Cursor cursor = baseDatos.obtenerTodasPersonas();

            String[] from = new String[]{
                    "nombre",
                    "fecha",
                    "zodiaco",
                    "ruta_imagen"
            };

            int[] to = new int[]{
                    R.id.persona_nombre,
                    R.id.persona_fecha,
                    R.id.persona_zodiaco,
                    R.id.foto_gallery,
            };
            cursorAdapter = new ImagenAdapter(this, cursor, from, to);
            listViewPersonas.setAdapter(cursorAdapter);
        }catch(Exception e){
            Log.d("Error", "El mensaje de error es: " + e.getMessage());
        }finally{
            // Se cierra la base de datos.
            baseDatos.cerrar();
        }
    }

    /**
     * Metodo publico que edita una persona.
     * @param p_id
     */
    public void editarPersona(int p_id){
        // Si el p_id es 0, entonces se crea una nueva persona.
        if(p_id == 0){
            // Se dirige a la actividad EditarPersonaActivity.
            Intent actividad_editarPersona = new Intent(MainActivity.this, EditarPersonaActivity.class);
            startActivityForResult(actividad_editarPersona, CODIGO_RESULT_EDITAR_PERSONA);
        }else{
            // Recupera una persona especifica.
            Persona persona;

            try{
                persona = baseDatos.getPersona(p_id);

                // Se dirige a la actividad EditarPersonaActivity.
                Intent actividad_editarPersona = new Intent(this, EditarPersonaActivity.class);

                // Se le coloca parametros para enviar a la actividad EditarPersonaActivity.
                actividad_editarPersona.putExtra("id", p_id);
                actividad_editarPersona.putExtra("nombre", persona.getNombre());
                actividad_editarPersona.putExtra("fecha", persona.getFecha());
                actividad_editarPersona.putExtra("zodiaco", persona.getZodiaco());
                actividad_editarPersona.putExtra("ruta_imagen", persona.getRutaImagen());

                startActivityForResult(actividad_editarPersona, CODIGO_RESULT_EDITAR_PERSONA);
            }catch (Exception e){
                Toast.makeText(getApplicationContext(), "Error al editar", Toast.LENGTH_SHORT).show();
                e.printStackTrace();
            }finally{
                baseDatos.cerrar();
            }
        }
    }

    /**
     * Metodo privado que elimina una persona.
     * @param id_persona
     */
    private void eliminarPersona(int id_persona){
        // Objetos.
        AlertDialog.Builder mensaje_dialogo = new AlertDialog.Builder(this);

        // Variables.
        final int v_id_persona = id_persona;

        mensaje_dialogo.setTitle("Importante");
        mensaje_dialogo.setMessage("¿Está seguro de eliminar esta persona?");
        mensaje_dialogo.setCancelable(false);
        mensaje_dialogo.setPositiveButton("Confirmar", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialogo1, int id) {
                try{
                    baseDatos.eliminaPersona(v_id_persona);

                    recuperarTodasPersonas();
                }catch(Exception e){
                    Toast.makeText(getApplicationContext(), "Error al eliminar!", Toast.LENGTH_SHORT).show();
                    e.printStackTrace();
                }finally{
                    baseDatos.cerrar();
                }
            }
        });
        mensaje_dialogo.setNegativeButton("Cancelar", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialogo1, int id) {
                recuperarTodasPersonas();
            }
        });
        mensaje_dialogo.show();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        recuperarTodasPersonas();
    }
}

EditarPersona (only part of the code)

This is how my Alarm works to activate:

    private void setAlarm(Uri passuri, int notification_id) throws ParseException {

        System.currentTimeMillis();
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm", Locale.getDefault());
        java.util.Calendar cal = java.util.Calendar.getInstance();
        cal.setTime(sdf.parse(editTextFecha.getText().toString()));
        Intent intent = new Intent(getBaseContext(), otrointento.dos.notif.AlarmReceiver.class);
        //los extras
        intent.putExtra("titulo", editTextNombre.getText().toString());
        PendingIntent pendingIntent = PendingIntent.getBroadcast(
                getBaseContext(),
                notification_id,
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT);

        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);

    }


//// luego pulsando mi botón se añade

        butonGuardar.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                if (verificarCampoNombre() && verificarCampoFecha()
                        && verificarCampoZodiaco()) {
                    if (estadoEditarPersona()) {
                        editarPersona();
                    } else {
                        try {
                            notification_id = (int) insertarNuevoPersona();
                            setAlarm(uriAlarm, notification_id);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    }
                    finish();

                }

DataBaseHandler

public class DatabaseHandler extends SQLiteOpenHelper{
    // Ruta por defecto de las bases de datos en el sistema Android.
    private static String RUTA_BASE_DATOS = "/data/data/otrointento.dos/databases/";

    // Nombre de la Base de Datos.
    private static String NOMBRE_BASE_DATOS = "BDBIRTHDAY_INFO";

    // Version de la Base de Datos.
    private static final int VERSION_BASE_DATOS = 1;

    // Objeto Base de Datos.
    private SQLiteDatabase base_datos;

    // Objeto Contexto.
    private Context contexto;

    // Constante privada
    private String SENTENCIA_SQL_CREAR_BASE_DATOS_PERSONAS = "CREATE TABLE if not exists personas (_id INTEGER PRIMARY KEY autoincrement, " +
            "nombre TEXT, fecha TEXT, zodiaco TEXT, ruta_imagen TEXT)";

    /**
     * Constructor
     * Toma referencia hacia el contexto de la aplicación que lo invoca para poder acceder a los 'assets' y
     * 'resources' de la aplicación.
     * Crea un objeto DBOpenHelper que nos permitirá controlar la apertura de la base de datos.
     * @param context
     */
    public DatabaseHandler(Context context) {
        super(context, NOMBRE_BASE_DATOS, null, VERSION_BASE_DATOS);
        this.contexto = context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // Se ejecuta la sentencia SQL de creación de la tabla personas.
        db.execSQL(SENTENCIA_SQL_CREAR_BASE_DATOS_PERSONAS);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Se elimina la versión anterior de la tabla Personas.
        db.execSQL("DROP TABLE IF EXISTS Personas");

        // Se crea la nueva versión de la tabla personas.
        db.execSQL(SENTENCIA_SQL_CREAR_BASE_DATOS_PERSONAS);
    }

    /**
     * Metodo publico para insertar una nueva persona.
     */
    public long insertarPersona(Persona persona){
        ContentValues valores = new ContentValues();
        valores.put("nombre", persona.getNombre());
        valores.put("fecha", persona.getFecha());
        valores.put("zodiaco", persona.getZodiaco());
        valores.put("ruta_imagen", persona.getRutaImagen());
        return this.getWritableDatabase().insert("Personas", null, valores);
    }

    /**
     * Metodo publico para actualizar una persona.
     */
    public void actualizarRegistros(int id, String nombre, String fecha, String zodiaco, String ruta_imagen){
        ContentValues actualizarDatos = new ContentValues();
        actualizarDatos.put("nombre", nombre);
        actualizarDatos.put("fecha", fecha);
        actualizarDatos.put("zodiaco", zodiaco);
        actualizarDatos.put("ruta_imagen", ruta_imagen);
        String where = "_id=?";
        String[] whereArgs = new String[] {String.valueOf(id)};

        try{
            this.getReadableDatabase().update("Personas", actualizarDatos, where, whereArgs);
        }
        catch (Exception e){
            String error =  e.getMessage().toString();
        }
    }

    /**
     * Metodo publico que retorna una persona especifica.
     * @param id
     * @return
     */
    public Persona getPersona(int p_id) {
        String[] columnas = new String[]{"_id", "nombre", "fecha", "zodiaco", "ruta_imagen"};
        Cursor cursor = this.getReadableDatabase().query("Personas", columnas, "_id" + "= " + p_id, null, null, null, null);

        if (cursor != null){
            cursor.moveToFirst();
        }

        Persona persona = new Persona(Integer.parseInt(cursor.getString(0)), cursor.getString(1), cursor.getString(2), cursor.getString(3),
                cursor.getString(4));

        // Retorna la persona especifica.
        return persona;
    }

    /**
     * Metodo publico que cierra la base de datos.
     */
    public void cerrar(){
        this.close();
    }

    /**
     * Metodo publico que devuelve todas las personas.
     * @return
     */
    public Cursor obtenerTodasPersonas(){
        String[] columnas = new String[]{"_id", "nombre", "fecha", "zodiaco", "ruta_imagen"};
        Cursor cursor = this.getReadableDatabase().query("Personas", columnas, null, null, null, null, null);

        if(cursor != null) {
            cursor.moveToFirst();
        }
        return cursor;
    }


    /**
     * Metodo publico que elimina una persona especifica.
     * @param rowId
     * @return
     */
    public boolean eliminaPersona(long id){
        return this.getWritableDatabase().delete("Personas", "_id" + "=" + id, null) > 0;
    }
}

ImagenAdapter :

public class ImagenAdapter extends SimpleCursorAdapter {
    // Objetos de clase.
    private Cursor cursor;
    private Context contexto;
    private LayoutInflater mInflater;


    static class ViewHolder{
        TextView textViewNombre;
        TextView textViewFecha;
        TextView textViewZodiaco;
        ImageView thumb_persona;
    }

    /**
     * Constructor con 4 parametros.
     * @param contexto
     * @param cursor
     * @param from
     * @param to
     */
    public ImagenAdapter(Context contexto, Cursor cursor, String[] from,
                         int[] to) {
        super(contexto, R.layout.fila_persona, cursor, from, to);
        this.contexto = contexto;
        this.cursor = cursor;
        this.mInflater = LayoutInflater.from(contexto);
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;

        if (convertView == null){
            convertView = this.mInflater.inflate(R.layout.fila_persona, null);
            viewHolder = new ViewHolder();

            viewHolder.textViewNombre = (TextView)convertView.findViewById(R.id.persona_nombre);
            viewHolder.textViewFecha = (TextView)convertView.findViewById(R.id.persona_fecha);
            viewHolder.textViewZodiaco = (TextView)convertView.findViewById(R.id.persona_zodiaco);
            viewHolder.thumb_persona = (ImageView)convertView.findViewById(R.id.foto_gallery);
            convertView.setTag(viewHolder);
        }else{
            viewHolder = (ViewHolder)convertView.getTag();
        }
        this.cursor.moveToPosition(position);

        viewHolder.textViewNombre.setText(this.cursor.getString(this.cursor.getColumnIndex("nombre")));
        viewHolder.textViewFecha.setText(this.cursor.getString(this.cursor.getColumnIndex("fecha")));
        viewHolder.textViewZodiaco.setText(this.cursor.getString(this.cursor.getColumnIndex("zodiaco")));

        // Se obtiene la ruta de la imagen.
        String ruta_imagen = cursor.getString(cursor.getColumnIndex("ruta_imagen"));

        File imagenArchivo = new  File(ruta_imagen);
        if(imagenArchivo.exists()){
            Bitmap bitmap = BitmapFactory.decodeFile(imagenArchivo.getAbsolutePath());
            BitmapFactory.Options opciones = new BitmapFactory.Options();
            opciones.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(ruta_imagen, opciones);

            int scaleW = opciones.outWidth / 854 + 1;
            int scaleH = opciones.outHeight / 480 + 1;
            int scale = Math.max(scaleW, scaleH);

            opciones.inJustDecodeBounds = false;
            opciones.inSampleSize = scale;
            opciones.inSampleSize = scale;
            bitmap = BitmapFactory.decodeFile(ruta_imagen, opciones);
            viewHolder.thumb_persona.setImageBitmap(bitmap);
        }
        return convertView;
    }
}

Edit:

Log

// cuando guardo la DB

02-20 14:15:32.473 24882-24882/vrteam.birthday I/MainActivity: inicia exportDB()
02-20 14:15:32.479 24882-24882/vrteam.birthday I/MainActivity: es directorio: /storage/emulated/0/BirthdayBackup
02-20 14:15:32.485 24882-24882/vrteam.birthday I/MainActivity: termina exportDB()...


// cuando restauro la DB

02-20 14:16:39.888 24882-25168/vrteam.birthday I/OpenGLRenderer: Initialized EGL, version 1.4
02-20 14:16:39.888 24882-25168/vrteam.birthday D/OpenGLRenderer: Swap behavior 1
02-20 14:16:43.311 24882-24882/vrteam.birthday E/MainActivity: inicia importDB()
02-20 14:16:43.340 24882-24882/vrteam.birthday E/MainActivity: Termina importDB() procede a activar alertas.
02-20 14:16:43.344 24882-24882/vrteam.birthday I/MainActivity: Activando alarma 1 para usuario Uno
02-20 14:16:43.345 24882-24882/vrteam.birthday I/MainActivity:  alarma 20/2/2017 14:18
    
asked by UserNameYo 18.01.2017 в 17:24
source

2 answers

4

To cancel the Alarm is relatively simple, take the PendingIntent base that you created:

  Intent intent = new Intent(getBaseContext(), otrointento.dos.notif.AlarmReceiver.class);
    //los extras
    intent.putExtra("titulo", editTextNombre.getText().toString());
    PendingIntent pendingIntent = PendingIntent.getBroadcast(
            getBaseContext(),
            notification_id,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT);

By using the AlarmManager you can cancel your alarm that you previously set, it is important to have the id of the requestCode with which the Intent was generated (in your case it is notification_id ) to identify the alarm configured to be canceled, the method used for cancelation is cancel () :

Intent intent = new Intent(getBaseContext(), otrointento.dos.notif.AlarmReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(getBaseContext(), notification_id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
//Cancela Alarma.
alarmManager.cancel(sender);

This will be enough to cancel your alarm.

  

AlarmManager.cancel () Remove alarms with an Intent   coincident. Any alarm, of any type, whose Intent matches   with this, it will be canceled.

The only way to ensure canceling the alarm is by the id it was created with.

Code analysis: To cancel the alert by deleting the user you can use a method which cancels the alarm using its id, the code would be:

  @Override
    public boolean onContextItemSelected(android.view.MenuItem item) {
        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();

        switch (item.getItemId()) {
            case R.id.menu_contextual_editar_persona:
                editarPersona((int)info.id);
                return true;
            case R.id.menu_contextual_eliminar_persona:
                eliminaAlerta((int)info.id); /** CANCELA ALARMA**/
                eliminarPersona((int)info.id);
                recuperarTodasPersonas();
                return true;
            default:
                return super.onContextItemSelected((android.view.MenuItem) item);
        }
    }

    public void eliminaAlerta(int id){
        Intent intent = new Intent(getBaseContext(), vrteam.birthday.notif.AlarmReceiver.class);
        PendingIntent sender = PendingIntent.getBroadcast(getBaseContext(), id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
        //Cancela Alarma.
        alarmManager.cancel(sender); 
    }

There is a detail to correct which apparently could not allow to register the alarm, within the class EditarPersonaActivity method setAlarm() , the format you use is not the same as the one used when defining the SimpleDateFormat() , generate an error could not register the Alarm, therefore make this change:

  //  SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm", Locale.getDefault());
    SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault());
    
answered by 11.02.2017 / 00:38
source
1

As I do not know how far you have progressed in your code, for while with the other problems, I leave you with a slightly more abstract solution.

To keep your code a little more orderly, I recommend you to handle the whole subject of your alarms in your main activity.

First you define constants:

static final int SIN_CAMBIO=0;
static final int NUEVO_USUARIO;
static final int USUARIO_EDITADO;
static final int USUARIO_BORRADO;

Instead of using setResult(int codigo) in the activities to create / edit users, you use:

setResult(SIN_CAMBIO, intent); // si no cambió nada o el resultado fue cancelado (onBackButton)
setResult(NUEVO_USUARIO, intent); // con los nuevos datos del usuario en el intent
setResult(USUARIO_EDITADO, intent); // idem
setResult(USUARIO_BORADO, intent); // en el caso que usas un intent para borrar

If you do not use an activity to delete, you can call onActivityResult(..) direct with the result and the intent.

Then you leave all the code to turn on, update and cancel alarms in onActivityResult :

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        switch(requestCode){
            case SIN_CAMBIO:
                // nada que hacer
                break;
            case NUEVO_USUARIO:
            case USUARIO_EDITADO:
                // obtiene id y fecha de intent (tu código), luego
                setAlarma(uriAlarm, id, fecha);
                break;
            case USUARIO_BORRADO:
                // obtiene id de intent (tu código), luego
                cancelAlarma(uriAlarm, id);
                break;
        }
        recuperarTodasPersonas();
    }

And the methods to manage alarms:

private void setAlarm(Uri passuri, int notification_id, String fecha) throws ParseException {

    System.currentTimeMillis();
    SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm", Locale.getDefault());
    java.util.Calendar cal = java.util.Calendar.getInstance();
    cal.setTime(sdf.parse(fecha));
    Intent intent = new Intent(getBaseContext(), otrointento.dos.notif.AlarmReceiver.class);
    //los extras
    intent.putExtra("titulo", editTextNombre.getText().toString());
    PendingIntent pendingIntent = PendingIntent.getBroadcast(
            getBaseContext(),
            notification_id,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT);

    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);

}

cancel:

private void cancelAlarm(Uri passuri, int notification_id){

    Intent intent = new Intent(getBaseContext(), otrointento.dos.notif.AlarmReceiver.class);
    //los extras no importan
    PendingIntent pendingIntent = PendingIntent.getBroadcast(
            getBaseContext(),
            notification_id,
            intent,
            PendingIntent.FLAG_CANCEL_CURRENT);

    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    alarmManager.cancel(pendingIntent);
}

So you have everything well organized and not distributed in several classes.

    
answered by 16.02.2017 в 04:44