Translate

domingo, 21 de julio de 2013

Creando un sitio web ASP .Net.

Roque Rueda
Mi hermano me solicito que le creara un sitio web para venta de ropa así que para apoyarle he decidido crear un sitio web ASP .net en donde el pueda promocionar las ventas.

Primero vamos a crear una nueva solución.

En el tipo de proyecto vamos a seleccionar una solución en blanco y vamos a darle el nombre que deseamos.


Ahora ya tenemos nuestra solución, una solución puede estar compuesta de diversos proyectos es por eso que nosotros vamos a generar proyectos para que cada responsabilidad quede separada adecuadamente. En este caso vamos a generar una solución con N capas. (Un poco de información aquí.)
Para esto vamos a generar los proyectos necesarios en este caso vamos a crear DataAccessLayer, BusinessLogic, WebPresentation, BusinessEntities, UnitTest, IntegrationTest.
·         Data Access Layer: Esta capa es la encargada de acceder a los datos en la aplicación (dll).
·         Business Logic: Esta capa contendrá todas las reglas y operaciones de negocio (dll).
·         Presentation: Esta capa es la interfaz de usuario que se va a implementar en ASP. NET (asp.net application).
·         Bussiness Entities: Esta capa va a contener contenedores de datos que se comparten en las demás capas (dll).
·         Unit Test: Esta capa contendrá las pruebas unitarias de las funcionalidades que se utilicen (unit testing).
·         Integration Test: Esta capa contiene las pruebas de integración entre entidades, capas o sdks diversos (unit testing).


Presentation
Interfaz de usuario,
Flujos de Interfaz

Business Logic
Componentes de negocio,
Flujos de negocio.

Bussiness Entities
Entidades de negocio

Data Access Layer
Acceso a datos,
Acceso a servicios.
Buscamos obtener una estructura que similar a la siguiente.


Hay que tomar en cuenta que esta es la estructura guía y puede ser modificada si es necesario. Al final me ha resultado una estructura del proyecto en el explorador de soluciones de la siguiente manera (Cambia el color VS2012):



Aquí se puede apreciar que la capa de lógica de negocio de divide en implementación e interfaces así como la capa de acceso a datos, la capa de entidades de negocio se ha mantenido en solo un proyecto de biblioteca de clases (ojo no decir librería), los proyectos de pruebas unitarias y de integración son ambos proyectos de pruebas unitarias y finalmente la presentación es un proyecto de asp.net. Esta estructura en VS2012 nos va a permitir separar adecuadamente cada cuestión de la aplicación (separación de asuntos).
Ahora vamos a iniciar creando una prueba unitaria para nuestra capa de acceso a datos, vamos a seguir el flujo de TDD (Test-driven development). Lo primero que vamos a hacer es crear una prueba la cual va a fallar, lo cual nos va a permitir ir descubriendo el comportamiento de nuestras piezas de software.

Para esto vamos a nuestro proyecto de pruebas unitarias, en este caso vamos a editar la clase que se nos genera por defecto. Para nuestro caso vamos a modificar el nombre dando clic derecho y "rename".


Vamos a llamarla ProductManagerUnitTest.cs ya que vamos a hacer pruebas sobre el administrador de repositorios; pero aun no tenemos administrador de repositorios, esto es ya que vamos a aprovechar la generación de código de VS2012 más adelante y obtener la clase necesaria.

Además vamos a cambiar el nombre al método de prueba de TestMethod1 a GetProductListTest, quedando nuestra clase de prueba de la siguiente manera.




using System;
using System.Collections.Generic;

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace LuisClothes.UnitTest
{
    [TestClass]
    public class ProductManagerUnitTest
    {
        [TestMethod]
        public void GetProductListTest()
        {
            
        }
    }
}

Ahora vamos a iniciar pensando en representar el mundo, tendremos una clase que se llamara ProductManager el cual va a ser el responsable de los productos de nuestra aplicación, esto también implica generar la clase Product ya que el ProductManager administra a Product. Ahora bien nuestro ProductManager va a existir en la capa de acceso a datos, pero, ¿dónde vamos a colocar la clase Product?; la clase Product va a ser parte de las entidades de negocio ya que será compartida por las demás capas. Lo que se espera al mencionar GetProductList es que se obtenga una lista de entidades Product en este caso vamos a utilizar una lista genérica y a poner como tipo Product. Agregamos las referencias a la capa de acceso a datos y a la capa de entidades de negocio, de interfaces de acceso a datos y acceso a datos.


Vamos a agregar los usings para Generics y dentro de la clase using con alias para referirnos a las capas de nuestra aplicación. Claro que ahora vamos a poner los nombres y VS se va quejar de que no existen por lo que vamos a obtener algo como lo siguiente.




Esta prueba de momento nuestra primera tarea es eliminar esos problemas que VS2012 nos marca para poder compilar y ejecutar la prueba. Aquí solo vamos a escribir lo mínimo necesario. En BussinessEntities vamos a agregar la clase Product, de momento vamos a colocar las propiedades básicas sin adentrarnos mucho en el detalle.



/*
 * Copyright 2013 Roque Rueda.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LuisClothes.BusinessEntities
{
    /// 
    /// Represents a basic Product that can be sell in our store.
    /// 
    public class Product
    {
        /// 
        /// Identifier of this product.
        /// 
        public int Id { get; set; }

        /// 
        /// Name of this product.
        /// 
        public string Name { get; set; }

        /// 
        /// Price of this product in MX pesos.
        /// 
        public double Price { get; set; }
    }
}


Ahora que ya tenemos nuestra clase Product vamos a construir el proyecto vamos a ver lo siguiente.




Ya nos logramos deshacer de un error de compilación, ahora vamos a las interfaces de acceso a datos debemos generar la interfaz IProductManager y definir el método GetProductList. Primero se crea la interfaz haciendo clic derecho sobre el proyecto DataAccessLayerInterfaces y agregar interfaz.

De entrada generamos la interfaz únicamente algo como lo siguiente:


Ahora vamos a definir nuestro metodo GetProductList pero debemos recordar que ya que vamos a obtener una lista de Product vamos a necesitar hacer referencia a las entidades de negocio, por lo que agregamos una referencia a BusinessEntities.


La estructura de nuestro proyecto sera algo como lo siguiente (noten como elimine las referencias que no eran necesarias).


La definición del método será la siguiente:


Yo prefiero iniciar agregando los comentarios del método o pieza de código que me encuentro modificando para que así pueda desde un inicio saber que se debe esperar de resultado. En este caso se define que se retorna la lista de todos los productos existentes o null si no existe ningún producto.


Vemos que ya nos hemos hecho cargo de otro error de compilacion ahora solo nos resta definir la clase ProductManager, ya que definimos una variable IProductManager y asignamos un ProductManager podemos inferir que ProductManager implementa la interfaz por lo que si la contener codigo para devolver una lista de objetos. Para poder utilizar la interfaz debemos agregar la referencia al proyecto.


Una vez hecho esto vamos a poder implementar la interfaz.

Tambien debemos agregar una referencia a las entidades de negocio con el fin de poder utilizar la clase Product.


Finalmente la clase ProductManager tendra una estructura como la siguiente:



Y ya no debemos tener errores de compilación en nuestro código por lo que la ejecución de nuestra prueba puede comenzar. Para eso regresamos a la prueba unitaria y vamos a hacer clic derecho sobre el metodo de prueba y seleccionamos run test.


Cuando ejecutamos nuestra prueba vamos a ver un resultado como el siguiente:


Nuestra prueba ha fallado :( pero no se pongan tristes, ya que de acuerdo con nuestra forma de trabajo la prueba debe fallar, ahora si notaron el mensaje de error nos indica que se lanzo la excepcion NotImplementedException esto es así debido a la implementación que se coloco en el método que genero por nosotros amablemente VS2012. Entonces si adivinan debemos modificar la implementación de ese método; hacemos clic en el nombre del método GetProductList del mensaje de fallo en la prueba.



using System;
using System.Collections.Generic;

using LuisClothes.DataAccessLayerInterfaces;
using LuisClothes.BusinessEntities;

namespace LuisClothes.DataAccessLayer
{
    /// 
    /// Reprensents a product repository and contains the funtions to access the products.
    /// 
    public class ProductManager : IProductManager
    {
        public List CurrentProducts { get; private set; }

        /// 
        /// Populates the current products list.
        /// 
        private void PopulateProducts()
        {
            if (CurrentProducts == null) // Lazy creation
            {
                CurrentProducts = new List();
                for (int i = 0; i < 10; i++)
                {
                    CurrentProducts.Add(new Product() { Id = i, Name = "Product" + i, Price = i * 1000 });
                }
            }
        }


        #region IProductManager implementation

        /// 
        /// Get a list of products that exists in a resource repository.
        /// 
        /// 
        /// List of all existing products or null if there aren't any product.
        /// 
        /// 
        public List GetProductList()
        {
            // We are going to set dummy data in order to past this test.
            // TODO: Add the database implementation.
            PopulateProducts();
            return CurrentProducts;
        }

        #endregion
    }
}
Ahora vamos a volver a ejecutar nuestra prueba.

Como vemos en los resultados de las pruebas, la prueba paso. De este modo es como se va a generar la funcionalidad para la aplicacion.
Saludos! Esperen la siguiente parte.

miércoles, 3 de julio de 2013

Creando una aplicación de libreta en Android Studio.

Para crear una aplicación utilizando AndroidStudio vamos a hacer click en File -> New Project. Con lo que se nos mostrara un formulario como el siguiente:


En en el sdk mínimo requerido seleccionamos la versión api versión 11, en la versión destino la versión de api 14 y en compilado la más actual hasta este momento la api versión 17 y el tema de la aplicación Holo Light with Dark Action Bar.


Posteriormente vamos a seleccionar la imagen para el icono para el launcher de nuestra aplicación, el launcher de la aplicación es aquel icono que al presionarlo inicia la aplicación.


Yo he seleccionado uno les recomiendo sitios como iconfinder.com o vectorarchive también deviantart.com siempre y cuando respetando las licencias que proveen las imágenes.

Posteriormente vamos a indicar el tipo de Activity para nuestra aplicacion en este caso seleccionamos una actividad en blanco.


Para la navegación de nuestra aplicación vamos a seleccionar Dropdown esto ya que estamos pensado que nuestra aplicación de libreta presente entre diversos documentos utilizando este Dropdown.


Una vez hecho esto se nos presenta la pantalla con la estructura inicial del proyecto.



Esta pantalla nos indica que aun no tenemos seleccionado ningún elemento de nuestro proyecto vamos a iniciar creando la clase que representara y almacenara los archivos de texto, nuestra libreta tomara el texto y lo almacenara en un archivo de texto. Los archivos de texto usualmente tienen terminación .txt (pero se puede utilizar cualquier terminación para los archivos en realidad); para mantener los archivos con una terminación utilizada generalmente vamos a utilizar esta.

Para esto vamos a crear una clase que nos permita generar un archivo de texto a partir del texto, y también que nos obtenga el texto a partir de un archivo (operación inversa).

Vamos a ir a nuestro arbol del proyecto y vamos a agregar una nueva clase.


Vamos a hace click derecho en nuestra carpeta com.roque.rueda.notepad (o como le nombraron) y agregar una nueva clase. Le vamos a nombrar TextFile.


La clase debe tener la funcionalidad para permitirnos la generación de los archivos de texto. Vamos a iniciar con la parte que a mi parecer es la mas importante de la aplicación que es la generación de los archivos de texto. La clase que vamos a generar sera algo como lo siguiente.

/*
 * Copyright 2013 Roque Rueda.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.roque.rueda.notepad;

import android.content.Context;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

/**
 * Save a file using a text input also gets the text of a file
 * and presents as a string.
 * Created by Roque Rueda on 25/06/13.
 */
public class TextFile {

    private Context mContext;
    private static final String ENCODING = "utf8";

    public TextFile(Context ctx) {
        mContext = ctx;
    }

    /**
     * Create a file in the device file system.
     * @param path Path where a new text file is going to be created.
     * @param content Text content of the file.
     * @return True if the file can be created.
     * @throws IOException if there's a problem creating the new file.
     */
    public boolean createFile(String path, String content)
            throws IOException {
        FileOutputStream fileOutputStream = mContext.openFileOutput(path, Context.MODE_PRIVATE);
        OutputStreamWriter osw = new OutputStreamWriter(fileOutputStream, ENCODING);
        osw.write(content);
        osw.flush();
        osw.close();
        return true;
    }

    /**
     * Read the contents of the file and returns as a string.
     * @param path Path of the file that is going to be read.
     * @return Content of the file.
     * @throws IOException if the file can't be found or if there's a problem
     * reading the content of he file.
     */
    public String getFileContent(String path)
            throws IOException{

        StringBuilder content = new StringBuilder(350);
        FileInputStream fileInputStream = mContext.openFileInput(path);
        InputStreamReader isr = new InputStreamReader(fileInputStream, ENCODING);
        BufferedReader br = new BufferedReader(isr);
        String line;
        while ((line = br.readLine()) != null){
            content.append(line).append("\n");
        }
        return content.toString();
    }

}


Esta clase ofrece la funcionalidad de la creación de archivo de texto, para la creación del archivo de texto se requiere del método openFileOutput el cual proviene de la clase Context es por eso necesario que en el constructor de la clase se requiera de una instancia de esta clase para poder realizar las operaciones, (para que android studio nos genere el constructor utilize las teclas alt + insert). La creacion del archivo es una operacion sencilla utilizando los métodos de la clase Context.

Para extraer el contenido del archivo se utiliza el metodo openFileInput pasando la ruta del archivo una vez realizado se lee el archivo linea por linea y se almacena en un StringBuilder, finalmente se regresa toda la cadena generada en el archivo. De momento se omiten el manejo de excepciones y las verificaciones de datos.


Ahora vamos a regresar a nuestra clase NoteActivity que fue generada con el proyecto. La cual contiene lo siguiente:

package com.roque.rueda.notepad;

import android.annotation.TargetApi;
import android.app.ActionBar;
import android.os.Bundle;
import android.content.Context;
import android.os.Build;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.NavUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class NoteActivity extends FragmentActivity implements ActionBar.OnNavigationListener {

    /**
     * The serialization (saved instance state) Bundle key representing the
     * current dropdown position.
     */
    private static final String STATE_SELECTED_NAVIGATION_ITEM = "selected_navigation_item";

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

        // Set up the action bar to show a dropdown list.
        final ActionBar actionBar = getActionBar();
        actionBar.setDisplayShowTitleEnabled(false);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);

        // Set up the dropdown list navigation in the action bar.
        actionBar.setListNavigationCallbacks(
                // Specify a SpinnerAdapter to populate the dropdown list.
                new ArrayAdapter(
                        getActionBarThemedContextCompat(),
                        android.R.layout.simple_list_item_1,
                        android.R.id.text1,
                        new String[] {
                                getString(R.string.title_section1),
                                getString(R.string.title_section2),
                                getString(R.string.title_section3),
                        }),
                this);
    }

    /**
     * Backward-compatible version of {@link ActionBar#getThemedContext()} that
     * simply returns the {@link android.app.Activity} if
     * getThemedContext is unavailable.
     */
    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    private Context getActionBarThemedContextCompat() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            return getActionBar().getThemedContext();
        } else {
            return this;
        }
    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        // Restore the previously serialized current dropdown position.
        if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) {
            getActionBar().setSelectedNavigationItem(
                    savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        // Serialize the current dropdown position.
        outState.putInt(STATE_SELECTED_NAVIGATION_ITEM,
                getActionBar().getSelectedNavigationIndex());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.note, menu);
        return true;
    }
    
    @Override
    public boolean onNavigationItemSelected(int position, long id) {
        // When the given dropdown item is selected, show its contents in the
        // container view.
        Fragment fragment = new DummySectionFragment();
        Bundle args = new Bundle();
        args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1);
        fragment.setArguments(args);
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.container, fragment)
                .commit();
        return true;
    }

    /**
     * A dummy fragment representing a section of the app, but that simply
     * displays dummy text.
     */
    public static class DummySectionFragment extends Fragment {
        /**
         * The fragment argument representing the section number for this
         * fragment.
         */
        public static final String ARG_SECTION_NUMBER = "section_number";

        public DummySectionFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_note_dummy, container, false);
            TextView dummyTextView = (TextView) rootView.findViewById(R.id.section_label);
            dummyTextView.setText(Integer.toString(getArguments().getInt(ARG_SECTION_NUMBER)));
            return rootView;
        }
    }

}

En nuestro metodo onCreate modificaremos el titulo de “Section 1” a “New document”, androidStudio nos muestra el valor del metodo getString pasando el identificador del string de nuestro archivo strings, por lo tanto para poder realizar la modificacion nos movemos al archivo strings.xml y modificaremos el valor de “title_section1”, quedando algo como lo siguiente:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">Notepad</string>
    <string name="action_settings">Settings</string>
    <string name="title_section1">New document</string>
    <string name="title_section2">Section 2</string>
    <string name="title_section3">Section 3</string>

</resources>


Adicional vamos a agregar la final de nuestro método onCreate la creación de nuestra clase TextFile e invocaremos la creación del archivo con un contenido por defecto de momento.

mTextFile = new TextFile(this);
try {
 mTextFile.createFile("test.txt", "Hello World");
} catch (IOException e) {
 e.printStackTrace();
}


Una vez hecho esto solo tenemos que mostrar el contenido de nuestro archivo en la pantalla. Debido a que el diseño de nuestra actividad se compone de Fragments, vamos a modificar el código que se genero por nosotros en el método onNavigationItemSelected de la siguiente manera.


@Override
    public boolean onNavigationItemSelected(int position, long id) {
        // When the given dropdown item is selected, show its contents in the
        // container view.
        Fragment fragment = new DummySectionFragment();
        Bundle args = new Bundle();
        
        switch (position){
            case 0:{
                String content = null;
                try {
                    content = mTextFile.getFileContent("test.txt");
                } catch (IOException e) {
                    e.printStackTrace();
                }
                args.putString(DummySectionFragment.ARG_TEXT_FILE, content);
                break;
            }
            default:{
                args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1);
                break;
            }
        }
        
        
        fragment.setArguments(args);
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.container, fragment)
                .commit();
        return true;
    }


Estas modificación también implican modificación a la clase interna generada DummySectionFragment agregando una constante: ARG_TEXT_FILE la cual se utiliza como llave para recuperar los datos que se obtienen del archivo de texto. Para lo que tambien vamos a modificar el metodo onCreateView. Teniendo como resultado lo siguiente:




/**
     * A dummy fragment representing a section of the app, but that simply
     * displays dummy text.
     */
    public static class DummySectionFragment extends Fragment {
        /**
         * The fragment argument representing the section number for this
         * fragment.
         */
        public static final String ARG_SECTION_NUMBER = "section_number";

        public static final String ARG_TEXT_FILE = "myTextFile";

        public DummySectionFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_note_dummy, container, false);
            TextView dummyTextView = (TextView) rootView.findViewById(R.id.section_label);

            if (getArguments().containsKey(ARG_TEXT_FILE)){
                dummyTextView.setText(getArguments().getString(ARG_TEXT_FILE));
            }
            else {
                dummyTextView.setText(Integer.toString(getArguments().getInt(ARG_SECTION_NUMBER)));
            }

            return rootView;
        }
    }


El resultado de la clase es el siguiente:




package com.roque.rueda.notepad;

import android.annotation.TargetApi;
import android.app.ActionBar;
import android.os.Bundle;
import android.content.Context;
import android.os.Build;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.NavUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import java.io.IOException;

public class NoteActivity extends FragmentActivity implements ActionBar.OnNavigationListener {

    /**
     * The serialization (saved instance state) Bundle key representing the
     * current dropdown position.
     */
    private static final String STATE_SELECTED_NAVIGATION_ITEM = "selected_navigation_item";

    private TextFile mTextFile;

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

        // Set up the action bar to show a dropdown list.
        final ActionBar actionBar = getActionBar();
        actionBar.setDisplayShowTitleEnabled(false);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);

        // Set up the dropdown list navigation in the action bar.
        actionBar.setListNavigationCallbacks(
                // Specify a SpinnerAdapter to populate the dropdown list.
                new ArrayAdapter(
                        getActionBarThemedContextCompat(),
                        android.R.layout.simple_list_item_1,
                        android.R.id.text1,
                        new String[] {
                                getString(R.string.title_section1),
                                getString(R.string.title_section2),
                                getString(R.string.title_section3),
                        }),
                this);

        mTextFile = new TextFile(this);
        try {
            mTextFile.createFile("test.txt", "Hello World");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Backward-compatible version of {@link ActionBar#getThemedContext()} that
     * simply returns the {@link android.app.Activity} if
     * getThemedContext is unavailable.
     */
    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    private Context getActionBarThemedContextCompat() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            return getActionBar().getThemedContext();
        } else {
            return this;
        }
    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        // Restore the previously serialized current dropdown position.
        if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) {
            getActionBar().setSelectedNavigationItem(
                    savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        // Serialize the current dropdown position.
        outState.putInt(STATE_SELECTED_NAVIGATION_ITEM,
                getActionBar().getSelectedNavigationIndex());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.note, menu);
        return true;
    }
    
    @Override
    public boolean onNavigationItemSelected(int position, long id) {
        // When the given dropdown item is selected, show its contents in the
        // container view.
        Fragment fragment = new DummySectionFragment();
        Bundle args = new Bundle();

        switch (position){
            case 0:{
                String content = null;
                try {
                    content = mTextFile.getFileContent("test.txt");
                } catch (IOException e) {
                    e.printStackTrace();
                }
                args.putString(DummySectionFragment.ARG_TEXT_FILE, content);
                break;
            }
            default:{
                args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1);
                break;
            }
        }


        fragment.setArguments(args);
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.container, fragment)
                .commit();
        return true;
    }

    /**
     * A dummy fragment representing a section of the app, but that simply
     * displays dummy text.
     */
    public static class DummySectionFragment extends Fragment {
        /**
         * The fragment argument representing the section number for this
         * fragment.
         */
        public static final String ARG_SECTION_NUMBER = "section_number";

        public static final String ARG_TEXT_FILE = "myTextFile";

        public DummySectionFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_note_dummy, container, false);
            TextView dummyTextView = (TextView) rootView.findViewById(R.id.section_label);

            if (getArguments().containsKey(ARG_TEXT_FILE)){
                dummyTextView.setText(getArguments().getString(ARG_TEXT_FILE));
            }
            else {
                dummyTextView.setText(Integer.toString(getArguments().getInt(ARG_SECTION_NUMBER)));
            }

            return rootView;
        }
    }

}

Y cuando ejecutemos en el emulador obtendremos el siguiente resultado.



Saludos dudas o comentarios abajo.

domingo, 23 de junio de 2013

Actividades en Android

Una actividad en Android representa una pantalla la cual es presentada al usuario. Dependiendo de la complejidad de la aplicación es más probable el uso de diferentes pantallas se hacen necesarias.

Usualmente las actividades se encargan del procesamiento de los eventos disparados por el usuario. Y consisten de fragmentos que permiten que la Interfaz de Usuario se componga de actividades secundarias. Para la navegación entre actividades se inicia una nueva actividad. La mayoría de las Activitys están diseñadas para ocupar toda la pantalla sin embargo se pueden crea actividades flotantes o semitransparentes.


Ciclo de vida de una Activity.


Para manejar los cambios de estado Android provee una serie de eventos que son disparados entre cada transición de estado de una actividad. El ciclo de vida completo de una actividad es desde el método onCreate hasta el método onDestroy (cabe aclarar que muchas actividades son destruidas sin llegar al método onDestroy); el ciclo de vida visible de una actividad comprende unicamente los métodos onStart hasta onStop, y el ciclo de vida activo de una actividad va desde el método onResume hasta onPause.


El siguiente framento de codigo explica los elementos que se colocan dentro de cada uno de los métodos. Fuente: Professional Android 4 Application Development.





package com.roque.rueda.helloworld;

import android.app.Activity;
import android.os.Bundle;

/**
 * Created by Roque Rueda on 23/06/13.
 */
public class MyStateChangeActivity extends Activity {

    // Called at the start of the full lifetime.
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Initialize Activity and inflate the UI.
    }
    
    // Called after onCreate has finished, use to restore UI state
    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        // Restore UI state from the savedInstanceState.
        // This bundle has also been passed to onCreate.
        // Will only be called if the Activity has been 
        // killed by the system since it was last visible.
    }
    
    // Called before subsequent visible lifetimes
    // for an Activity process.
    @Override
    public void onRestart(){
        super.onRestart();
        // Load changes knowing that the Activity has already
        // been visible within this process.
    }
    
    // Called at the start of the visible lifetime.
    @Override
    public void onStart(){
        super.onStart();
        // Apply any required UI change now that the Activity is visible.
    }
    
    // Called at the start of the active lifetime.
    @Override
    public void onResume(){
        super.onResume();
        // Resume any paused UI updates, threads, or processes required
        // by the Activity but suspended when it was inactive.
    }
    
    // Called to save UI state changes at the
    // end of the active lifecycle.
    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        // Save UI state changes to the savedInstanceState.
        // This bundle will be passed to onCreate and 
        // onRestoreInstanceState if the process is
        // killed and restarted by the run time.
        super.onSaveInstanceState(savedInstanceState);
    }
    
    // Called at the end of the active lifetime.
    @Override
    public void onPause(){
        // Suspend UI updates, threads, or CPU intensive processes
        // that don’t need to be updated when the Activity isn’t
        // the active foreground Activity.
        super.onPause();
    }
    
    // Called at the end of the visible lifetime.
    @Override
    public void onStop(){
        // Suspend remaining UI updates, threads, or processing
        // that aren't required when the Activity isn’t visible.
        // Persist all edits or state changes
        // as after this call the process is likely to be killed.
        super.onStop();
    }
    
    // Sometimes called at the end of the full lifetime.
    @Override
    public void onDestroy(){
        // Clean up any resources including ending threads,
        // closing database connections etc.
        super.onDestroy();
    }

}

jueves, 13 de junio de 2013

Tipos de aplicaciones Android.


  • Primer plano: Son aplicaciones que son útiles únicamente solo cuando es activada y se suspende cuando no es visible. Un ejemplo claro de este tipo de aplicaciones son los juegos.
  • Segundo plano: Es una aplicación que es limitada en interacción, salvo por la configuración, estas aplicaciones se mantienen la mayor parte de su ejecución ocultas. Aplicaciones de este tipo son raras sin embargo sin son muy utilizadas, ejemplos son las aplicaciones de llamadas, responder mensajes SMS, alarmas.
  • Intermitente: Las aplicaciones que tienen un “buen diseño” caen en esta categoría. Son aplicaciones que permiten interacción pero realizan la mayor parte del trabajo en segundo plano. Un ejemplo de estas aplicaciones son el reproductor de música. O el cliente de correo.
  • Widgets y Live Wallpapers: Son aplicaciones que se presentan como parte de la pantalla de inicio o como fondos animados.

martes, 11 de junio de 2013

Color Android Studio

Para cambiar el color de AndroidStudio vamos a ir a File -> Settings.


Una ves ahí vamos Editor -> Colors and Fonts.


Vamos a modificar el Default Theme por Dracula


Nos solicita el reinicio de AndroidStudio.


Reiniciamos y listo nuestro nuevo look and feel.


domingo, 9 de junio de 2013

Entendiendo el proyecto Hola Mundo

Entendiendo el proyecto Hola Mundo.

Vamos a tratar de entender los elementos que se generaron en la publicacion pasada (http://progrmrmalasmanas.blogspot.mx/2013/06/android-studio-tutorial.html) donde se genera un proyecto HelloWorld usando AndroidStudio.


Si miramos en el proyecto generando veremos la clase Activity la que es la base para la interaccion visual y los componentes de la aplicacion. Se podria pensar que es similar a un formulario del desarrollo desktop.



La clase se encuentra en la carpeta src -> main -> java


package com.roque.rueda.helloworld;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class HelloWorld extends Activity {

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


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


En Android los componentes visuales son llamados Views, los cuales podrían compararse con los controles del desarrollo desktop. La plantilla que se genera con el proyecto sobre escribe el método onCreate el cual llama al método setContentView el cual asigna la interfaz. Esto inflando un recurso.



setContentView(R.layout.helloworld_activity);




Los recursos para el proyecto Android se almacenan en la carpeta res de la jerarquía de carpetas. Esta incluye varias carpetas layout (diseño de la interfaz de usuario), values (valores simples para la aplicación), drawable (archivos que se generan como imágenes .png, .9.png, .jpg, .gif) para una lista mas detallada vean aquí.





<RelativeLayout 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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".HelloWorld">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

</RelativeLayout>





Realizar la definición de la interfaz de usuario en un archivo xml y posteriormente “inflarla” es el método común para la creación de la interfaz de usuario. Para poder acceder a los elementos que se definieron en el archivo layout se agregan atributos a los Views en el archivo xml. Posteriormente se puede acceder a ellos utilizando el metodo findViewById el cual nos retorna una instancia de un View. A continuacion se muestra una modificacion para agregar un atributo al TextView donde se muestra el texto “HelloWorld”.


<TextView
        android:id="@+id/hello_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />


Básicamente se asigna un identificador a ese View. Y esto nos permite acceder a el de la siguiente manera desde la clase HelloWorld.java.



TextView helloWorld = (TextView) findViewById(R.id.hello_text);


Alternativamente (aunque usualmente no se utiliza por no ser considerado una buena practica), puedes generar el layout en código como se muestra en el siguiente fragmento de código.



protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

//        setContentView(R.layout.helloworld_activity);
//        TextView helloWorld = (TextView) findViewById(R.id.hello_text);

        // Params that are used to set up the main layout
        LinearLayout.LayoutParams params;
        params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.WRAP_CONTENT);

        // Params to the text view.
        LinearLayout.LayoutParams textView;
        textView = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.WRAP_CONTENT);
        
        // Layout that will contain all the views
        LinearLayout ll = new LinearLayout(this);
        ll.setOrientation(LinearLayout.VERTICAL);
        
        // Set the text of the textView
        TextView myTextView = new TextView(this);
        myTextView.setText(getString(R.string.hello_world));
        
        // Add the views into the linear layout
        ll.addView(myTextView, textView);
        // Add the layout into the activity
        this.addContentView(ll, params);

    }



Todas las propiedades disponibles en código también se encuentran disponibles en xml. Ademas de permitir separación de el diseño visual del código de la aplicación. Ya que Android se ejecuta en una gran variedad de dispositivos, definir el diseño de la interfaz en el archivo xml facilita incluir diversos diseños optimizados para los tamaños de cada pantalla.

Saludos dudas y comentarios abajo!!

martes, 4 de junio de 2013

Android Studio Tutorial


Roque Manuel Rueda

Momento android. Los dispositivos moviles no habian sido más poplares; telefonos inteligentes con mayor capacidad son opciones regulares para los consumidores. Se puede encontrar a android en una gran variedad de dispositivos lo que permite una mayor audiencia para las aplicaciones. La infraestructura ofrecida por Google Play hace perfecto la distribucion a un gran numero de usuarios.
Hello World.
Creando tu primera aplicación en android studio.
  1.  Selecciona New Project de la ventana de inicio.


  2. 2.       Rellena el nombre de la aplicación con HelloWorld  ademas notaras que se puede incluir el nombre de  modulo, paquete, lugar donde se guardara asi como el sdk minimo tambien el sdk objetivo asi como el usado para la compilacion.
    3.       Selecciona el tema HoloLight with Dark Action Bar.
    4.       Deja marcada las casillas de Create custom launcher icon y create activity.



     5.       Ademas podemos indicar la imagen que se utilizara como icono de nuestra aplicación.


    6.       Una vez hecho esto vamos a seleccionar el estilo de navegacion de nuestra aplicación. Para este caso vamos a utilizar la aplicación en blanco.


    7.       Y precionamos finish. Veremos como se inicia la descarga de los componentes y la construccion de nuestro proyecto.



    8.       Al finalizar nos mostrara una vist de bienvenida con algunos tips sobre el ide. Les recomiendo que lean algunos.


    9.       Ahora la estructura del proyecto generada vemos la clase de nuestra actividad asi como el layout de la misma.


    10.       Vamos a precionar ejecutar nuestra aplicación para verificar como se ve en emulador de android.


    11.       Nos presenta un cuadro de dialogo para indicar el dispositivo donde se ejecutara.


    12. Presionamos ok en mi caso ya tengo un dispositivo por lo que se lanza una instancia del emulador con la aplicación que se acaba de crear


    Listo. Dudas y comentarios abajo saludos!.