lunes, 7 de abril de 2014

Aplicación para Android: Crea una versión de prueba de tu app.


Hoy os traigo una aplicación para Android, para crear una versión trial de tu app. En este artículo expondré, que es eso de versión de prueba, explicare el código fuente, os comentaré porque os interesa usar esto para vuestras aplicaciones Android y porque no.  
 

Introducción: ¿Qué es una aplicación con versión de prueba y en que me beneficia?


Las aplicaciones de versión de prueba, o shareware, son una forma de distribuirlas de forma gratuita para que los usuarios puedan evaluar nuestro producto, con limitaciones de tiempo o de funcionalidades. En nuestro caso vamos a limitar el tiempo de uso. Esto puede retornarnos beneficios, tales como:

-          Podemos dar a probar a nuestros usuarios potenciales nuestro producto o servicio durante un tiempo, y si realmente le gusta y se engancha a nuestra app, seguramente la pague.

-          El mercado Android tiende a inclinarse por las aplicaciones gratuitas, pero si tu aplicación es muy buena u ofrece servicios por los cuales tú, como desarrollador, tienes que pagar, el usuario deberá aportar algo para que por lo menos tu app siga viva en el google place. 


Vamos al lio: Código fuente de la aplicación.


Antes de seguir, he de decir que, el sistema que sigo para hacer esta pequeña aplicación, no es muy seguro, en cuanto a que, un usuario que tenga más o menos idea, borrando los datos de la aplicación tendría de nuevo los días que le demos de prueba. Con lo cual nunca nos pagaría …. La idea sería almacenar los datos en la nube. Puede que haga otra versión y os muestre como se hace. 


Código Fuente: StoredDataManager.java


Empezaremos por la parte del programa que manejará si la aplicación está pagada, si hace falta crear la fecha de expiración, y comprobar cuantos días queda para que la aplicación expire.

StoredDataManager – es una clase que utiliza un SharedPreferences, donde se guarda, clave:valor, en un fichero xml en nuestro móvil. Ahí es donde almacenaremos y consultaremos los datos. 


StoredDataManager.java
package net.alejandre.apptrialversion.storeddata;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.util.Log;

// this SuppressLint is for the SimpleDateFormat.
@SuppressLint("SimpleDateFormat") 
public class StoredDataManager {
 // we need to save the Context (android.content.Context) of our activity:
 private Context initApp;
 // we will save on the SharedPreferences as Key=Value (android.content.SharedPreferences) 
 // the date when the app finalize the free trial.
 private SharedPreferences sharedPreferences;
 // we save here the date saved in the SharedPreferences as java.util.Date
 private Calendar dateEndOfTrial;
 // we save the Date of today:
 private Calendar today;
 // days to end the trial version 
 // TODO - you should change this value.
 private static final int TRIAL_DAYS_AVAILED = 7;
 // format of our dates in string.
 private static final SimpleDateFormat Stringformat = 
   new SimpleDateFormat("dd/MM/yyyy");
 
 /**
  * Constructor StoredDataManager(Context ActivityInitApp):
  * This method is called when the object is created.
  * We instantiate the SharedPreferences and save the Context
  * of the application which call this object. In this case InitActivity.java
  * Finally this create a new Calendar with today.
  */
 public StoredDataManager(Context ActivityInitApp) {
  // saving the Context of the activity we can call the getSharedPreferences method.
  initApp = ActivityInitApp;
  // set the SharedPreferences into our variable:
  sharedPreferences = initApp.getSharedPreferences("datesaved", Context.MODE_PRIVATE);
  // we save today Date:
  today = Calendar.getInstance();
 }
 
 /* --------------------------------------------------------------------
  * ------- Methods to work with the dates -----------------------------
  * -------------------------------------------------------------------- */
 /**
  * Method isSetDate():
  * This method extract the date from the SharedPreferences, save it,
  * and returns true if the date is set or false if it is not.
  * @return
  */
 public boolean isSetDate() {
  // we extract the date from the sharedPreferences as String.
  String dateSaved = sharedPreferences.getString("date", "no date set");
  // if the date is set ...
  if(!dateSaved.equals("no date set")) {
   // we transform the string Date to a Calendar.
         TransformStrToDate(dateSaved);
         return true;
        }
  // if the date is not set in the SharedPreferences we return false.
        return false;
 }
 
 /**
  * Method TransformStrToDate(String dateSaved):
  * This method transforms a String to a Calendar.
  * @param dateSaved - String saved into the SharedPreferences.
  */
 private void TransformStrToDate(String dateSaved) {
  // format of the date saved into the SharedPreferences.
  // day in two numbers
  // month in two numbers
  // year in four numbers
  try {
   dateEndOfTrial = Calendar.getInstance();
   dateEndOfTrial.setTime(Stringformat.parse(dateSaved));
  } catch (ParseException e) {
   // we can have a Parse Exception trying to parse a bad formated date
   // compared with the saved string into the SharedPreferences.
   e.printStackTrace();
  }
 }

 /**
  * Method isEndOfTrial(String today):
  * we compare the date saved into our SharedPreferences
  * and today date.
  * @return true - if is it the same day.
  * @return false - if is not the same day.
  */
 public boolean isEndOfTrial() {
  // we have not the same day and the day of the end has not passed ...
  if(DaysToEnd() >= 0)
   return false;
  // it is the same day.
  return true;
 }
 
 /**
  * Method DaysToEnd():
  * this method returns the days between today and the day when this application
  * will expire.
  */
 public int DaysToEnd() {
  // CHECK THIS OUT!
  // if the year is the same ...
  if(today.get(Calendar.YEAR) == dateEndOfTrial.get(Calendar.YEAR)) {
   return dateEndOfTrial.get(Calendar.DAY_OF_YEAR) - today.get(Calendar.DAY_OF_YEAR);
  } else if(today.get(Calendar.YEAR) > dateEndOfTrial.get(Calendar.YEAR)) {
   // if the year of today is biger than the year of trial end ...
   return 0;
  }
  // if the year of today is smaller than the year of trial end ...
  // what we have to do is take how many days of the year we have to left the year ...
  int daysToEndOfYear = 365 - today.get(Calendar.DAY_OF_YEAR);
  // now this days with days of year to the end of trial we have how many days we have to
  // the trial version ends...
  return dateEndOfTrial.get(Calendar.DAY_OF_YEAR) + daysToEndOfYear;
  
 }
 
 /**
  * Method setEndOfTrialDate(String date):
  * This method set a date generated to the SharedPreferences.
  */
 public void setEndOfTrialDate() {
  // we get today in a Calendar Object:
  Calendar end = today;
  Log.e("TODAY:",Stringformat.format(end.getTime()));
  // we add the days set from today:
  end.add(Calendar.DATE, TRIAL_DAYS_AVAILED);
  Log.e("END TRIAL DAY:",Stringformat.format(end.getTime()));
  // we use an Editor (android.content.SharedPreferences.Editor) to storage
  // data in our SharedPreferences:
  Editor editor = sharedPreferences.edit();
  // we save the date in format dd/MM/yyyy.
   editor.putString("date",Stringformat.format(end.getTime()));
   // and make that change to persist in our SharedPreferences.
   editor.commit();
 }
 
 /* --------------------------------------------------------------------
  * ------- End of Methods to work with the dates ----------------------
  * --------------------------------------------------------------------
  * --------------------------------------------------------------------
  * ------- Methods to work with the payment data  ---------------------
  * -------------------------------------------------------------------- */
 
 /**
  * Method initializePaid():
  * This method extract the paid value from the SharedPreferences, and
  * check if it is not set to initialize it to false.
  * @return
  */
 public void initializePaid() {
  // we extract the paid value from the sharedPreferences as String.
  String paidSaved = sharedPreferences.getString("paid", "not set");
  // if paid is not set ...
  if(paidSaved.equals("not set")) {
         // we set it to false:
   setPaid(false);
        }
  
 }
 
 /**
  * Method isPaid():
  * This method extract the paid value from the SharedPreferences and
  * return it.
  * @return
  */
 public boolean isPaid() {
  // we extract the paid value from the sharedPreferences as String.
  String paidSaved = sharedPreferences.getString("paid", "not set");
  // we check if it is saved true and return true or,
  // in other case we return false.
  return (paidSaved.equals("true")) ? true : false;
 }
 
 /**
  * Method setPaid(boolean isPaid):
  * this method set the paid value in the SharedPreferences.
  * @param isPaid
  */
 public void setPaid(boolean isPaid) {
  // we use an Editor (android.content.SharedPreferences.Editor) to storage
  // data in our SharedPreferences:
  Editor editor = sharedPreferences.edit();
  // we save the date in format dd/MM/yyyy.
   editor.putString("paid", (isPaid) ? "true" : "false" );
   // and make that change to persist in our SharedPreferences.
   editor.commit();
 }
  
}

Código Fuente: InitActivity.java


Esta activity es la que se inicia nada más ejecutar nuestra aplicación en el móvil siempre. Lo que hace es, a través de la clase que vimos antes, StoredDataManager, consultar si está pagada o no y en caso negativo comprobar si existe la fecha o no y si hoy es el dia de la expiración de la aplicación. Hace todas las comprobaciones para mostrar un mensaje en un TextView nada más… pero la funcionalidad está clara.



InitActivity.java
package net.alejandre.apptrialversion;

import net.alejandre.apptrialversion.storeddata.StoredDataManager;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;

public class InitActivity extends Activity {
 
 private StoredDataManager storedDataMngr;
 private int daysToEnd;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.init_app);
        // instantiate the TextView:
        TextView prompt = (TextView) findViewById(R.id.displayDaysToEnd);
        // 1º - we instantiate our StoredDataManager object:
        storedDataMngr = new StoredDataManager(this);
        // 2º - now we try to initialize if the app is paid to false.
        storedDataMngr.initializePaid();
        // 3º - we check if the app is not paid to continue checking things...
        if(!storedDataMngr.isPaid()) {
         // 4º we ask if the date of end is set:
         if(storedDataMngr.isSetDate()) {
          // 5º - we ask if today is the final day of free trial.
          if(storedDataMngr.isEndOfTrial()) {
           daysToEnd = storedDataMngr.DaysToEnd();
           // TODO - Here you have to send to the user 
           // to your playStore app premium version or whatever you want to do.
          } else {
           // TODO - Here you will send the user to the main activity of your
           // application. With an Intent. In this example, we save the number of
           // days to finish the trial.
           daysToEnd = storedDataMngr.DaysToEnd();
          }
         } else {
          // 5º - if the date is not set ...
          storedDataMngr.setEndOfTrialDate();
          // we set the date. You don not have to do it. just make the intent
          // deleting from here to the first }.
          storedDataMngr.isSetDate();
          // TODO - Here you will send the user to the main activity of your
          // application. With an Intent. In this example, we save the number of
          // days to finish the trial.
          daysToEnd = storedDataMngr.DaysToEnd();
         }
         Log.e("toend", daysToEnd+"");
         if(daysToEnd > 0) {
          // 6º - we put the days in the prompt to see it in the Activity:
          prompt.setText(daysToEnd+" Trial days.");
         } else {
          prompt.setText("This App has expired, Please go to menu -> buy app.");
         }
        } else {
         // if we are here, the application is paid ...
         prompt.setText("This App was paid, Thank you!");
   // TODO - Here you will send the user to the main activity of your
   // application. With an Intent.
        }
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.init_app, menu);
        return true;
    }
    
    /**
     * This method is called when clicked a menu item.
     */
    @Override
 public boolean onOptionsItemSelected(MenuItem item) {
     Intent intent;
     switch (item.getItemId()) {
  case R.id.item_buy:
   // we do it, finish to refresh when press back in the 
   // PayActivity calling a new intent.
   finish();
   // we navigate to the activity to pay:
   intent=new Intent(this,PayActivity.class);
   startActivity(intent);
   return true;
  default:
   return super.onOptionsItemSelected(item);
  }
 }   
}

Código Fuente: PayActivity.java


Esta activity lo único que hace es una simulación de pago muy simple, cambiando un false por un true en nuestro almacenamiento interno (SharedPreferences):



PayActivity.java
package net.alejandre.apptrialversion;

import net.alejandre.apptrialversion.storeddata.StoredDataManager;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.widget.TextView;

public class PayActivity extends Activity {
 
 private StoredDataManager storedDataMngr;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.init_app);
        // instantiate the TextView:
        TextView prompt = (TextView) findViewById(R.id.displayDaysToEnd);
        // 1º - we instantiate our StoredDataManager object:
        storedDataMngr = new StoredDataManager(this);
        // 2º - now we set
        storedDataMngr.setPaid(true);
        prompt.setText("This App has been paid, Thank you!, press back");

    }

    @Override
 public void onBackPressed() {
     // we do it to finish this Activity.
     finish();
     // we navigate to the initial activity:
     Intent intent=new Intent(this,InitActivity.class);
     startActivity(intent);
  super.onBackPressed();
 }

 @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.init_app, menu);
        return true;
    }
    
}



Bueno chic@s, espero que más o menos entendáis lo que he pretendido hacer con esta aplicación, si teneis alguna duda, preguntar, que no pasa nada, si pensáis que debería desarrollar el contenido más pedirlo y lo hare encantado, espero que os sirva.

Podeis coger el proyecto entero de aqui: 
https://github.com/demon666ro/AppTrialVersionProject

No hay comentarios:

Publicar un comentario