Translate

domingo, 1 de diciembre de 2013

Creando un sitio web ASP .Net. Parte 5

Para continuar con la creación de nuestro sitio web vamos a crear una conexión con la base de datos la cual nos va a permitir obtener información de la base que creamos.
Crear un usuario en la base de datos

-- Create user for SQL Authentication
CREATE LOGIN clothesUsr WITH PASSWORD = 'HolaMundo'
,DEFAULT_DATABASE = LuisClothes
GO
-- Add User to first database
USE LuisClothes;
CREATE USER clothesUsr FOR LOGIN clothesUsr;
EXEC sp_addrolemember 'db_datareader', 'clothesUsr'
EXEC sp_addrolemember 'db_datawriter', 'clothesUsr'
GO
Crear un rol para ejecución de procedimientos almacenados.
-- 1 - db_executestoredprocedures
-- 1a - Create role
CREATE ROLE db_produccion
GO
Una vez que terminemos la creación de nuestros procedimientos y funciones almacenadas ejecutaremos las siguientes sentencias.
-- 1b - Grant permissions
GRANT EXECUTE TO db_produccion
GO

También vamos a crear el rol para la selección de funciones.
-- 2 - db_selecttablevaluedfunctions
-- 2a - Create role
CREATE ROLE db_select_funtions
GO
Para dar permisos de seleccion a nuestras funciones se ejecutara el siguiente script una vez que terminemos la creacion de las funciones.
-- 2 - Create permissions
DECLARE @Function_Name nvarchar(250);
DECLARE @CMDEXEC1 nvarchar(2000);
DECLARE db_cursor CURSOR FOR 
SELECT [name]
FROM sys.objects
WHERE Type = 'TF'
OPEN db_cursor  
FETCH NEXT FROM db_cursor INTO @Function_Name
WHILE @@FETCH_STATUS = 0  
BEGIN
  
 SET @CMDEXEC1 = 'GRANT SELECT ON [' + @Function_Name + '] TO db_select_funtions;'
 --- SELECT @CMDEXEC1
 EXEC(@CMDEXEC1)
 FETCH NEXT FROM db_cursor INTO @Function_Name
END
CLOSE db_cursor  
DEALLOCATE db_cursor
GO

Ahora vamos a crear algunos procedimientos almacenados como por ejemplo la creación de un producto. Para esto en nuestro Object Explorer vamos a dar clic derecho en stored procedures.



Con lo que nos a generar una plantilla para nuestro procedimiento almacenado.
-- ================================================
-- Template generated from Template Explorer using:
-- Create Procedure (New Menu).SQL
--
-- Use the Specify Values for Template Parameters
-- command (Ctrl-Shift-M) to fill in the parameter
-- values below.
--
-- This block of comments will not be included in
-- the definition of the procedure.
-- ================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:        <Author,,Name>
-- Create date: <Create Date,,>
-- Description:   <Description,,>
-- =============================================
CREATE PROCEDURE <Procedure_Name, sysname, ProcedureName>
      -- Add the parameters for the stored procedure here
      <@Param1, sysname, @p1> <Datatype_For_Param1, , int> = <Default_Value_For_Param1, , 0>,
      <@Param2, sysname, @p2> <Datatype_For_Param2, , int> = <Default_Value_For_Param2, , 0>
AS
BEGIN
      -- SET NOCOUNT ON added to prevent extra result sets from
      -- interfering with SELECT statements.
      SET NOCOUNT ON;

    -- Insert statements for procedure here
      SELECT <@Param1, sysname, @p1>, <@Param2, sysname, @p2>
END
GO

Ahora solo tenemos que dar la definición de nuestro procedimiento.
-- ================================================
-- Project Luis Clothes.
-- ================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:        Roque Rueda.

-- Create date: 24/11/2013

-- Description:   Creates a new product record in
--              the database. If you need to inser
--                      a new row you should give a -1
--                      product id(this is the default value)
-- =============================================
CREATE PROCEDURE Insert_Product (
      -- stored procedure params
      @product_id             int = -1,
      @product_name           nvarchar(150),
      @product_price          decimal(10, 2) = 1,
      @product_photo          nvarchar(2083),
      @product_type           int
      )
AS
BEGIN
      -- SET NOCOUNT ON added to prevent extra result sets from
      -- interfering with SELECT statements.
      SET NOCOUNT ON;
     
      -- Update information or insert if not exists
      UPDATE Product SET Name = @product_name,
                                Price = @product_price,
                                Photo = @product_photo,
                                IdType = @product_type
      WHERE Id = @product_id;
      IF @@ROWCOUNT = 0 -- Check if the row was updated.
      INSERT INTO Product (Name,
                                    Price,
                                    Photo,
                                    IdType,
                                    CreationDate)
      VALUES (@product_name, -- Name
                  @product_price, -- Price
                  @product_photo, -- Photo
                  @product_type, -- Typeid from ProductType
                  GETDATE()); -- Gets the current date
                 
      -- Reset SET NONCOUNT
      SET NOCOUNT OFF;

END

GO




Por que hacer store procedure para hacer los llamados a base de datos. Supongamos que por algún motivo necesitamos saber qué fecha fue modificado un producto. Por desgracia la tabla ya fue creada y nuestro programa ya está utilizando. Algo como lo siguiente:

            string connectionString = "connection Settings";
            using (var conn = new SqlConnection(connectionString))
            using (var command = new SqlCommand("InsertProduct", conn)
            {
                CommandType = System.Data.CommandType.StoredProcedure
            })
            {
                conn.Open();
                command.Parameters.AddWithValue("@product_id", 1);
                ...
                command.Parameters.AddWithValue("@@product_type", 1);
                command.ExecuteNonQuery();
                conn.Close();
            }

Para nuestra aplicación que está usando el procedimiento almacenado lo que se debe hacer es nada... así es ya que solo se proporciona el nombre y parámetros mientras la interfaz y el numero de parámetros se mantengan igual no hay necesidad de cambiar.

-- Roque Rueda add a column to know when the produc
-- was modified.

ALTER TABLE Product
ADD LastModified DATETIME

Si se agrega la columna lo único que debemos realizar es agregar las sentencias necesarias en nuestro store procedure.
-- ================================================
-- Project Luis Clothes.
-- ================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:        Roque Rueda.

-- Create date: 24/11/2013

-- Description:   Creates a new product record in
--              the database. If you need to inser
--                      a new row you should give a -1
--                      product id(this is the default value)
-- =============================================
ALTER PROCEDURE InsertProduct (
      -- stored procedure params
      @product_id             int = -1,
      @product_name           nvarchar(150),
      @product_price          decimal(10, 2) = 1,
      @product_photo          nvarchar(2083),
      @product_type           int
      )
AS
BEGIN
      -- SET NOCOUNT ON added to prevent extra result sets from
      -- interfering with SELECT statements.
      SET NOCOUNT ON;
     
      -- Update information or insert if not exists
      UPDATE Product SET Name = @product_name,
                                Price = @product_price,
                                Photo = @product_photo,
                                IdType = @product_type,
                                LastModified = GETDATE()
      WHERE Id = @product_id;
      IF @@ROWCOUNT = 0 -- Check if the row was updated.
      INSERT INTO Product (Name,
                                    Price,
                                    Photo,
                                    IdType,
                                    CreationDate)
      VALUES (@product_name, -- Name
                  @product_price, -- Price
                  @product_photo, -- Photo
                  @product_type, -- Typeid from ProductType
                  GETDATE()); -- Gets the current date
                 
      -- Reset SET NONCOUNT
      SET NOCOUNT OFF;

END
GO

Si se dan cuenta no se afectaría en ningún momento el código de la aplicación. Es por eso que en este proyecto vamos a seguir este modelo, aunque en algunos casos no utilicemos un store procedure, tratare de explicarle el por qué no de uso.




jueves, 26 de septiembre de 2013

Creando una aplicación de libreta en Android (parte 2).



Vamos a continuar con la creación de la aplicación libreta usando AndroidStudio. Pueden ver la publicación anterior (http://progrmrmalasmanas.blogspot.mx/2013/07/creando-una-aplicacion-de-libreta-en.html). En la ultima publicación se logro la creación de un archivo de texto así como la lectura del mismo mostrando su contenido en una actividad.
Vamos a crear un método para crear el archivo en la tarjeta sd en lugar de la memoria del teléfono y cambiar el nombre de los métodos que hemos creado; para esto vamos a modificar la clase TextFile agregando esas nuevos metodos.

/*
 * 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");
        }
        fileInputStream.close();
        return content.toString();
    }

}

Vamos a editar nuestra clase para conseguir 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 android.os.Environment;
import android.util.Log;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
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";
    private static final String TAG = "TextFile";
    private static final String DIR = "/textFiles";
    private boolean mExternalStorageAvailable;
    private boolean mExternalStorageWriteable;

    public TextFile(Context ctx) {
        mContext = ctx;

        String state = Environment.getExternalStorageState();

        // We need to know if we can write to external storage
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            // We can read and write the media
            mExternalStorageAvailable = mExternalStorageWriteable = true;
        } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            // We can only read the media
            mExternalStorageAvailable = true;
            mExternalStorageWriteable = false;
        } else {
            // Something else is wrong. It may be one of many other states, but all we need
            //  to know is we can neither read nor write
            mExternalStorageAvailable = mExternalStorageWriteable = false;
        }
    }

    /**
     * Create a file in the device file system.
     * @param name 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 name, String content)
            throws IOException {
        OutputStreamWriter osw = null;
        try
        {
            FileOutputStream fileOutputStream = mContext.openFileOutput(name, Context.MODE_PRIVATE);
            osw = new OutputStreamWriter(fileOutputStream, ENCODING);
            osw.write(content);
            osw.flush();
            Log.w(TAG, String.format("A new file is created named:%s", name));
            return true;
        } finally {
            osw.close();
        }
    }

    /**
     * Creates a file if can in the sd card of this device, otherwise
     * creates the file in the the internal storage.
     * @param name name of the file.
     * @param content content of the file.
     * @return true if the file can be created.
     * @throws IOException if the file can't be created.
     */
    public boolean createSDFile(String name, String content)
            throws IOException {
        // We can write in the sd storage.
        if (mExternalStorageAvailable && mExternalStorageWriteable) {
            OutputStreamWriter osw = null;
            try
            {
                File sdCard = Environment.getExternalStorageDirectory();
                File dir = new File (sdCard.getAbsolutePath() + DIR);
                // Creates a new folder.
                dir.mkdir();
                File file = new File(dir, name);
                FileOutputStream fileOutputStream = new FileOutputStream(file);
                osw = new OutputStreamWriter(fileOutputStream, ENCODING);
                osw.write(content);
                osw.flush();
                Log.w(TAG, String.format("A new file is created named:%s", name));
                return true;
            }
            finally {
                if (osw != null)
                osw.close();
            }
        } else {
            return createFile(name, content);
        }
    }

    /**
     * Reads the contents of a sd card file.
     * @param name name of the file that is going to be read.
     * @return Contents of the file as string.
     * @throws IOException if the file can't be found.
     */
    public String getSDFileContent(String name)
            throws IOException
    {
        if (mExternalStorageAvailable) {
            BufferedReader br = null;
            try {
                File sdCard = Environment.getExternalStorageDirectory();
                File dir = new File (sdCard.getAbsolutePath() + DIR);
                File file = new File(dir, name);
                // This object contains the text will store the content of the file.
                StringBuilder text = new StringBuilder(400);
                br = new BufferedReader(new FileReader(file));
                String line;
                while((line = br.readLine()) != null) {
                    text.append(line).append('\n');
                }
                Log.w(TAG, String.format("File %s is read", name));
                return text.toString();
            } finally {
              if (br != null)
                  br.close();
            }
        }
        else {
            return getFileContent(name);
        }
    }

    /**
     * Read the contents of the file and returns as a string.
     * @param name 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 name)
            throws IOException{
        BufferedReader br = null;
        try {
            StringBuilder content = new StringBuilder(350);
            FileInputStream fileInputStream = mContext.openFileInput(name);
            InputStreamReader isr = new InputStreamReader(fileInputStream, ENCODING);
            br = new BufferedReader(isr);
            String line;
            while ((line = br.readLine()) != null){
                content.append(line).append("\n");
            }
            Log.w(TAG, String.format("File %s is read", name));
            return content.toString();
        } finally {
            if (br != null)
            br.close();
        }
    }

}

Ahora vamos a editar nuestro diseño de interfaz de usuario para permitir crear un nuevo archivo nombrarlo y guardarlo. Una cuestión extra seria poder abrir y visualizar el contenido para su edición si se desea. Vamos a crear un nuevo archivo layout.






Vamos a crear un nuevo elemento al cual vamos a nombrar edit_text.xml en donde vamos a colocar el diseño básico para editar y visualizar el texto.
 










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

<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <EditText
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:id="@+id/text"
            android:inputType="textMultiLine"
            android:layout_gravity="center"
            android:text="@string/app_name"
            android:gravity="left|top"/>
</GridLayout>

Así es como definimos el fragmento. Ahora vamos a indicar las funciones para ese fragmento el cual solo contiene el Widget EditText para que se vea el texto y este pueda ser editado. Ahora ya tenemos la parte visual tenemos que generar la clase que será la que dé el funcionamiento del fragmento de nuestra aplicación.

/*
 * 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.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;

/**
 * This fragment is used to show, edit and save text into a txt file.
 *
 * Created by Roque on 28/07/13.
 */
public class EditTextFragment extends android.support.v4.app.Fragment {

    public static final String ARG_TEXT_FILE = "myTextFile";

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.edit_text, container, false);
        EditText editText = (EditText) rootView.findViewById(R.id.text);

        if (getArguments().containsKey(ARG_TEXT_FILE)){
            editText.setText(getArguments().getString(ARG_TEXT_FILE));
        }

        return rootView;
    }

}
 








Vamos a modificar el método onNavigationItemSelected de nuestra actividad principal NoteActivity.java para que sea algo como lo siguiente:

@Override
    public boolean onNavigationItemSelected(int position, long id) {
        // When the given dropdown item is selected, show its contents in the
        // container view.
        Fragment fragment;
        Bundle args = new Bundle();

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


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

Ejecutamos y en nuestro emulador veremos lo siguiente:












Como pueden ver ya se muestra un Widget para editar el texto del documento ahora en la siguiente parte vamos a ver como almacenar los cambios a nuestro documento de texto y la invocación de los métodos para la escritura del archivo en la tarjeta sd.
En primer lugar vamos a generar una clase con las constantes que estamos utilizando esto con el fin de evitar tener dos veces la misma constante como en el caso de la clase DummySectionFragment y EditTextFragment para evitar acoplamiento entre las clases. Vamos modificar las llamadas a la constante con el siguiente codigo Constants.ARG_TEXT_FILE y nuestra clase quedara como la 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;

/**
 * Contains the constants used in this application.
 *
 * Created by Roque on 19/09/13.
 */
public final class Constants {

    /**
     * This is the constant used to send data between the fragments.
     */
    public static final String ARG_TEXT_FILE = "myTextFile";

    private  Constants ()
    {
        // This is empty.
    }

}

Ahora vamos a proceder a almacenar el texto que edite el usuario cuando presione el menú deseamos que aparezca la opción de guardar. Para esto vamos a navegar a nuestra NoteActivity para poder agregar el elemento al menú. Nuestro menu se encuentra en el archivo res\menu\menu.xml, en este archivo vamos a agregar los elementos que deseamos se muestren cuando se presione el botón de menú. Primero vamos a agregar un nuevo string en nuestro archivo strings.xml

<string name="action_save">Save</string>

Y posteriormente en nuestro archivo menu.xml vamos a cambiar el texto de nuestro elemento en el menu como lo siguiente:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/action_save"
        android:title="@string/action_save"
        android:orderInCategory="100"
        android:showAsAction="never" />
</menu>

En nuestra activity vamos a manejar el evento que se dispara cuando un elemento del menu es seleccionado para esto vamos a agregar el siguiente método a nuestra clase:
@Override
    public boolean onOptionsItemSelected(MenuItem item){
        switch(item.getItemId()){
           
        }

        return true;
    }

Lo que vamos a hacer en este metodo es del elemento del menu que es seleccionado vamos a obtener su id y dependiendo del id es que vamos a realizar alguna acción en este caso guarda los cambios de texto en el archivo. Para esto vamos a generar una interfaz la cual va a ser nuestro contrato para recibir la información desde nuestros fragmentos de la interfaz. Esto implica algunos cambios en nuestras clases DummySectionFragment y EditTextFragment.
/*
 * 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;

/**
 * This interface defines behaviour to get user text input.
 *
 * Created by Roque on 19/09/13.
 */
public interface TextInput {

    /**
     * Returns the input of the user as text.
     * @return user input.
     */
    CharSequence getText();
}

En este caso la única funcionalidad que se define es un método que retorna el texto que ingresa el usuario. Este método debe ser implementado por los fragmentos de los que deseamos obtener texto para almacenarlo en el archivo de texto. Quedando nuestras clases de la siguiente manera:
/**
     * A dummy fragment representing a section of the app, but that simply
     * displays dummy text.
     */
    public static class DummySectionFragment extends Fragment implements TextInput {
        /**
         * The fragment argument representing the section number for this
         * fragment.
         */
        public static final String ARG_SECTION_NUMBER = "section_number";
        private TextView mDummyTextView;

        public DummySectionFragment() {
        }

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

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

            return rootView;
        }

        @Override
        public CharSequence getText() {
            return mDummyTextView.getText();
        }
    }



/*
 * 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.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;

/**
 * This fragment is used to show, edit and save text into a txt file.
 *
 * Created by Roque on 28/07/13.
 */
public class EditTextFragment extends android.support.v4.app.Fragment implements TextInput {


    private EditText mEditText;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.edit_text, container, false);
        mEditText = (EditText) rootView.findViewById(R.id.text);

        if (getArguments().containsKey(Constants.ARG_TEXT_FILE)){
            mEditText.setText(getArguments().getString(Constants.ARG_TEXT_FILE));
        }

        return rootView;
    }

    @Override
    public CharSequence getText() {
        return mEditText.toString();
    }
}

Y nuestra actividad quedara como se muestra a continuación, noten que se llama a la interfaz para obtener el texto del usuario no se llama directamente a la actividad lo cual es posible pero no optamos seguir ese camino.
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;
    private TextInput mTextInput;
    private final static String TAG = "NotePadRoque";

    @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<String>(
                        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.createSDFile("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
     * <code>getThemedContext</code> 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 onOptionsItemSelected(MenuItem item){
        switch(item.getItemId()){

            case R.id.action_save:
                try
                {
                    mTextFile.createSDFile("test.txt", mTextInput.getText().toString());
                }
                catch (IOException ioex)
                {
                    Toast.makeText(this, ioex.getMessage(), Toast.LENGTH_SHORT).show();
                }

                return true;
        }
        return false;
    }
   
    @Override
    public boolean onNavigationItemSelected(int position, long id) {
        // When the given dropdown item is selected, show its contents in the
        // container view.
        Fragment fragment;
        Bundle args = new Bundle();

        switch (position){
            case 0:{
                fragment = new EditTextFragment();
                String content = null;
                try {
                    content = mTextFile.getSDFileContent("test.txt");
                } catch (IOException e) {
                    Log.w(TAG, e.getMessage());
                }
                args.putString(Constants.ARG_TEXT_FILE, content);
                break;
            }
            default:{
                fragment = new DummySectionFragment();
                args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1);
                break;
            }
        }

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

Asi mismo hay que agregar el permiso de escritura externa en nuestro Android manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.roque.rueda.notepad"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="14" />

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".NoteActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Y ahora vamos a ejecutar nuestra aplicacion.