sábado, 21 de marzo de 2015

Actualización del navegador MediaNav Renault captur renault clio

Actualización del navegador.

Nuestro Clio tiene de serie el sistema multimedia «Media Nav», que consta de una pantalla táctil de siete pulgadas, la conexión Bluetooth para teléfonos móviles y un navegador que Renault llama «Nav N Go». No hay posibilidad de tener un lector de discos CD, así que quien quiera escuchar música de su elección debe utilizar una memoria USB o un reproductor MP3, ya que el sistema multimedia «Media Nav» sí ofrece una toma USB —compatible con reproductores Ipod—y un conector auxiliar —Aux-In—
La cartografía del navegador es de la empresa NAVTEQ, con mapas de los países España, Portugal, Gibraltar, Andorra, Italia, el Vaticano, San Marino y Grecia y paquetes de puntos de interés —«POI»— de España, Italia, Portugal y Grecia. La primera actualización de los mapas es gratuita, según las instrucciones, hay que realizarla en los 90 días posteriores a la compra del vehículo.
El proceso de actualización no es complicado y requiere unos 30 minutos, una memoria USB  y un ordenador con conexión a Internet. Si se tiene un ordenador portátil y una conexión a Internet wifi o 3G en la zona donde está el coche el proceso es algo más rápido, ya que nos ahorramos los paseos desde el coche a la habitación donde este el ordenador. Eso sí, hay que tener en cuenta que el tamaño de la descarga puede llegar hasta los 4 Gb, por lo que es preferible hacerlo desde una conexión rápida.
El coche lleva un pequeño manual de intrucciones para inicial el proceso. Primero hay que registrase en la base de datos de Renault (se accede desde esta página) y después descargar un programa gratuito denominado «Renault Media Nav Toolbox» (desde esta página).

El segundo paso es introducir la memoria USB en el sistema «Media Nav» —tiene que estar vacía— y acceder al menú opciones del navegador. En este menú hay que seleccionar «Actualización de Mapas». En esa pestaña es posible comprobar los mapas y paquetes de POI que hay instalados —los de nuestro Clio eran «2012 Q2»— y también copiar los datos a la memoria USB. Este paso lo hemos tenido que repetir hasta tres veces a lo largo de todo el proceso, su duración es cercana a los 5 minutos.

Tras finalizar la copia hay que conectar esa memoria USB al ordenador. El programa «Toolbox» nos ha informado automáticamente de la existencia de una versión nueva del software —versión 2.1.0—. Con nuestra conexión a Internet (ADSL 10 Mb), la descarga ha durado 4:30 minutos—.
Vuelta al coche. Al conectar la memoria USB aparece una pantalla mostrando la versión actual y la que deseamos instalar. El proceso de instalación ha durando menos de 5 minutos.  Para comprobar que todo está correcto, hay que ir al menú «opciones» y confirmar la versión. También hay que volver a copiar en la memoria USB los datos actuales del sistema «Media Nav» y con ella actualizar el programa «Toolbox» en el ordenador.

Desde la aplicación «Toolbox», descargamos la actualización de los mapas. En nuestro caso era gratuita, pero es posible ver el precio de cada actualización. Ejemplos:
  • Mapas de Europa, Rusia y Marruecos, precio 119 €
  • Mapas de los países Euro, precio 99 €
  • Mapas de los países de Europa del Este, precio 99 €
  • Mapas de los países de Europa Occidental, precio 99 €
Otra opción, es comprar paquetes de puntos de interés, por ejemplo:
  • Puntos de interés extra de Wcities de Europa Occidental, precio 17,95 €
  • Puntos de interés extra de Wcities de Amsterdam, Bruselas, Dublín y Londres, precio 12,95 €
A nosotros la descarga nos ha tardado 15 minutos. Durante este tiempo, aparece en la pantalla el estado del proceso y los mapas que se están actualizando.

Nos aguarda un nuevo paseo hasta el Clio, el último. Al conectar la memoria USB en el sistema «Media Nav» nos sorprende un mensaje de advertencia que nos informa de que no hay datos multimedia.  Simplemente hay que pulsar en «aceptar» y esperar. Si sois impacientes —nosotros lo fuimos— y tocáis la pantalla en busca de una solución, el sistema dirá que el paquete de actualización no es válido…Y entonces hay que volver a repetir el proceso de descarga de datos en el UBS. Si se espera, aparece un cuadro de diálogo que dice “¿Está preparado para actualizar el dispositivo?”.
Finalizada la actualización, accedimos a la pantalla correspondiente para comprobar que aparecían instaladas las nuevas versiones («2012 Q4») tanto de los mapas como los paquetes de POI son versión . Para finalizar, volvemos a grabar en la memoria USB los datos del sistema multimedia.

Todo el proceso en un vídeo:
Fuente: http://blogs.km77.com/prueba-renault-clio/2013/06/12/actualizacion-del-navegador/

viernes, 20 de marzo de 2015

Basic access authentication

Basic access authentication

From Wikipedia, the free encyclopedia
In the context of an HTTP transaction, basic access authentication is a method for an HTTP user agent to provide a user name and passwordwhen making a request.

Features[edit]

HTTP Basic authentication (BA) implementation is the simplest technique for enforcing access controls to web resources because it doesn't require cookiessession identifier and login pages. Rather, HTTP Basic authentication uses static, standard HTTP headers which means that no handshakes have to be done in anticipation.

Security[edit]

The BA mechanism provides no confidentiality protection for the transmitted credentials. They are merely encoded with Base64 in transit, but not encrypted or hashed in any way. Basic Authentication is, therefore, typically used over HTTPS.
Because the BA header has to be sent with each HTTP request, the web browser needs to cache credentials for a reasonable period of time to avoid constantly prompting the user for their username and password. Caching policy differs between browsers. Microsoft Internet Explorer by default caches them for 15 minutes.[1]
HTTP does not provide a method for a web server to instruct the client to "log out" the user. However, there are a number of methods to clear cached credentials in certain web browsers. One of them is redirecting the user to a URL on the same domain containing credentials that are intentionally incorrect:
Unfortunately, this behavior is inconsistent between various browsers and browser versions.[2] Microsoft Internet Explorer offers a dedicated JavaScript method to clear cached credentials:[3]
 <script>document.execCommand('ClearAuthenticationCache', 'false');</script>

Protocol[edit]

Server side[edit]

When the server wants the user agent to authenticate itself towards the server, it can send a request for authentication.
This request should be sent using the HTTP 401 Not Authorized response code[4] containing a WWW-Authenticate HTTP header.[5]
The WWW-Authenticate header for basic authentication (used most often) is constructed as following:[6]
WWW-Authenticate: Basic realm="nmrs_m7VKmomQ2YM3:"

Client side[edit]

When the user agent wants to send the server authentication credentials it may use the Authorization header.[7]
The Authorization header is constructed as follows:[8]
  1. Username and password are combined into a string "username:password"
  2. The resulting string is then encoded using the RFC2045-MIME variant of Base64, except not limited to 76 char/line[9]
  3. The authorization method and a space i.e. "Basic " is then put before the encoded string.
For example, if the user agent uses 'Aladdin' as the username and 'open sesame' as the password then the header is formed as follows:
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

See also[edit]

Fuente: http://en.wikipedia.org/wiki/Basic_access_authentication

    jueves, 12 de marzo de 2015

    Diferencia entre Code 128 and EAN 128

    Code 128 provides excellent density for all-numeric data and good density for alphanumeric data. The symbol can be as long as necessary to store the encoded data. It is often selected over Code 39 in new applications because of its density and because it offers a much larger selection of characters. Code 128 is designed to encode all 128 ASCII characters.
    A Code 128 can actually be divided into three subsets A, B, and C. There are three separate start codes to indicate which subset is being used. In addition, each subset includes control characters to switch to another subset in the middle of a barcode.
    • A – Digits, uppercase characters, standard ASCII symbols, and control codes.
    • B – Digits, upper and lower case characters, standard ASCII symbols, and control codes.
    • C – Numeric only. Compresses two numeric digits into each character, providing excellent density. Barcode Xpress will add a leading "0" if there are an odd number of digits in the code.
    When the BarcodeType property is set to write a Code 128 barcode, Barcode Xpress will automatically switch between the three character sets (A, B, and C) to code the data in the shortest form.
    • EAN-128 – The UCC/EAN 128 barcode is a special form of Code 128. EAN-128 is based on Code 128 but it has a double start character. It is also called UCC128.
    Barcode Xpress will generate an error if you have characters in your barcode value that are not allowed.
    Each character is 11 times the width of the most narrow bar. Each character consists of 3 bars and 3 spaces. The bars always use an even number of elements and the spaces use an odd number. This provides the basis for a character-by-character consistency check during scanning. In addition, each Code 128 barcode includes a Modulo 103 checksum.
    Code 128 requires a quiet zone, which should be at least the width of 10 narrow bars. This means that if you set the MakeBarcodeBarSize property to 3 pixels (narrow bar size), you should set the MakeBarcodeBWidth property to 30 pixels.


    Fuente: http://help.accusoft.com/BarcodeXpress/v9.0/activex/Code%20128%20and%20EAN%20128.html

    lunes, 9 de marzo de 2015

    Dos versiones de la misma aplicación con Android Studio Flavors





    Logo Android Studio
    Tras un largo tiempo sin publicar nada por falta de tiempo, vengo a hablar de cómo crear dos versiones de la misma aplicación con Android Studio, es algo común a la hora de desarrollar una aplicación el hacer dos versiones de la misma, una gratuita con publicidad y una de pago por ejemplo. Lógicamente no vamos a hacer dos aplicaciones diferentes ya que a la larga el mantenimiento se haría muy complicado.
    Para cumplir nuestro cometido utilizaremos la herramienta "Flavors" de Android Studio que está pensada y diseñada para ello, utilizando esta forma de trabajar será el propio Gradle el que se encargue de crear "las dos versiones" de la aplicación, pero nosotros sólo tendremos que mantener una, lo que sea diferente en alguna de las dos versiones se realiza en esa versión y listo.
    Antes de Android Studio si utilizabas Eclipse probablemente hayas hecho esto mismo utilizando librerías, es decir, creabas una librería que contenía el código común a las dos versiones y lo que fuese independiente de cada una lo hacías en la versión correspondiente, esto es algo parecido, sólo que simplificado e ideado para hacer el trabajo mucho más fácil.
    Aquí veremos una sencilla aplicación de ejemplo que hará la función de calculadora de la cuál crearemos dos versiones diferentes, una que sólo puede sumar y restar (la gratuita) y otra que puede sumar, restar, multiplicar y dividir (la de pago), he de decir que no voy a comentar el código en sí del ejemplo que vemos a ver, comentaré lo que sea relevante para el tema en cuestión, el código propio de la aplicación es tan simple que no requiere comentarios.

    Creamos un nuevo proyecto

    Empecemos creando un nuevo proyecto al que llamaremos "TestingFlavorsCalc", en el nombre del paquete podemos poner lo que querramos (yo he puesto "com.dolphinziyo.android.testingflavorscalc") y lo demás lo dejamos por defecto.

    Creamos los distintos Flavors

    Una vez el proyecto ha sido creado y podemos empezar a trabajar lo que haremos será crear los distintos flavors, que llevarán el nombre de "free" y "pro", para ello entramos en las "Preferencias del módulo" presionando F4 o con el botón derecho encima de la zona blanca de la izquierda "Open Módule Settings".
    En cuánto se abra, arriba a la izquierda veremos varias pestañas, entre ellas la que dice "Flavors", la abrimos y debajo presionamos en el "+" de color verde. Al hacerlo, el formulario de la derecha cambiará para que introduzcamos los datos específicos de éste, lo que haremos será cambiar el nombre por "free" y lo demás lo copiamos del otro flavor (defaultConfig), el nombre del paquete ("Application Id") debemos cambiarlo para que sea distinto al de la otra versión, si no al subirlo a la Play Store se pensaría que es la misma aplicación, recordemos que Google identifica la aplicación por el nombre del paquete. Yo lo que he hecho ha sido añadir "free" al final del nombre del paquete (quedando así: com.dolphin.android.testingflavorscalcfree).
    Y repetimos el proceso anterior para la versión "pro", llamándola "pro" en vez de "free" y añadiéndole la coletilla al nombre del paquete. Le damos a "Apply" para que se apliquen los cambios y luego cerramos el diálogo pulsando en "Ok".

    Cambiando entre una versión (Build Variants)

    Para poder trabajar en una aplicación u otra es necesario cambiar el Build Variant ya que Android Studio sólo nos permite estar trabajando en único flavor, para ello a la izquierda de Android Studio abajo, vemos una pestaña en vertical que dice "Build Variants", le damos y se nos abre una pequeña ventanita.

    Ahí podemos ver dos columnas "Module" y "Build Variant", pues pinchando en la primera línea, columna "Build Variant" (en "freeDebug" en la imagen anterior) se nos abre un menú desplegable que nos permite seleccionar cualquiera de las cuatro (por defecto) versiones de la aplicación, las dos de la gratuita (debug y release) y las dos de la pro (debug y release también).
    Como dijimos antes Android Studio sólo permite trabajar con una por tanto si tenemos ahí seleccionado freeDebug sólo podremos trabajar en la versión "free", para hacer cambios en la "pro" tendremos que cambiarlo ahí.

    Las carpetas necesarias para los flavors

    Android Studio no crea las carpetas que necesitamos para las diferentes versiones ya que él no sabe cuál es el planteamiento que utilizaremos, por tanto tenemos que crearlas a mano, para ello, dentro de la carpeta "src" (dentro de "app"->"java") crearemos dos carpetas que tienen que llamarse igual que el nombre de los flavor para que Gradle puede identificarlos a la hora de compilar, así que le damos botón derecho a "src"->"New"->"Directory" y le llamamos "free" y lo repetimos para la versión "pro".

    Como vemos hay cuatro carpetas:
    • androidTest: No la utilizaremos en este ejemplo, almacenaría los tests de la aplicación
    • free: Contendrá las ventanas y recursos independientes de la versión gratuita
    • main: Contiene y contendrá las ventanas y recursos comunes a las dos versiones de la aplicación
    • pro: Contendrá las ventanas y recursos independientes de la versión de pago

    El código común a ambas aplicaciones

    Para que se haga notorio que las dos aplicaciones son la misma pero con pequeños cambios antes de acceder a la calculadora habrá una ventana con dos botones que nos permitirá acceder a la calculadora o cerrar la aplicación, así que vamos a crearla.
    Por comodidad voy a cambiar la forma en que se muestra la estructura del proyecto ya que para trabajar con flavors la vista por defecto no me parece cómoda, así que si tú también quieres hacerlo , arriba a la izquierda dónde pone "Android" pinchamos para abrir el desplegable y seleccionamos "Project".





    Primero creamos el "Layout" que contendrá los botones editando el "activity_main" dentro de "main"->"res"->"layout" cuyo código quedaría:
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical"
      android:paddingBottom="@dimen/activity_vertical_margin"
      android:paddingLeft="@dimen/activity_horizontal_margin"
      android:paddingRight="@dimen/activity_horizontal_margin"
      android:paddingTop="@dimen/activity_vertical_margin"
      tools:context=".MainActivity">
     
      <Button
      android:id="@+id/btn_entrar_calculadora"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="@string/abrir_calculadora"/>
     
      <Button
      android:id="@+id/btn_salir"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="@string/salir"/>
    </LinearLayout>
    Nos mostrará dos errores y es porque no tenemos los strings necesarios, así que vamos a copiar los strings para evitar estos y futuros errores, para ello editamos el fichero "strings.xml" dentro de "main"->"res"->"values" dejándolo así:
      <resources>
        <string name="app_name">TestingFlavorsCalc</string>
        <string name="action_settings">Settings</string>
     
        <string name="num_1">Número 1</string>
        <string name="num_2">Número 2</string>
        <string name="sumar">+</string>
        <string name="restar">-</string>
        <string name="multiplicar">*</string>
        <string name="dividir">/</string>
        <string name="igual">=</string>
        <string name="abrir_calculadora">Calculadora</string>
        <string name="salir">Cerrar aplicacion</string>
      </resources>
    Con los errores en el "activity_main.xml" ya resueltos vamos a editar el "MainActivity.java" que contendrá el comportamiento de los botones:
      package com.dolphinziyo.android.testingflavorscalc;
     
      import android.content.Intent;
      import android.support.v7.app.ActionBarActivity;
      import android.os.Bundle;
      import android.view.Menu;
      import android.view.MenuItem;
      import android.view.View;
      import android.widget.Button;
     
     
      public class MainActivity extends ActionBarActivity implements View.OnClickListener {
        Button btnEntrar, btnSalir;
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
     
          btnEntrar = (Button) findViewById(R.id.btn_entrar_calculadora);
          btnSalir = (Button) findViewById(R.id.btn_salir);
     
          btnEntrar.setOnClickListener(this);
          btnSalir.setOnClickListener(this);
        }
     
     
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
          // Inflate the menu; this adds items to the action bar if it is present.
          getMenuInflater().inflate(R.menu.menu_main, menu);
          return true;
        }
     
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
          // Handle action bar item clicks here. The action bar will
          // automatically handle clicks on the Home/Up button, so long
          // as you specify a parent activity in AndroidManifest.xml.
          int id = item.getItemId();
     
          //noinspection SimplifiableIfStatement
          if (id == R.id.action_settings) {
            return true;
          }
     
          return super.onOptionsItemSelected(item);
        }
     
        @Override
        public void onClick(View v) {
          if (v == btnEntrar) {
            startActivity(new Intent(this, VentanaCalculadora.class));
          } else if (v == btnSalir) {
            finish();
          }
        }
      }
    Ya tenemos la ventana principal creada, vemos que da un error al final, pero no tenemos que preocuparnos, es porque falta una clase que no hemos creado aun. Antes de ello vamos a crear un objeto que será el que haga la función de la calculadora, y como es común  a las dos versiones a pesar de que una no utilizará todos los métodos, lo crearemos también en la parte general (main), para ello pinchamos con el botón derecho del ratón en el paquete dentro de "main"->"java" y seleccionamos "New"->"Java Class", nos pedirá el nombre, así que ponemos "Calculadora".
    Ahora vamos a implementar toda la logística de este objeto que consta de un constructor y cuatro métodos (sumar, restar, dividir y multiplicar):
      package com.dolphinziyo.android.testingflavorscalc;
     
      /**
      * Creado por dolphinziyo el 19/02/2015.
      * http://www.tecnogame.org
      * http://twitter.com/dolphinziyo
      */
     
      public class Calculadora {
        double num1, num2;
     
        Calculadora(double num1, double num2){
          this.num1 = num1;
          this.num2 = num2;
        }
     
        public double sumar(){
          return num1 + num2;
        }
     
        public double restar(){
          return num1 - num2;
        }
     
        public double multiplicar(){
          return num1 * num2;
        }
     
        public double dividir(){
          return num1 / num2;
        }
      }
    Ya tenemos creado todo lo común a ambas versiones, así que vamos con el funcionamiento de los flavors pero antes aunque no esté creada la ventana de la calculadora (VentanaCalculadora) vamos a añadir al Manifest el "Activity" de esa ventana, para luego no tener errores por culpa de que no es capaz de encontrarla:
    Así quedaría nuestro AndroidManifest:

    Códificando los Flavors

    • Versión "Free"

    Primero y antes que nada seleccionamos "freeDebug" en el "Build Variants" si no lo tenemos seleccionado ya.
    Para esta versión vamos a necesitar un "Layout", un fichero "strings" y un código específico por lo que dentro de la carpeta "free" vamos a crear dos carpetas más, una "java" que contendrá el código y otra "res" (y dentro de esta una llamada "layout") que contendrá los recursos, para ello pulsamos botón derecho en "free"->"New"->"Directory" al que llamamos "java" y de nuevo botón derecho en "free"->"New"->"Android resource directory", en la ventana que se nos abre nos pide varias cosas, de "Directory Name" ponemos "layout" en "Resource Type" seleccionamos también "layout" y en "Source Set" seleccionamos "free", le damos a "Ok" y ya nos crea la carpeta "res" que contiene dentro la de los "layout".

    Del modo que hicimos con la carpeta "layout" hacemos lo mismo para crear la de "values" ya que llevará algunos textos específicos, para ello botón derecho encima de "res"->"New"->"Android resource directory", y ponemos "values" en "Directory Name", seleccionamos "values" en el desplegable de "Resource Type" y "free" en el de "Source Set".
    Ahora creamos el layout principal que llevará nuestra ventana en la carpeta "layout" creada antes en este mismo paso, al layout le llamaremos "calc" para ello botón derecho en la carpeta y "New"->"XML"->"Layout XML File":
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical"
      android:paddingBottom="@dimen/activity_vertical_margin"
      android:paddingLeft="@dimen/activity_horizontal_margin"
      android:paddingRight="@dimen/activity_horizontal_margin"
      android:paddingTop="@dimen/activity_vertical_margin">
     
      <TextView
      android:text="@string/gratuita"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_marginTop="10dp"
      android:layout_marginBottom="10dp"
      android:textSize="20sp"
      android:gravity="center"/>
     
      <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:orientation="horizontal">
     
      <EditText
      android:id="@+id/et_num1"
      android:layout_width="0dip"
      android:layout_height="wrap_content"
      android:layout_weight="1"
      android:hint="@string/num_1"
      android:inputType="numberDecimal"
      android:gravity="center"/>
     
      <TextView
      android:id="@+id/tv_operacion"
      android:layout_width="0dip"
      android:layout_height="wrap_content"
      android:layout_weight="0.10"
      android:gravity="center"/>
     
      <EditText
      android:id="@+id/et_num2"
      android:layout_width="0dip"
      android:layout_height="wrap_content"
      android:layout_weight="1"
      android:hint="@string/num_2"
      android:inputType="numberDecimal"
      android:gravity="center"/>
     
      <TextView
      android:layout_width="0dip"
      android:layout_height="wrap_content"
      android:layout_weight="0.10"
      android:text="@string/igual"
      android:gravity="center"/>
     
      <TextView
      android:id="@+id/tv_resultado"
      android:layout_width="0dip"
      android:layout_weight="1"
      android:layout_height="wrap_content"
      android:gravity="center" />
    </LinearLayout>
     
    <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
     
    <Button
    android:id="@+id/btn_sumar"
    android:layout_width="0dip"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:text="@string/sumar" />
     
    <Button
    android:id="@+id/btn_restar"
    android:layout_width="0dip"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:text="@string/restar" />
    </LinearLayout>
    </LinearLayout>
    Si por casualidad muestra error en alguna de las siguientes líneas, cambiar momentáneamente al "Build Variant" "proDebug" u otro cualquiera y volver al "freeDebug":
    xmlns:android=”http://schemas.android.com/apk/res/android”
    xmlns:tools=”http://schemas.android.com/tools”
    Vamos a crear también el fichero strings específico de la versión gratuita, para ello hacemos igual que con el layout "calc" sólo que esta vez pulsando encima de "values" y seleccionando "Values XML File", como nombre ponemos "strings", dentro contiene:

      <?xml version="1.0" encoding="utf-8"?>
      <resources>
        <string name="app_name">TestingFlavorsCalc Free</string>
        <string name="gratuita">Versión gratuita</string>
      </resources>
    Sólo nos falta añadir el comportamiento de la ventana de la calculadora gratuita, así que dentro de la carpeta "free"->"java" creamos el paquete antes que nada, botón derecho "New"->"Package" y lo llamamos igual que el nombre del paquete principal (en este ejemplo "com.dolphinziyo.android.testingflavorscalc") y dentro del paquete creamos un nuevo "Java Class" que llamaremos "VentanaCalculadora", una vez creado sustituimos el código por el siguiente:

      package com.dolphinziyo.android.testingflavorscalc;
     
      import android.app.Activity;
      import android.os.Bundle;
      import android.view.View;
      import android.widget.Button;
      import android.widget.EditText;
      import android.widget.TextView;
     
      public class VentanaCalculadora extends Activity implements View.OnClickListener{
        Button btnSumar, btnRestar;
        EditText etNum1, etNum2;
        TextView tvResultado, tvOperacion;
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.calc);
     
          btnSumar = (Button)findViewById(R.id.btn_sumar);
          btnRestar = (Button)findViewById(R.id.btn_restar);
     
          btnSumar.setOnClickListener(this);
          btnRestar.setOnClickListener(this);
     
          etNum1 = (EditText)findViewById(R.id.et_num1);
          etNum2 = (EditText)findViewById(R.id.et_num2);
          tvResultado = (TextView)findViewById(R.id.tv_resultado);
          tvOperacion = (TextView)findViewById(R.id.tv_operacion);
        }
     
        @Override
        public void onClick(View v) {
          double num1, num2;
          if(etNum1 != null && etNum2 != null){
            if(!etNum1.getText().toString().equals("")){
              num1 = Float.parseFloat(etNum1.getText().toString());
            }else{
              num1 = 0;
            }
            if(!etNum2.getText().toString().equals("")){
              num2 = Float.parseFloat(etNum2.getText().toString());
            }else{
              num2 = 0;
            }
          }else{
            num1 = 0;
            num2 = 0;
          }
          Calculadora calc = new Calculadora(num1, num2);
          if(v == btnSumar){
            tvResultado.setText("" + calc.sumar());
            tvOperacion.setText(getResources().getString(R.string.sumar));
          }else if(v == btnRestar){
            tvResultado.setText("" + calc.restar());
            tvOperacion.setText(getResources().getString(R.string.restar));
          }
        }
      }
    Llegados a este punto ya podemos ejecutar la aplicación, la versión gratuita ya está hecha y completamente funcional, pero nos falta la versión "pro", así que…
    • Versión "pro"

    Para no alargar más el artículo simplemente dejaré aquí los códigos de la versión "pro", ya que lo demás es igual que la versión "free", no olvides cambiar el "Build Variant" al "proDebug".
    Tras crear las carpetas necesarias y el paquete para el código, les asignamos su comportamiento:
    • strings.xml:
      <?xml version="1.0" encoding="utf-8"?>
      <resources>
        <string name="de_pago">Versión de pago</string>
      </resources>
    • calc.xml:
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical"
      android:paddingBottom="@dimen/activity_vertical_margin"
      android:paddingLeft="@dimen/activity_horizontal_margin"
      android:paddingRight="@dimen/activity_horizontal_margin"
      android:paddingTop="@dimen/activity_vertical_margin">
     
      <TextView
      android:text="@string/de_pago"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_marginTop="10dp"
      android:layout_marginBottom="10dp"
      android:textSize="20sp"
      android:gravity="center"/>
     
      <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:orientation="horizontal">
     
      <EditText
      android:id="@+id/et_num1"
      android:layout_width="0dip"
      android:layout_height="wrap_content"
      android:layout_weight="1"
      android:hint="@string/num_1"
      android:inputType="numberDecimal"
      android:gravity="center"/>
     
      <TextView
      android:id="@+id/tv_operacion"
      android:layout_width="0dip"
      android:layout_height="wrap_content"
      android:layout_weight="0.10"
      android:gravity="center"/>
     
      <EditText
      android:id="@+id/et_num2"
      android:layout_width="0dip"
      android:layout_height="wrap_content"
      android:layout_weight="1"
      android:hint="@string/num_2"
      android:inputType="numberDecimal"
      android:gravity="center"/>
     
      <TextView
      android:layout_width="0dip"
      android:layout_height="wrap_content"
      android:layout_weight="0.10"
      android:gravity="center"
      android:text="@string/igual" />
     
      <TextView
      android:id="@+id/tv_resultado"
      android:layout_width="0dip"
      android:layout_weight="1"
      android:layout_height="wrap_content"
      android:gravity="center" />
    </LinearLayout>
     
    <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
     
    <Button
    android:id="@+id/btn_sumar"
    android:layout_width="0dip"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:text="@string/sumar" />
     
    <Button
    android:id="@+id/btn_restar"
    android:layout_width="0dip"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:text="@string/restar" />
     
    <Button
    android:id="@+id/btn_multiplicar"
    android:layout_width="0dip"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:text="@string/multiplicar" />
     
    <Button
    android:id="@+id/btn_dividir"
    android:layout_width="0dip"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:text="@string/dividir" />
    </LinearLayout>
    </LinearLayout>
    • VentanaCalculadora.java:
      package com.dolphinziyo.android.testingflavorscalc;
     
      import android.app.Activity;
      import android.os.Bundle;
      import android.view.View;
      import android.widget.Button;
      import android.widget.EditText;
      import android.widget.TextView;
     
      public class VentanaCalculadora extends Activity implements View.OnClickListener{
        Button btnSumar, btnRestar, btnMultiplicar, btnDividir;
        EditText etNum1, etNum2;
        TextView tvResultado, tvOperacion;
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.calc);
     
          btnSumar = (Button)findViewById(R.id.btn_sumar);
          btnRestar = (Button)findViewById(R.id.btn_restar);
     
          if(BuildConfig.FLAVOR.equals("pro")){
            btnMultiplicar = (Button)findViewById(R.id.btn_multiplicar);
            btnDividir = (Button)findViewById(R.id.btn_dividir);
     
            btnMultiplicar.setOnClickListener(this);
            btnDividir.setOnClickListener(this);
          }
     
          btnSumar.setOnClickListener(this);
          btnRestar.setOnClickListener(this);
     
          etNum1 = (EditText)findViewById(R.id.et_num1);
          etNum2 = (EditText)findViewById(R.id.et_num2);
          tvResultado = (TextView)findViewById(R.id.tv_resultado);
          tvOperacion = (TextView)findViewById(R.id.tv_operacion);
        }
     
        @Override
        public void onClick(View v) {
          double num1, num2;
          if(etNum1 != null && etNum2 != null){
            if(!etNum1.getText().toString().equals("")){
              num1 = Float.parseFloat(etNum1.getText().toString());
            }else{
              num1 = 0;
            }
            if(!etNum2.getText().toString().equals("")){
              num2 = Float.parseFloat(etNum2.getText().toString());
            }else{
              num2 = 0;
            }
          }else{
            num1 = 0;
            num2 = 0;
          }
          Calculadora calc = new Calculadora(num1, num2);
          if(v == btnSumar){
            tvResultado.setText("" + calc.sumar());
            tvOperacion.setText(getResources().getString(R.string.sumar));
          }else if(v == btnRestar){
            tvResultado.setText("" + calc.restar());
            tvOperacion.setText(getResources().getString(R.string.restar));
          }else if(v == btnMultiplicar){
            tvResultado.setText("" + calc.multiplicar());
            tvOperacion.setText(getResources().getString(R.string.multiplicar));
          }else if(v == btnDividir){
            tvResultado.setText("" + calc.dividir());
            tvOperacion.setText(getResources().getString(R.string.dividir));
          }
        }
      }
    Este es el resultado:
    VERSIÓN FREEVERSIÓN PRO


    Puedes descargar el proyecto con todo preparado y listo para ejecutar de mi Github
    Y eso es todo, cambiando el "Build Variant" puedes ejecutar una versión de la aplicación u otra. Al generar la aplicación firmada se exportarán las dos versiones listas para publicar en Play Store, espero que este artículo haya sido útil y como siempre cualquier duda, sugerencia o comentario puedes dejarlo abajo.
    Relacionado:

    Jesús Moreno - Ingeniero Ténico Informático - consultor Informático

    Hola, soy Jesús Moreno Ingeniero Técnico Informático en sistemas por la US y propietario de éste blog. Mi trabajo en los ultimos años se ...