Tecnologías Móviles
clase 12
Ejercicio de la clase anterior
Agregar Tabs
Mostrar Mensajes
Mostrar Chats
Ejercicio de la clase anterior
public class ApiClientService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener {
...
protected void setEmail() {
mEmail = mPreferences.getString("email", "amoyano@iua.edu.ar");
mBinder.login();
}
public void onCreate() {
...
setEmail();
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
...
if (key.equals("email")) {
setEmail();
}
}
...
}
ApiClientService
Ejercicio de la clase anterior
public class ApiClientService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener {
...
public class APIBinder extends Binder {
...
public void login() {
JSONObject data = new JSONObject();
try {
data.putOpt("mail", mEmail);
RestClient.post(mUrl + "/login", data, new RestClient.Result() {
@Override
public void onResult(Object result) {
mLoggedIn=true;
db.setCurrentUser((JSONObject) result);
findUsers();
findChats();
}
@Override
public void onError(String message) {
mLoggedIn=false;
}
});
} catch (JSONException e) {
mLoggedIn=false;
e.printStackTrace();
} catch (IOException e) {
mLoggedIn=false;
e.printStackTrace();
}
}
...
}
...
}
ApiClientService
Ejercicio de la clase anterior
public class ApiClientService extends Service implements
SharedPreferences.OnSharedPreferenceChangeListener {
...
public class APIBinder extends Binder {
...
public void findChats(final RestClient.Result handler) {
RestClient.get(mUrl + "chat/", new RestClient.Result() {
@Override
public void onResult(Object result) {
JSONArray resArray = (JSONArray) result;
db.setChats(resArray);
for(int i = 0; i < resArray.length(); i++) {
JSONObject chat = null;
try {
chat = resArray.getJSONObject(i);
findMsgs(chat.getString("_id"));
} catch (JSONException e) {
e.printStackTrace();
}
}
if(handler != null) handler.onResult(null);
}
@Override
public void onError(String message) {}
});
}
...
}
...
}
ApiClientService
Ejercicio de la clase anterior
public class ApiClientService extends Service implements
SharedPreferences.OnSharedPreferenceChangeListener {
...
public class APIBinder extends Binder {
...
public void findMsgs(final String chatId) { ... }
public void findUsers() { ... }
public void addChat(final JSONObject chat, final RestClient.Result handler) { ... }
public void addMsg(final String chatId, final JSONObject msg) { ... }
public void addUser(final JSONObject usuario) { ... }
public void setUser(JSONObject usuario) { ... }
public void rmUser(JSONObject usuario) { ... }
...
}
...
}
ApiClientService
Ejercicio de la clase anterior
public class UserContract {
...
public class ChatTable implements BaseColumns {
public static final String TABLE_NAME = "chat";
public static final String MONGO_ID = "mongo_id";
public static final String TO = "toUser";
public static final String DATE = "date";
public static final String MSG = "msg";
public static final String FROM = "fromUser";
public static final String TABLE_CREATE =
"CREATE TABLE " + TABLE_NAME + " (" +
...
}
public class MsgTable implements BaseColumns {
public static final String TABLE_NAME = "msg";
public static final String MONGO_ID = "mongo_id";
public static final String MSG = "msg";
public static final String DATE = "date";
public static final String CHAT = "chat";
public static final String FROM = "fromUser";
public static final String TABLE_CREATE =
"CREATE TABLE " + TABLE_NAME + " (" +
...
}
}
UserContract
Ejercicio de la clase anterior
public class UserDBHelper extends SQLiteOpenHelper {
...
public void setCurrentUser(JSONObject user) {
try {
mCurrentUser = user.getString("_id");
mPreferences.edit().putString("current-user", mCurrentUser).commit();
} catch (JSONException e) {
e.printStackTrace();
}
}
public String getCurrentUser() { ... }
public JSONObject getChat(String id) { ... }
public JSONObject getChatByUser(String id) { ... }
private JSONObject chatRowToJSON(Cursor cursor) { ... }
public UserDBHelper setChats(JSONArray chats) { ... }
private void doCreateChat(JSONObject chat) { ... }
public UserDBHelper createChat(JSONObject chat, RestClient.Result handler) { ... }
public int countChat() { ... }
public JSONObject readChat(Integer pos) { ... }
public UserDBHelper setMsgs(String chatId, JSONArray msgs) { ... }
private void doCreateMsg(String chatId, JSONObject msg) { ... }
public int countMsg(String chatId) { ... }
public JSONObject readMsg(String chatId, int position) { ... }
private JSONObject msgRowToJSON(Cursor cursor) { ... }
public UserDBHelper createMsg(String chatId, JSONObject msg) { ... }
}
UserDBHelper
Ejercicio de la clase anterior
public class ListFragment extends Fragment {
...
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
...
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final String uid = adapter.getItem(position).optString("mongo_id");
JSONObject chat = mDB.getChatByUser(uid);
if(chat != null) {
main.openMsgs(chat.optString("mongo_id"));
} else {
RestClient.Result handler = new RestClient.Result() {
@Override
public void onResult(Object result) {
JSONObject chat = mDB.getChatByUser(uid);
main.openMsgs(chat.optString("mongo_id"));
}
@Override
public void onError(String message) {
Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT);
}
};
JSONObject newChat = new JSONObject();
try {
newChat.put("to", uid);
mDB.createChat(newChat, handler);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
});
...
}
}
ListFragment
Ejercicio de la clase anterior
public class ChatFragment extends Fragment {
MainActivity main;
public ChatFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
main = (MainActivity) getActivity();
View root = inflater.inflate(R.layout.fragment_chat, container, false);
ListView chats = (ListView) root.findViewById(R.id.chatList);
chats.setAdapter(ChatAdapter.getInstance(main));
chats.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
JSONObject chat = ChatAdapter.getInstance().getItem(position);
try {
main.openMsgs(chat.getString("mongo_id"));
} catch (JSONException e) {
e.printStackTrace();
}
}
});
return root;
}
}
ChatFragment
Ejercicio de la clase anterior
public class MainActivity extends AppCompatActivity {
...
public void openMsgs(String chatId) {
MsgFragment msg = new MsgFragment();
Bundle args = new Bundle();
args.putString("chatId", chatId);
msg.setArguments(args);
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.container, msg);
transaction.addToBackStack("messages");
transaction.commit();
}
...
}
MainActivity
Ejercicio de la clase anterior
public class MsgFragment extends Fragment {
...
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
MainActivity main = (MainActivity) getActivity();
Bundle args = getArguments();
final String chatId = args.getString("chatId");
View root = inflater.inflate(R.layout.fragment_msg, container, false);
ListView msgs = (ListView) root.findViewById(R.id.msgList);
msgs.setAdapter(MsgAdapter.getInstance(main, chatId));
final EditText msgText = (EditText) root.findViewById(R.id.msg);
ImageView send = (ImageView) root.findViewById(R.id.send);
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
UserDBHelper mDB = UserDBHelper.getInstance(getActivity());
JSONObject msg = new JSONObject();
try {
msg.put("chat", chatId);
msg.put("from", mDB.getCurrentUser());
msg.put("message", msgText.getText().toString());
mDB.createMsg(chatId, msg);
msgText.setText("");
} catch (JSONException e) {
e.printStackTrace();
}
}
});
return root;
}
}
MsgFragment
Ejercicio de la clase anterior
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
...
<EditTextPreference
android:defaultValue="amoyano@iua.edu.ar"
android:inputType="textEmailAddress"
android:key="email"
android:title="@string/email_title" />
</PreferenceScreen>
res/xml/settings.xml
public class SettingsFragment extends PreferenceFragmentCompat {
...
public void onCreate(Bundle savedInstanceState) {
...
bindPreferenceSummaryToValue(findPreference("email"));
}
}
SettingsFragment
...
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="@+id/msgList"
android:stackFromBottom="true"
android:transcriptMode="alwaysScroll">
</ListView>
...
res/layout/fragment_msg.xml
WebSockets
Es una tecnología que proporciona un canal de comunicación bidireccional y full-duplex sobre un único socket TCP.
Está diseñada para ser implementada en navegadores y servidores web, pero puede utilizarse por cualquier aplicación cliente/servidor.
Permite la emisión de eventos del lado del servidor.
Una librería que implementa WebSockets para muchas plataformas, incluyendo a Android, es Socket.IO
WebSockets
app/build.gradle
dependencies {
...
compile 'com.github.nkzawa:socket.io-client:0.3.0'
}
AndroidManifest.xml
<!-- app/AndroidManifest.xml -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
...
</manifest>
WebSockets
MainActivity o Fragment
import com.github.nkzawa.socketio.client.IO;
import com.github.nkzawa.socketio.client.Socket;
private Socket mSocket;
{
try {
mSocket = IO.socket("http://chat.socket.io");
} catch (URISyntaxException e) {}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSocket.connect();
}
WebSockets
Emitiendo Eventos
private EditText mInputMessageView;
private void attemptSend() {
String message = mInputMessageView.getText().toString().trim();
if (TextUtils.isEmpty(message)) {
return;
}
mInputMessageView.setText("");
mSocket.emit("new message", message);
}
Escuchando Eventos
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSocket.on("new message", onNewMessage);
mSocket.connect();
}
WebSockets
Listener
private Emitter.Listener onNewMessage = new Emitter.Listener() {
@Override
public void call(final Object.. args) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
JSONObject data = (JSONObject) args[0];
String username;
String message;
try {
username = data.getString("username");
message = data.getString("message");
} catch (JSONException e) {
return;
}
// add the message to view
addMessage(username, message);
}
});
}
};
WebSockets
Desconectar
@Override
public void onDestroy() {
super.onDestroy();
mSocket.disconnect();
mSocket.off("new message", onNewMessage);
}
Ejercicio
Basado en el ejercicio de la clase anterior, realizar los siguientes puntos teniendo en cuenta la base a donde apunta la api (https://iua-tm-api.herokuapp.com/) utilizar los siguientes eventos:
- Eventos Escuchados por el servidor:
- 'post:login' (String mail): Realiza el Login de acuerdo al mail enviado.
- 'get:user' (JSONObject query): Realiza una búsqueda de usuarios de acuerdo al criterio especificado (query).
- 'get:chat' (): Realiza la búsqueda de chats a los cuales pertenece el usuario logueado.
- 'post:chat' (String to): Inserta un nuevo chat, y pone como participante al usuario identificado por su id (to).
- 'post:message' (String chatId, String msg): Inserta el mensaje "msg" en el chat "chatId".
- 'get:message' (String chatId): Realiza la búsqueda de todos los mensajes del chat "chatId".
- 'post:user' (JSONObject data): Crea un nuevo usuario.
Ejercicio
- Eventos Escuchados por el Servidor:
- 'put:user' (JSONObject data): Modifica el usuario actual.
- 'delete:user' (): Elimina el usuario actual.
- Eventos Emitidos por el Servidor:
- 'api:error' (String err): Devuelve un String con el error.
- 'post:login' (JSONObject user): Respuesta al evento post:login.
- 'get:user' (JSONArray users): Respuesta al evento get:user.
- 'get:chat' (JSONArray chats): Respuesta al evento get:chat.
- 'post:chat' (JSONObject chat): Respuesta al evento post:chat.
- 'post:message' (JSONObject msg): Respuesta al evento post:message.
- 'get:message' (JSONArray messages): Respuesta al evento get:message.
- 'post:user', (String insertedId): Respuesta al evento post:user.
- 'put:user', (String updatedId): Respuesta al evento put:user.
Ejercicio
- El fragment del chat debería contener un EditText en donde agrego el mensaje, y un botón "enviar" para agregar mensajes al chat (POST /chat/<id de chat>/message con {"message": "<texto del mensaje>"} como body)
Tecnologías Móviles - Clase 12
By Agustin Moyano
Tecnologías Móviles - Clase 12
- 752