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