2

Estoy tratando de crear un string que me arroje una construcción de RFC mexicano con Android Studio y la clase TextWatcher, en donde necesito la primera letra y primer vocal del apellido paterno, primera letra del apellido materno y primera letra del nombre.

Ejemplo: Diana Alvarez Lopez
Salida: AALD

Este es mi código:
public class MainActivity extends Activity {
    private EditText nombreEditText, apellidoEditText, apellidomatEditiText;
    private TextView textView;

    // ATTENTION: This was auto-generated to implement the App Indexing API.
    // See https://g.co/AppIndexing/AndroidStudio for more information.

    private GoogleApiClient client;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        nombreEditText = (EditText) findViewById(R.id.nombre_et);
        String[] arr = nombreEditText.split(" ", 2);

        apellidoEditText = (EditText) findViewById(R.id.apellido_et);
        textView = (TextView) findViewById(R.id.construccionRFC);
        textView.setVisibility(View.VISIBLE);

        // Set Text Watcher listener 
        nombreEditText.addTextChangedListener(rfcWatcher);
        apellidoEditText.addTextChangedListener(rfcWatcher);

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
    }

    private final TextWatcher elrfcWatcher = new TextWatcher() {
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        public void onTextChanged(CharSequence s, int start, int before, int count) {
            textView.setVisibility(View.VISIBLE);
        }

        public void afterTextChanged(Editable s) {
            textView.setText("" + nombreEditText.getText() + apellidoEditText.getText());
        }
    };

    // ATTENTION: This was auto-generated to implement the App Indexing API.
    // See https://g.co/AppIndexing/AndroidStudio for more information.
    public Action getIndexApiAction() {
        Thing object = new Thing.Builder()
            .setName("Main Page") // TODO: Define a title for the content shown.
            .setUrl(Uri.parse("http://[ENTER-YOUR-URL-HERE]")) // TODO: Make sure this auto-generated URL is correct.
            .build();

        return new Action.Builder(Action.TYPE_VIEW)
            .setObject(object)
            .setActionStatus(Action.STATUS_TYPE_COMPLETED)
            .build();
    }

    @Override
    public void onStart() {
        super.onStart();

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        client.connect();
        AppIndex.AppIndexApi.start(client, getIndexApiAction());
    }

    @Override
    public void onStop() {
        super.onStop();

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        AppIndex.AppIndexApi.end(client, getIndexApiAction());
        client.disconnect();
    }
}
Fran Cámara
  • 736
  • 1
  • 3
  • 21
Diana Lopez
  • 21
  • 1
  • 2
  • ¡Bienvenido a [es.so]! Por favor mira en la ayuda [ask] , [qué puedo preguntar](/help/on-topic) y [qué no](/help/dont-ask). La pregunta tal cual la tienes ahora es muy amplia y es probable que sea cerrada. Te sugiero que la borres y cuando tengas una pregunta clara lo hagas con [un ejemplo mínimo, completo y verificable](http://es.stackoverflow.com/help/mcve). Lo único que has puesto es código que no tiene que ver con lo que quieres hacer y no hay nada de lo que has intentado y qué problema exacto tienes con él. – Awes0meM4n Dec 05 '16 at 07:39
  • 2
    Las reglas para obtener las 4 letras del RFC son más complejas, como se discute en [Cómo validar un RFC de México y su digito verificador](http://es.stackoverflow.com/a/31714/127). No es la primera vocal, sino la primera vocal *interna*. Y hay excepciones si el apellido paterno tiene 1 o 2 letras, no se toma la primera vocal sino la primera letra del apellido materno, o cuando no tiene vocales, una `X`. También hay [excepciones](http://mariano.freevar.com/rfc/Algoritmo-RFC.odt) cuando las 4 letras resulten en una palabra inconveniente (regla 9) o con palabras que no se utilizan (anexo V) – Mariano Dec 05 '16 at 08:12

2 Answers2

6

NO es posible generar el RFC (Registro Federal de Contribuyentes) a partir de los datos personales porque la homoclave es asignada arbitrariamente por el SAT, y no se puede calcular.

El RFC se construye, a modo general, de la siguiente forma:

RFC descompuesto en cada caracter

Donde los 2 primeros caracteres de la homoclave se asignan verificando que no haya otro RFC igual (evitando homonimias). Algunos algoritmos dicen calcular la homoclave por defecto, pero es un cálculo incorrecto que fallará con cada RFC que presenta homonimia.

Además, como explico en Cómo validar un RFC de México y su digito verificador, con las reglas obtenidas del documento Algoritmo para generar el RFC con homoclave para personas fisicas y morales.odt , existen otras reglas para obtener los 4 primeros caracteres del RFC:

  • Las tildes no son tomadas en cuenta. Por ejemplo, si la primera vocal del apellido paterno es Á, se utilizará A.

  • La Ñ se convierte en &.

  • Existen palabras que no se utilizan, y son ignoradas para el cálculo del RFC (anexo V):

    DE, LA, LAS, MC, VON, DEL, LOS, Y, MAC, VAN, MI

  • Cuando el apellido paterno o materno son compuestos, se toma sólo la primera palabra que corresponda a cualquiera de ellos.

  • Si el apellido paterno tiene 1 o 2 letras, no se considera, y se asume que no tiene.

  • Si no tiene alguno de los apellidos (paterno o materno), se toma la primera y segunda letra del apellido que tiene, y el 4to caracter será la segunda letra del nombre.

  • Cuando el apellido paterno no tiene vocales, se utiliza una X en vez de la vocal.

  • El segundo caracter no es la primera vocal, sino la primera vocal interna. Es decir, si la primera letra del apellido paterno es una vocal, se toma la segunda vocal.

  • Cuando el nombre es compuesto, se toma la letra inicial del primer nombre, pero si es MARIA o JOSE, se toma la inicial del segundo.

  • Cuando las 4 letras resulten en una palabra inconveniente (regla 9), se modifica la última letra a una X. Las palabras inconvenientes son:

    BUEI, BUEY, CACA, CACO, CAGA, CAGO, CAKA, CAKO, COGE, COJA, COJE, COJI, COJO, CULO, FETO, GUEY, JOTO, KACA, KACO, KAGA, KAGO, KOGE, KOJO, KAKA, KULO, MAME, MAMO, MEAR, MEAS, MEON, MION, MOCO, MULA, PEDA, PEDO, PENE, PUTA, PUTO, QULO, RATA, RUIN



Para obtener los primeros 4 caracteres del RFC siguiendo estas reglas, utilizamos la siguiente función:

public static String primerosCuatroCaracteresRFC(String nombre, String apellidoPaterno, String apellidoMaterno)
{
    //Eliminar acentos y llevar a mayúsculas
    nombre = eliminarAcentosYSimbolos(nombre);
    apellidoPaterno = eliminarAcentosYSimbolos(apellidoPaterno);
    apellidoMaterno = eliminarAcentosYSimbolos(apellidoMaterno);

    //Nombre: Omitir palabras que no se utilizan, MARIA, JOSE y compuestos, y obtener las 2 primeras letras
    Pattern pattern = Pattern.compile("\\A(?:(?:MARIA|JOSE) )?+(?:(?:DEL?|L(?:AS?|OS)|M(?:AC|[CI])|V[AO]N|Y)\\b ?)*+([A-Z&]?)([A-Z&]?)");
    final Matcher matcherNom = pattern.matcher(nombre);
    matcherNom.find();

    //Apellido: Omitir palabras que no se utilizan, y obtener la primera letra y la vocal interna (si el apellido tiene más de 2 letras)
    pattern = Pattern.compile("\\A(?:(?:DEL?|L(?:AS?|OS)|M(?:AC|[CI])|V[AO]N|Y)\\b ?)*+(([A-Z&]?)[B-DF-HJ-NP-TV-Z&]*([AEIOU]?)[A-Z&]?)");
    final Matcher matcherPat = pattern.matcher(apellidoPaterno);
    matcherPat.find();

    final Matcher matcherMat = pattern.matcher(apellidoMaterno);
    matcherMat.find();

    //LETRAS
    //Obtener vocal de apellido paterno y letra(s) del nombre
    String letraPat = matcherPat.group(2);
    String letraMat = matcherMat.group(2);
    String letraNom = matcherNom.group(1);
    String rfc;
    if (letraPat.isEmpty() || letraMat.isEmpty()) {
        //Si no tiene alguno de los apellidos (paterno o materno), se toma la primera y segunda letra del apellido que tiene
        //y el 4to caracter será la segunda letra del nombre.
        rfc = (matcherPat.group(1) + matcherMat.group(1)).substring(0,2) + letraNom + matcherNom.group(2);
    }
    else if (matcherPat.group(1).length() > 2)
    {
        String vocal = matcherPat.group(3);
        //Cuando el apellido paterno no tiene vocales, se utiliza una X.
        if (vocal.isEmpty())
            vocal = "X";
        rfc = letraPat + vocal + letraMat + letraNom;
    } 
    else
    {
        //Si el apellido paterno tiene 1 o 2 letras, no se toma la primera vocal,
        //y el 4to caracter es la segunda letra del nombre.
        rfc = letraPat + letraMat + letraNom + matcherNom.group(2);
    }


    //Cuando las 4 letras resulten en una palabra inconveniente (regla 9), se modifica la última letra a una X
    if (rfc.matches("BUE[IY]|C(?:A[CGK][AO]|O(?:GE|J[AEIO])|ULO)|FETO|GUEY|JOTO|K(?:A(?:[CG][AO]|KA)|O(?:GE|JO)|ULO)|M(?:AM[EO]|E(?:A[RS]|ON)|ION|OCO|ULA)|P(?:E(?:D[AO]|NE)|UT[AO])|QULO|R(?:ATA|UIN)"))
        return rfc.substring(0,3) + "X";
    else
        return rfc;
}

public static String eliminarAcentosYSimbolos(String s)
{
    s = Normalizer.normalize(s.replaceAll("[Ññ]","&"), Normalizer.Form.NFD);
    s = s.replaceAll("[^&A-Za-z ]", "");
    return s.trim().toUpperCase();
}

Resultado:

╔═══════════════════╦═════════════════╦═════════════════╦══════╗
║      Nombre       ║  Ape. Paterno   ║  Ape. Materno   ║ RFC  ║
╠═══════════════════╬═════════════════╬═════════════════╬══════╣
║ Diana             ║ Álvarez         ║ López           ║ AALD ║
║ María De La Diana ║ Álvarez Gimenez ║ López Fernández ║ AALD ║
║ Alejandro         ║ Crávier         ║ Céspedez        ║ CACX ║
║ Alejandro         ║ Céspedez        ║                 ║ CEAL ║
║ Diego             ║ Si              ║ Von Pato        ║ SPDI ║
║ Diego             ║ Schwdt          ║ Fierro          ║ SXFD ║
║ José María        ║ Gil             ║ Romero          ║ GIRM ║
║ Esteban           ║ Petersen        ║ Niembro         ║ PENX ║
╚═══════════════════╩═════════════════╩═════════════════╩══════╝

Demo:

ideone.com

Mariano
  • 23,777
  • 20
  • 70
  • 102
0

intenta utilizar el siguiente método que acabo de crear que te genera el RFC según un nombre, al método le tendrías que pasar como parametro el valor donde el usuario escriba el nombre y poner este método en el TextWatcher para que se actualice el campo con el resultado de este método:

    public static String generarRFC(String input)
{
    String resultado ="";
    String nombreSplit[] = input.split(" ");
    String nombre = nombreSplit[0];
    String apellidoPaterno = nombreSplit[1];
    String apellidoMaterno = nombreSplit[2];
    boolean vocalEncontrada = false;

    //Sacamos la primera letra del apellido paterno
    resultado += apellidoPaterno.charAt(0);
    //Sacamos la primera vocal del apellido paterno
    for(int i=0; i<apellidoPaterno.length() && !vocalEncontrada;i++)
    {
        String letra = String.valueOf(apellidoPaterno.charAt(i));
        for(int j=0; j<vocales.length; j++)
        {
            if(letra.compareTo(vocales[j]) == 0)
            {
                resultado += letra;
                vocalEncontrada = true;
                break;
            }
        }   
    }

    //Sacamos la primera letra del apellido materno
    resultado += apellidoMaterno.charAt(0);
    resultado += nombre.charAt(0);

    return resultado;
}