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:

 

  1. Conexión a la Red.
     
  2. Internal Storage.
     
  3. External Storage.
     
  4. SQLite Database.
     
  5. 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