Tecnologías Móviles
clase 9
Ejercicio de la clase anterior
REST API
SERVICE
Ejercicio de la clase anterior
public class UserContract {
public static final String DBNAME = "userDB";
public static final Integer VERSION = 1;
public UserContract() {}
/* Inner class that defines the table contents */
public static abstract class UserTable implements BaseColumns {
public static final String TABLE_NAME = "user";
public static final String MONGO_ID = "mongo_id";
public static final String FIRSTNAME = "nombre";
public static final String LASTNAME = "apellido";
public static final String MAIL = "mail";
public static final String TABLE_CREATE =
"CREATE TABLE " + TABLE_NAME + " (" +
_ID +" INTEGER PRIMARY KEY, "+
FIRSTNAME + " TEXT, " +
LASTNAME + " TEXT, " +
MAIL + " TEXT, "+
MONGO_ID+" TEXT);";
}
}
UserContract
Ejercicio de la clase anterior
public class UserDBHelper extends SQLiteOpenHelper {
ApiClientService mService;
public static UserDBHelper self=null;
private UserDBHelper(Context context) {
super(context, UserContract.DBNAME, null, UserContract.VERSION);
}
public static UserDBHelper getInstance(Context context) {
if(self == null) {
self = new UserDBHelper(context);
}
return self;
}
public static UserDBHelper getInstance() throws Exception {
if(self == null) throw new Exception("Context no seteado");
return self;
}
public UserDBHelper setService(ApiClientService service) {
mService = service;
return this;
}
...
}
UserDBHelper
Ejercicio de la clase anterior
public class UserDBHelper extends SQLiteOpenHelper {
...
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(UserContract.UserTable.TABLE_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
public UserDBHelper setUsers(JSONArray users) {
this.getWritableDatabase().execSQL("delete from "+UserContract.UserTable.TABLE_NAME);
for(int i=0; i<users.length(); i++) {
try {
doCreate(users.getJSONObject(i));
} catch (JSONException e) {
e.printStackTrace();
}
}
UserAdapter.getInstance().notifyDataSetChanged();
return this;
}
public int count() {
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(
"select * from " +
UserContract.UserTable.TABLE_NAME, null);
return cursor.getCount();
}
...
}
UserDBHelper
Ejercicio de la clase anterior
public class UserDBHelper extends SQLiteOpenHelper {
...
protected void doCreate(JSONObject user) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(UserContract.UserTable.MONGO_ID, user.optString("_id"));
values.put(UserContract.UserTable.FIRSTNAME, user.optString("nombre"));
values.put(UserContract.UserTable.LASTNAME, user.optString("apellido"));
values.put(UserContract.UserTable.MAIL, user.optString("mail"));
db.insert(UserContract.UserTable.TABLE_NAME, null, values);
}
public UserDBHelper create(JSONObject user) {
doCreate(user);
UserAdapter.getInstance().notifyDataSetChanged();
if(mService != null) {
mService.mBinder.addUser(user);
}
return this;
}
...
}
UserDBHelper
Ejercicio de la clase anterior
public class UserDBHelper extends SQLiteOpenHelper {
...
public UserDBHelper delete(JSONObject user) {
SQLiteDatabase db = this.getWritableDatabase();
String selection = UserContract.UserTable._ID+" = ?";
String[] args = {user.optString("_id")};
db.delete(UserContract.UserTable.TABLE_NAME, selection, args);
UserAdapter.getInstance().notifyDataSetChanged();
if(mService != null) {
try {
user.put("_id", user.getString(UserContract.UserTable.MONGO_ID));
user.remove("mongo_id");
mService.mBinder.rmUser(user);
} catch (JSONException e) {
e.printStackTrace();
}
}
return this;
}
...
}
UserDBHelper
Ejercicio de la clase anterior
public class UserDBHelper extends SQLiteOpenHelper {
...
public UserDBHelper update(JSONObject user) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(UserContract.UserTable.FIRSTNAME, user.optString("nombre"));
values.put(UserContract.UserTable.LASTNAME, user.optString("apellido"));
values.put(UserContract.UserTable.MAIL, user.optString("mail"));
String selection = UserContract.UserTable._ID + " = ?";
String[] args = {user.optString("_id")};
db.update(UserContract.UserTable.TABLE_NAME, values, selection, args);
UserAdapter.getInstance().notifyDataSetChanged();
if(mService != null) {
try {
user.put("_id", user.getString(UserContract.UserTable.MONGO_ID));
user.remove("mongo_id");
mService.mBinder.setUser(user);
} catch (JSONException e) {
e.printStackTrace();
}
}
return this;
}
...
}
UserDBHelper
Ejercicio de la clase anterior
public class UserDBHelper extends SQLiteOpenHelper {
...
protected JSONObject rowToJSON(Cursor cursor) {
JSONObject user = new JSONObject();
try {
user.putOpt("_id", cursor.getLong(cursor.getColumnIndex(UserContract.UserTable._ID)));
user.putOpt("nombre", cursor.getString(cursor.getColumnIndex(UserContract.UserTable.FIRSTNAME)));
user.putOpt("apellido", cursor.getString(cursor.getColumnIndex(UserContract.UserTable.LASTNAME)));
user.putOpt("mail", cursor.getString(cursor.getColumnIndex(UserContract.UserTable.MAIL)));
user.putOpt("mongo_id", cursor.getString(cursor.getColumnIndex(UserContract.UserTable.MONGO_ID)));
} catch (JSONException e) {
e.printStackTrace();
return null;
}
return user;
}
public JSONObject read(Integer pos) {
SQLiteDatabase db = this.getWritableDatabase();
String[] args = {String.valueOf(pos)};
Cursor cursor = db.rawQuery(
"select * from " +
UserContract.UserTable.TABLE_NAME +
" order by " +
UserContract.UserTable.LASTNAME + ", " +
UserContract.UserTable.FIRSTNAME +
" limit 1 offset ? "
, args);
if(cursor.getCount() == 0) {
return null;
}
cursor.moveToFirst();
return rowToJSON(cursor);
}
...
}
UserDBHelper
Ejercicio de la clase anterior
public class UserDBHelper extends SQLiteOpenHelper {
...
public JSONObject get(String id) {
SQLiteDatabase db = this.getWritableDatabase();
String[] args = {String.valueOf(id)};
Cursor cursor = db.rawQuery(
"select * from " +
UserContract.UserTable.TABLE_NAME +
" where "+UserContract.UserTable.MONGO_ID+" = ?", args);
if(cursor.getCount() == 0) {
return null;
}
cursor.moveToFirst();
return rowToJSON(cursor);
}
...
}
UserDBHelper
Ejercicio de la clase anterior
public class ApiClientService extends Service {
...
private UserDBHelper db;
...
pubic void onCreate() {
...
db = UserDBHelper.getInstance(ApiClientService.this).setService(ApiClientService.this);
timer.schedule(new TimerTask() {
@Override
public void run() {
mBinder.resolvePending();
mBinder.findUsers();
}
}, 0, 6000);
}
public class APIBinder extends Binder {
private static final int ADD = 1;
private static final int DEL = 2;
private static final int UPD = 3;
private ArrayList<JSONObject> pending = new ArrayList<JSONObject>();
...
}
...
}
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() {
public void onResult(Object result) {
try {
JSONArray resArray = (JSONArray) result;
if(!mBound) {
int newCount=0;
JSONObject newUser = new JSONObject();
for(int i = 0; i < resArray.length(); i++) {
JSONObject user = resArray.getJSONObject(i);
boolean isNew = true;
if(db.get(user.getString("_id")) == null) {
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());
}
}
db.setUsers(resArray);
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onError(String message) {}
});
}
...
}
...
}
ApiClientService
Ejercicio de la clase anterior
public class ApiClientService extends Service {
...
public class APIBinder extends Binder {
...
public void addUser(final JSONObject usuario) {
final JSONObject pendingUser = usuario;
try {
RestClient.post(mUrl, usuario, new RestClient.Result() {
@Override
public void onResult(Object result) {
findUsers();
}
@Override
public void onError(String message) {
JSONObject payload = new JSONObject();
try {
payload.put("action", ADD);
payload.put("user", pendingUser);
pending.add(payload);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
...
}
...
}
ApiClientService
Ejercicio de la clase anterior
public class ApiClientService extends Service {
...
public class APIBinder extends Binder {
...
public void setUser(JSONObject usuario) {
final JSONObject pendingUser = usuario;
try {
RestClient.put(mUrl + usuario.getString("_id"), usuario, new RestClient.Result() {
public void onResult(Object result) {
findUsers();
}
public void onError(String message) {
JSONObject payload = new JSONObject();
try {
payload.put("action", UPD);
payload.put("user", pendingUser);
pending.add(payload);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
...
}
...
}
ApiClientService
Ejercicio de la clase anterior
public class ApiClientService extends Service {
...
public class APIBinder extends Binder {
...
public void rmUser(JSONObject usuario) {
final JSONObject pendingUser = usuario;
try {
RestClient.delete(mUrl+usuario.getString("_id"), new RestClient.Result() {
@Override
public void onResult(Object result) {
findUsers();
}
@Override
public void onError(String message) {
JSONObject payload = new JSONObject();
try {
payload.put("action", DEL);
payload.put("user", pendingUser);
pending.add(payload);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
} catch (JSONException e) {
e.printStackTrace();
}
}
...
}
...
}
ApiClientService
Ejercicio de la clase anterior
public class ApiClientService extends Service {
...
@Override
public IBinder onBind(Intent intent) {
mBound = true;
mNotificationManager.cancelAll();
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
mBound = false;
return false;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
}
ApiClientService
Ejercicio de la clase anterior
public class UserAdapter extends BaseAdapter {
...
UserDBHelper mDB;
public void setContext(MainActivity context) {
mContext = context;
mDB = UserDBHelper.getInstance(context);
}
public int getCount() {
return mDB.count();
}
public JSONObject getItem(int position) {
return mDB.read(position);
}
public View getView(final int position, View convertView, ViewGroup parent) {
...
delete.setOnClickListener(new View.OnClickListener() {
...
mDB.delete(getItem(position));
...
});
...
}
}
UserAdapter
Ejercicio de la clase anterior
public class MainActivity extends AppCompatActivity {
...
UserDBHelper mDB;
ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {}
public void onServiceDisconnected(ComponentName name) {}
};
protected void onCreate(Bundle savedInstanceState) {
...
mDB = UserDBHelper.getInstance(this);
...
}
public void setUser(JSONObject user, Integer pos) {
if(user != null) {
if (pos == null) mDB.create(user);
else mDB.update(user);
}
...
}
...
}
MainActivity
Persistencia
Exiten 5 formas de guardar datos en forma persistente:
-
Conexión a la Red.
-
Internal Storage.
-
External Storage.
-
SQLite Database.
- Shared Preferences.
Persistencia - Shared Preferences
Permite guardar y obtener, en forma persistente, pares de clave-valor de tipos de datos primitivos.
Una aplicación puede obtener un objeto SharedPreferences a través de 2 métodos:
- getSharedPreferences(): Se utiliza si hay varios archivos de preferencias identifcados por nombre.
- getPreferences(): El activity tiene un solo archivo de preferencias.
Persistencia - Shared Preferences
protected void onCreate(Bundle state){
super.onCreate(state);
. . .
// Restore preferences
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
boolean silent = settings.getBoolean("silentMode", false);
setSilent(silent);
}
protected void onStop(){
super.onStop();
// We need an Editor object to make preference changes.
// All objects are from android.context.Context
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("silentMode", mSilentMode);
// Commit the edits!
editor.commit();
}
Settings
Una aplicación puede proveer configuraciones que definen el comportamiento de la misma. Dichas configuraciones persisten a través de SharedPreferences
La interfaz de las configuraciones de la aplicación se construye utilizando objetos Preferences, se debe utilizar una clase especial de Activity (PreferenceActivity) para API menor a 11 o Fragment (PreferenceFragment).
Utilizando PreferenceFragment o PreferenceActivity, la estructura de las preferencias se definen en un xml especial, y no es necesario crear un layout para ello.
El archivo se carga a través del método addPreferencesFromResource()
Settings
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="@string/pref_sms_storage_title"
android:key="pref_key_storage_settings">
<CheckBoxPreference
android:key="pref_key_auto_delete"
android:summary="@string/pref_summary_auto_delete"
android:title="@string/pref_title_auto_delete"
android:defaultValue="false"... />
<Preference
android:key="pref_key_sms_delete_limit"
android:dependency="pref_key_auto_delete"
android:summary="@string/pref_summary_delete_limit"
android:title="@string/pref_title_sms_delete"... />
<Preference
android:key="pref_key_mms_delete_limit"
android:dependency="pref_key_auto_delete"
android:summary="@string/pref_summary_delete_limit"
android:title="@string/pref_title_mms_delete" ... />
</PreferenceCategory>
...
</PreferenceScreen>
res/xml/settings.xml
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
}
Settings
Tipos de Preferences
- CheckBoxPreference
- EditTextPreference
- ListPreference
- MultiSelectListPreference
- SwitchPreference
Agrupado de Preferences se puede realizar a través de PreferenceCategory.
Sub pantallas de preferencias se pueden armar anidando elementos PreferenceScreen.
Ejercicio
Basado en el ejercicio de la clase anterior, crear un PreferenceFragment que contenga las siguientes preferencias:
- Intervalo, en segundos, en el cual se debe preguntar a la API por nuevos usuarios
- URL a donde se deben realizar los llamados a la API.
Tecnologías Móviles - Clase 9
By Agustin Moyano
Tecnologías Móviles - Clase 9
- 617