Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Developing a Fan Made Version Of My University's App

Developing a Fan Made Version Of My University's App

(Spanish version / versión en español)

Bruno Aybar

May 31, 2017
Tweet

More Decks by Bruno Aybar

Other Decks in Programming

Transcript

  1. Developing a Fan Made Version Of My University’s App Bruno

    Aybar
 @brunoaybarg https://medium.com/@bruno.aybar/developing-a-fan-made-version-of-my-universitys-app-9eec3baafcd3
  2. Problemas • Ya no se podía ver el horario de

    clases • No se guardaba la sesión, ni había una opción de guardar credenciales • Muy lenta. Cualquier acción hacía que el app recargue por completo • La navegación era muy complicada
  3. Phase 1: The Dirty Work • Ingeniería inversa: decompilación del

    APK
 http://www.javadecompilers.com/apk

  4. Phase 1: The Dirty Work • Ingeniería inversa: decompilación del

    APK
 http://www.javadecompilers.com/apk

  5. Phase 1: The Dirty Work • Web services descubiertos: @POST("Autenticarp2")


    Observable<LoginResponse> login(..);
 
 @GET("Horario/")
 Observable<TimetableResponse> getTimeTable(..); @GET("CursoAlumno/")
 Observable<CourseListResponse> getCourses(..); @GET("Nota/")
 Observable<CourseResponse> getCourseDetail(..); @GET("Inasistencia/")
 Observable<AbsencesResponse> getAbsences(..); @GET("Companeros/")
 Observable<ClassmatesResponse> getClassmates(..); @GET("PagoPendiente/")
 Observable<PaymentsResponse> getPayments(..); @GET("RecursosDisponible/")
 Observable<ReserveAvailabilityResponse> getReservesAvailability(..); @GET("Reservar/")
 Observable<ReserveResponse> reserveResource(..);
  6. Phase 1: The Dirty Work • Web services descubiertos: @POST("Autenticarp2")


    Observable<LoginResponse> login(..);
 
 @GET("Horario/")
 Observable<TimetableResponse> getTimeTable(..); @GET("CursoAlumno/")
 Observable<CourseListResponse> getCourses(..); @GET("Nota/")
 Observable<CourseResponse> getCourseDetail(..); @GET("Inasistencia/")
 Observable<AbsencesResponse> getAbsences(..); @GET("Companeros/")
 Observable<ClassmatesResponse> getClassmates(..); @GET("PagoPendiente/")
 Observable<PaymentsResponse> getPayments(..); @GET("RecursosDisponible/")
 Observable<ReserveAvailabilityResponse> getReservesAvailability(..); @GET("Reservar/")
 Observable<ReserveResponse> reserveResource(..);
  7. Phase 1: The Dirty Work • Web services descubiertos: @POST("Autenticarp2")


    Observable<LoginResponse> login(..);
 
 @GET("Horario/")
 Observable<TimetableResponse> getTimeTable(..); @GET("CursoAlumno/")
 Observable<CourseListResponse> getCourses(..); @GET("Nota/")
 Observable<CourseResponse> getCourseDetail(..); @GET("Inasistencia/")
 Observable<AbsencesResponse> getAbsences(..); @GET("Companeros/")
 Observable<ClassmatesResponse> getClassmates(..); @GET("PagoPendiente/")
 Observable<PaymentsResponse> getPayments(..); @GET("RecursosDisponible/")
 Observable<ReserveAvailabilityResponse> getReservesAvailability(..); @GET("Reservar/")
 Observable<ReserveResponse> reserveResource(..);
  8. Phase 1: The Dirty Work • Web services descubiertos: @POST("Autenticarp2")


    Observable<LoginResponse> login(..);
 
 @GET("Horario/")
 Observable<TimetableResponse> getTimeTable(..); @GET("CursoAlumno/")
 Observable<CourseListResponse> getCourses(..); @GET("Nota/")
 Observable<CourseResponse> getCourseDetail(..); @GET("Inasistencia/")
 Observable<AbsencesResponse> getAbsences(..); @GET("Companeros/")
 Observable<ClassmatesResponse> getClassmates(..); @GET("PagoPendiente/")
 Observable<PaymentsResponse> getPayments(..); @GET("RecursosDisponible/")
 Observable<ReserveAvailabilityResponse> getReservesAvailability(..); @GET("Reservar/")
 Observable<ReserveResponse> reserveResource(..);
  9. Phase 1: The Dirty Work • Web services descubiertos: @POST("Autenticarp2")


    Observable<LoginResponse> login(..);
 
 @GET("Horario/")
 Observable<TimetableResponse> getTimeTable(..); @GET("CursoAlumno/")
 Observable<CourseListResponse> getCourses(..); @GET("Nota/")
 Observable<CourseResponse> getCourseDetail(..); @GET("Inasistencia/")
 Observable<AbsencesResponse> getAbsences(..); @GET("Companeros/")
 Observable<ClassmatesResponse> getClassmates(..); @GET("PagoPendiente/")
 Observable<PaymentsResponse> getPayments(..); @GET("RecursosDisponible/")
 Observable<ReserveAvailabilityResponse> getReservesAvailability(..); @GET("Reservar/")
 Observable<ReserveResponse> reserveResource(..);
  10. Phase 1: The Dirty Work • Web services descubiertos: @POST("Autenticarp2")


    Observable<LoginResponse> login(..);
 
 @GET("Horario/")
 Observable<TimetableResponse> getTimeTable(..); @GET("CursoAlumno/")
 Observable<CourseListResponse> getCourses(..); @GET("Nota/")
 Observable<CourseResponse> getCourseDetail(..); @GET("Inasistencia/")
 Observable<AbsencesResponse> getAbsences(..); @GET("Companeros/")
 Observable<ClassmatesResponse> getClassmates(..); @GET("PagoPendiente/")
 Observable<PaymentsResponse> getPayments(..); @GET("RecursosDisponible/")
 Observable<ReserveAvailabilityResponse> getReservesAvailability(..); @GET("Reservar/")
 Observable<ReserveResponse> reserveResource(..);
  11. Phase 1: The Dirty Work • Web services descubiertos: @POST("Autenticarp2")


    Observable<LoginResponse> login(..);
 
 @GET("Horario/")
 Observable<TimetableResponse> getTimeTable(..); @GET("CursoAlumno/")
 Observable<CourseListResponse> getCourses(..); @GET("Nota/")
 Observable<CourseResponse> getCourseDetail(..); @GET("Inasistencia/")
 Observable<AbsencesResponse> getAbsences(..); @GET("Companeros/")
 Observable<ClassmatesResponse> getClassmates(..); @GET("PagoPendiente/")
 Observable<PaymentsResponse> getPayments(..); @GET("RecursosDisponible/")
 Observable<ReserveAvailabilityResponse> getReservesAvailability(..); @GET("Reservar/")
 Observable<ReserveResponse> reserveResource(..);
  12. Phase 1: The Dirty Work • Web services descubiertos: @POST("Autenticarp2")


    Observable<LoginResponse> login(..);
 
 @GET("Horario/")
 Observable<TimetableResponse> getTimeTable(..); @GET("CursoAlumno/")
 Observable<CourseListResponse> getCourses(..); @GET("Nota/")
 Observable<CourseResponse> getCourseDetail(..); @GET("Inasistencia/")
 Observable<AbsencesResponse> getAbsences(..); @GET("Companeros/")
 Observable<ClassmatesResponse> getClassmates(..); @GET("PagoPendiente/")
 Observable<PaymentsResponse> getPayments(..); @GET("RecursosDisponible/")
 Observable<ReserveAvailabilityResponse> getReservesAvailability(..); @GET("Reservar/")
 Observable<ReserveResponse> reserveResource(..);
  13. Phase 1: The Dirty Work • Web services descubiertos: @POST("Autenticarp2")


    Observable<LoginResponse> login(..);
 
 @GET("Horario/")
 Observable<TimetableResponse> getTimeTable(..); @GET("CursoAlumno/")
 Observable<CourseListResponse> getCourses(..); @GET("Nota/")
 Observable<CourseResponse> getCourseDetail(..); @GET("Inasistencia/")
 Observable<AbsencesResponse> getAbsences(..); @GET("Companeros/")
 Observable<ClassmatesResponse> getClassmates(..); @GET("PagoPendiente/")
 Observable<PaymentsResponse> getPayments(..); @GET("RecursosDisponible/")
 Observable<ReserveAvailabilityResponse> getReservesAvailability(..); @GET("Reservar/")
 Observable<ReserveResponse> reserveResource(..);
  14. Phase 1: The Dirty Work • Web services descubiertos: @POST("Autenticarp2")


    Observable<LoginResponse> login(..);
 
 @GET("Horario/")
 Observable<TimetableResponse> getTimeTable(..); @GET("CursoAlumno/")
 Observable<CourseListResponse> getCourses(..); @GET("Nota/")
 Observable<CourseResponse> getCourseDetail(..); @GET("Inasistencia/")
 Observable<AbsencesResponse> getAbsences(..); @GET("Companeros/")
 Observable<ClassmatesResponse> getClassmates(..); @GET("PagoPendiente/")
 Observable<PaymentsResponse> getPayments(..); @GET("RecursosDisponible/")
 Observable<ReserveAvailabilityResponse> getReservesAvailability(..); @GET("Reservar/")
 Observable<ReserveResponse> reserveResource(..);
  15. Phase 1: The Dirty Work • Es ético? • Es

    legal? • Me puedo ir preso?
  16. Phase 1: The Dirty Work • “Guía de derecho de

    Autor para Creadores de Software”
 INDECOPI
 
 https:// www.indecopi.gob.pe/ documents/20182/143803/ GDA_CreadoresDeSoftwar e.pdf
  17. Phase 2: Defining the Scope • Historias de usuario
 


    
 Como (rol), quiero (algo), para (beneficio)
  18. Como estudiante, quiero ver mi horario semanal, para saber cuándo

    y donde serán mis clases. Phase 2: Defining the Scope
  19. Como estudiante, quiero ver mi historial de asistencias, para evitar

    caer en DPI (jalar por faltas). Phase 2: Defining the Scope
  20. Phase 4: Work In Progress • Hora de codear: •

    Extrañaba programar • Aprender y experimentar!
  21. Retrofit interface UpcServiceInterface { @POST("Autenticarp2")
 Observable<LoginResponse> login(..);
 
 @GET("Horario/")
 Observable<TimetableResponse>

    getTimeTable(..); @GET("CursoAlumno/")
 Observable<CourseListResponse> getCourses(..); @GET("Nota/")
 Observable<CourseResponse> getCourseDetail(..); @GET("Inasistencia/")
 Observable<AbsencesResponse> getAbsences(..); @GET("Companeros/")
 Observable<ClassmatesResponse> getClassmates(..); @GET("PagoPendiente/")
 Observable<PaymentsResponse> getPayments(..); @GET("RecursosDisponible/")
 Observable<ReserveAvailabilityResponse> getReservesAvailability(..); @GET("Reservar/")
 Observable<ReserveResponse> reserveResource(..); }
  22. RxJava (1.x) interface UpcServiceInterface { @POST("Autenticarp2")
 Observable<LoginResponse> login(..);
 
 @GET("Horario/")


    Observable<TimetableResponse> getTimeTable(..); @GET("CursoAlumno/")
 Observable<CourseListResponse> getCourses(..); @GET("Nota/")
 Observable<CourseResponse> getCourseDetail(..); @GET("Inasistencia/")
 Observable<AbsencesResponse> getAbsences(..); @GET("Companeros/")
 Observable<ClassmatesResponse> getClassmates(..); @GET("PagoPendiente/")
 Observable<PaymentsResponse> getPayments(..); @GET("RecursosDisponible/")
 Observable<ReserveAvailabilityResponse> getReservesAvailability(..); @GET("Reservar/")
 Observable<ReserveResponse> reserveResource(..); }
  23. MVVM public interface UserRepository {
 Observable<Timetable> getTimeTable();
 Observable<List<Course>> getCourses();
 Observable<Course>

    getCourseDetail();
 Observable<List<Absence>> getAbsences();
 Observable<List<Classmate>> getClassmates();
 }
  24. MVVM class ReserveViewModel { //El ViewModel expone data relevante para

    la vista, haciendo uso del DataModel
 fun getReserveEntries() : Observable<List<DisplayableReserveFilter>>{} 
 fun getReserveEnabledStream() : Observable<Boolean>{} 
 fun getReserveOptions(): Observable<List<DisplayableReserveOption>>{}
 
 fun updatedEntry(entries: List<DisplayableReserveFilter>, position: Int){} 
 fun applyFilters(filters: List<DisplayableReserveFilter>): Observable<String>{}
 
 fun selectedReserveOption(options: List<DisplayableReserveOption>, selected: Int){} }
  25. MVVM public class CoursesFragment extends BaseFragment { //View related stuff

    //. . . //. . . 
 @Override
 protected void bind() {
 super.bind();
 
 mSubscription.add(mViewModel.getCourseDetails()
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(this::showCourseDetail,this::displayError));
 }
 }

  26. android { // // setup… // productFlavors { prod {

    buildConfigField 'String', 'REST_URL', ‘“ << aquí estaba la url >>"' } } // // setup… // } build.gradle
  27. android { ... productFlavors { prod { def propsFile =

    rootProject.file('appconfig.properties') if(propsFile.exists()){ def props = new Properties() props.load(new FileInputStream(propsFile)) buildConfigField 'String', 'REST_URL', props["UPC_REST_URL"] } } } ... } https://github.com/Bruno125/Unofficial-Ups/blob/master/app/build.gradle