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:
-
Conexión a la Red.
-
Internal Storage.
-
External Storage.
-
SQLite Database.
- 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:
- El adapter de la lista de usuarios debe realizar todas las operaciones de usuarios contra un SQLite (myDB).
- Si la aplicación está online:
- 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/).
- Cuando se produce un cambio en myDB desde la API, se debe notificar al listado de usuarios.
- Si la aplicación está offline:
- Toda operación que se realice en la base de datos se debe guardar en un archivo.
- 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