Tecnologías Móviles

clase 8

Ejercicio de la clase anterior

REST API

 

 

 

 

 

SERVICE

 

 

 

 

 

 

Ejercicio de la clase anterior

public class ApiClientService extends Service {
    ...
    int MAIN_ACTIVITY_REQUEST = 1;
    private boolean mBound;
    private NotificationManager mNotificationManager;
    private NotificationCompat.Builder mBuilder;
    private static String usersFile = "users.json";

    public void onCreate() {
        RestClient.setContext(this);
        mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        Intent i = new Intent(ApiClientService.this, MainActivity.class);
        PendingIntent pi = PendingIntent.getActivity(ApiClientService.this, MAIN_ACTIVITY_REQUEST, 
                                                                i, PendingIntent.FLAG_UPDATE_CURRENT);
        mBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(android.R.drawable.stat_notify_sync)
                .setContentTitle(getString(R.string.newUser))
                .setContentIntent(pi);
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                mBinder.findUsers();
            }
        }, 0, 6000);
    }

    public void onDestroy() {
        timer.cancel();
    }
    ...
}

ApiClientService

Ejercicio de la clase anterior

public class ApiClientService extends Service {
    ...
    public class APIBinder extends Binder {
        ...
        public void findUsers() {
            RestClient.get(mUrl, new RestClient.Result() {
                @Override
                public void onResult(Object result) {
                    try {
                        JSONArray resArray = (JSONArray) result;
                        if(mBound) {
                            UserAdapter.getInstance().setUsers(resArray);
                        } else {
                            int newCount=0;
                            JSONObject newUser = new JSONObject();
                            FileInputStream fis = openFileInput(usersFile);
                            JSONArray usersState = new JSONArray(IOUtils.toString(fis));
                            for(int i = 0; i < resArray.length(); i++) {
                                JSONObject user = resArray.getJSONObject(i);
                                boolean isNew = true;
                                for(int j = 0; j < usersState.length(); j++) {
                                    if(user.getString("_id").equals(
                                            usersState.getJSONObject(j).getString("_id"))) {
                                        isNew = false;
                                        break;
                                    }
                                }
                                if(isNew) {
                                    newCount++;
                                    newUser = user;
                                }
                            }

ApiClientService

Ejercicio de la clase anterior

public class ApiClientService extends Service {
    ...
    public class APIBinder extends Binder {
        ...
        public void findUsers() {
            RestClient.get(mUrl, new RestClient.Result() {
                @Override
                public void onResult(Object result) {
                    ...
                            if(newCount > 0) {
                                if(newCount==1) {
                                    mBuilder.setContentText(
                                        newUser.getString("nombre")+" "+newUser.getString("apellido"));
                                } else {
                                    mBuilder.setContentText(newCount+" "+getString(R.string.newUsers));
                                }
                                mNotificationManager.notify(1, mBuilder.build());
                            }
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
    ...
}

ApiClientService

Ejercicio de la clase anterior

public class ApiClientService extends Service {
    ...
    public IBinder onBind(Intent intent) {
        mBound = true;
        mNotificationManager.cancelAll();
        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        try {
            FileOutputStream fos = openFileOutput(usersFile, MODE_PRIVATE);
            fos.write(UserAdapter.getInstance().getUsers().toString().getBytes());
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        mBound = false;
        return false;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }
}

ApiClientService

Persistencia

Exiten 5 formas de guardar datos en forma persistente:

 

  1. Conexión a la Red.
     
  2. Internal Storage.
     
  3. External Storage.
     
  4. SQLite Database.
     
  5. Shared Preferences.

Persistencia - Internal Storage

String FILENAME = "hello_file";
String string = "hello world!";

FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();

FileInputStream fis = openFileInput(FILENAME);
String contents = IOUtils.toString(fis);
fis.close();

//Contents: hello world!
Log.d("INT STORAGE", "Contents: "+contents);

Persistencia - External Storage

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

1. AndroidManifest

/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;
}

/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state) ||
        Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
        return true;
    }
    return false;
}

2. Chequear si se puede leer o escribir

Persistencia - External Storage

public File getAlbumStorageDir(String albumName) {
    // Get the directory for the user's public pictures directory.
    File file = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES), albumName);
    if (!file.mkdirs()) {
        Log.e(LOG_TAG, "Directory not created");
    }
    return file;
}

3. Escribir en External Storage

Persistencia - SQLite Database

public final class FeedReaderContract {
    // To prevent someone from accidentally instantiating the contract class,
    // give it an empty constructor.
    public FeedReaderContract() {}
    public static final String V1_ALTER_ENTRY_TABLE = 
        "alter table "+FeedEntry.TABLE_NAME +
        " add column "+FeedEntry.COLUMN_NAME_SUBTITLE + " TEXT";

    /* Inner class that defines the table contents */
    public static abstract class FeedEntry implements BaseColumns {
        public static final String TABLE_NAME = "entry";
        public static final String COLUMN_NAME_ENTRY_ID = "entryid";
        public static final String COLUMN_NAME_TITLE = "title";
        public static final String COLUMN_NAME_SUBTITLE = "subtitle";
        public static final String TABLE_CREATE =
                "CREATE TABLE " + TABLE_NAME + " (" +
                COLUMN_NAME_ENTRY_ID + " TEXT, " +
                COLUMN_NAME_TITLE + " TEXT, " +
                COLUMN_NAME_SUBTITLE + " TEXT);";

        ...
    }
}

1.Definir el esquema

Persistencia - SQLite Database

public class MyDBOpenHelper extends SQLiteOpenHelper {

    private static final int DATABASE_VERSION = 2;
    private static final String DATABASE_NAME = "mydb";

    MyDBOpenHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(FeedEntry.TABLE_CREATE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        if(oldVersion = 1) {
            db.execSQL(FeedReaderContract.V1_ALTER_ENTRY_TABLE);
        }
    }
}

2. Extender SQLiteOpenHelper

Persistencia - SQLite Database

MyDBOpenHelper mDbHelper = new MyDBOpenHelper(getContext());

SQLiteDatabase db = mDbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(FeedEntry.COLUMN_NAME_ENTRY_ID, id);
values.put(FeedEntry.COLUMN_NAME_TITLE, title);
values.put(FeedEntry.COLUMN_NAME_CONTENT, content);

// Insert the new row, returning the primary key value of the new row
long newRowId;
newRowId = db.insert(
         FeedEntry.TABLE_NAME,
         FeedEntry.COLUMN_NAME_NULLABLE,
         values);

3. Utilizar SQLiteOpenHelper

Insert

// Define 'where' part of query.
String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";
// Specify arguments in placeholder order.
String[] selectionArgs = { String.valueOf(rowId) };
// Issue SQL statement.
db.delete(FeedEntry.TABLE_NAME, selection, selectionArgs);

Delete

Persistencia - SQLite Database

String[] projection = {
    FeedEntry._ID,
    FeedEntry.COLUMN_NAME_TITLE,
    FeedEntry.COLUMN_NAME_UPDATED,
    ...
    };

// How you want the results sorted in the resulting Cursor
String sortOrder =
    FeedEntry.COLUMN_NAME_UPDATED + " DESC";

Cursor cursor = db.query(
    FeedEntry.TABLE_NAME,  // The table to query
    projection,                               // The columns to return
    selection,                                // The columns for the WHERE clause
    selectionArgs,                            // The values for the WHERE clause
    null,                                     // don't group the rows
    null,                                     // don't filter by row groups
    sortOrder                                 // The sort order
    );

cursor.moveToFirst();
long itemId = cursor.getLong(
    cursor.getColumnIndexOrThrow(FeedEntry._ID)
);

3. Utilizar SQLiteOpenHelper

Query

Persistencia - SQLite Database

// New value for one column
ContentValues values = new ContentValues();
values.put(FeedEntry.COLUMN_NAME_TITLE, title);

// Which row to update, based on the ID
String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";
String[] selectionArgs = { String.valueOf(rowId) };

int count = db.update(
    FeedReaderDbHelper.FeedEntry.TABLE_NAME,
    values,
    selection,
    selectionArgs);

3. Utilizar SQLiteOpenHelper

Insert

Ejercicio

Basado en el ejercicio de la clase anterior, realizar los siguientes puntos:

  1. El adapter de la lista de usuarios debe realizar todas las operaciones de usuarios contra un SQLite (myDB).
  2. Si la aplicación está online:
    1. Cuando se produce un cambio en myDB desde la aplicación, se debe hacer el llamado correspondiente a la API (http://tm5-agmoyano.rhcloud.com/).
    2. Cuando se produce un cambio en myDB desde la API, se debe notificar al listado de usuarios.
  3. Si la aplicación está offline:
    1. Toda operación que se realice en la base de datos se debe guardar en un archivo.
    2. Cuando el service detecte que el dispositivo está online nuevamente, debe reproducir dichas transacciones contra la API.

Tecnologías Móviles - Clase 8

By Agustin Moyano

Tecnologías Móviles - Clase 8

  • 606