├── .DS_Store ├── .gitignore ├── .idea ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── dictionaries │ └── rodrigogomes.xml ├── encodings.xml ├── gradle.xml ├── jarRepositories.xml ├── misc.xml └── vcs.xml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── google-services.json ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── rodrigmatrix │ │ └── sippa │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-web.png │ ├── java │ │ └── com │ │ │ └── rodrigmatrix │ │ │ └── sippa │ │ │ ├── Adapters │ │ │ ├── ArquivosAdapter.kt │ │ │ ├── DisciplinasAdapter.kt │ │ │ ├── HorasAdapter.kt │ │ │ ├── NotasAdapter.kt │ │ │ ├── NoticiasAdapter.kt │ │ │ └── PlanoAdapter.kt │ │ │ ├── ConnectionDetector.kt │ │ │ ├── DisciplinaActivity.kt │ │ │ ├── Fragments │ │ │ ├── ArquivosFragment.kt │ │ │ ├── DisciplinasFragment.kt │ │ │ ├── HorasFragment.kt │ │ │ ├── InfoFragment.kt │ │ │ ├── NotasFragment.kt │ │ │ ├── NoticiasFragment.kt │ │ │ └── PlanoAulaFragment.kt │ │ │ ├── HomeActivity.kt │ │ │ ├── LoginActivity.kt │ │ │ ├── RemoteConfig.kt │ │ │ ├── Serializer │ │ │ ├── Attendance.kt │ │ │ └── Serializer.kt │ │ │ ├── SippaApp.kt │ │ │ ├── entity │ │ │ ├── Version.kt │ │ │ └── Versions.kt │ │ │ ├── firebase │ │ │ └── FirebaseCloudMessaging.kt │ │ │ ├── persistence │ │ │ ├── Student.kt │ │ │ ├── StudentDao.kt │ │ │ └── StudentsDatabase.kt │ │ │ └── ui │ │ │ └── main │ │ │ ├── PageViewModel.kt │ │ │ ├── PlaceholderFragment.kt │ │ │ └── SectionsPagerAdapter.kt │ └── res │ │ ├── anim │ │ ├── item_animation_fall_down.xml │ │ └── layout_animation_fall_down.xml │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── book_24dp.xml │ │ ├── campus.jpeg │ │ ├── ic_arquivos_24dp.xml │ │ ├── ic_arrow_back_24dp.xml │ │ ├── ic_detalhes_24dp.xml │ │ ├── ic_group_black_24dp.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_notas_24dp.xml │ │ ├── ic_noticias_24dp.xml │ │ ├── ic_person_black_24dp.xml │ │ ├── ic_plano_24dp.xml │ │ ├── ic_refresh_black_24dp.xml │ │ ├── ic_stat_sippa.png │ │ ├── icon_sigaa.png │ │ ├── info_24dp.xml │ │ ├── profile_pic.png │ │ ├── side_nav_bar.xml │ │ └── sippa_logo.png │ │ ├── layout │ │ ├── activity_disciplina.xml │ │ ├── activity_home.xml │ │ ├── activity_login.xml │ │ ├── app_bar_home.xml │ │ ├── arquivo_row.xml │ │ ├── aula_row.xml │ │ ├── content_home.xml │ │ ├── disciplina_row.xml │ │ ├── fragment_arquivos.xml │ │ ├── fragment_disciplina.xml │ │ ├── fragment_disciplinas.xml │ │ ├── fragment_horas.xml │ │ ├── fragment_info.xml │ │ ├── fragment_notas.xml │ │ ├── fragment_noticias.xml │ │ ├── fragment_plano_aula.xml │ │ ├── horas_row.xml │ │ ├── nav_header_home.xml │ │ ├── nota_row.xml │ │ ├── noticia_row.xml │ │ └── plano_row.xml │ │ ├── menu │ │ ├── activity_home_drawer.xml │ │ └── menu_theme.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── values-night │ │ ├── colors.xml │ │ └── styles.xml │ │ ├── values-v27 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── ic_launcher_background.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── rodrigmatrix │ └── sippa │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── keystore └── keystore ├── privacy_policy └── settings.gradle /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /codemr 5 | /.idea/caches 6 | /.idea/libraries 7 | /.idea/modules.xml 8 | /.idea/workspace.xml 9 | /.idea/navEditor.xml 10 | /.idea/assetWizardSettings.xml 11 | .DS_Store 12 | /build 13 | /captures 14 | .externalNativeBuild 15 | .DS_Store 16 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | 11 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | xmlns:android 21 | 22 | ^$ 23 | 24 | 25 | 26 |
27 |
28 | 29 | 30 | 31 | xmlns:.* 32 | 33 | ^$ 34 | 35 | 36 | BY_NAME 37 | 38 |
39 |
40 | 41 | 42 | 43 | .*:id 44 | 45 | http://schemas.android.com/apk/res/android 46 | 47 | 48 | 49 |
50 |
51 | 52 | 53 | 54 | .*:name 55 | 56 | http://schemas.android.com/apk/res/android 57 | 58 | 59 | 60 |
61 |
62 | 63 | 64 | 65 | name 66 | 67 | ^$ 68 | 69 | 70 | 71 |
72 |
73 | 74 | 75 | 76 | style 77 | 78 | ^$ 79 | 80 | 81 | 82 |
83 |
84 | 85 | 86 | 87 | .* 88 | 89 | ^$ 90 | 91 | 92 | BY_NAME 93 | 94 |
95 |
96 | 97 | 98 | 99 | .* 100 | 101 | http://schemas.android.com/apk/res/android 102 | 103 | 104 | ANDROID_ATTRIBUTE_ORDER 105 | 106 |
107 |
108 | 109 | 110 | 111 | .* 112 | 113 | .* 114 | 115 | 116 | BY_NAME 117 | 118 |
119 |
120 |
121 |
122 | 123 | 125 |
126 |
-------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/dictionaries/rodrigogomes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | aluno 5 | arquivo 6 | arquivos 7 | aula 8 | cadastrada 9 | comando 10 | complementar 11 | complementares 12 | conexão 13 | conta 14 | contacte 15 | digite 16 | disciplina 17 | disciplinas 18 | enviar 19 | está 20 | expirado 21 | faltas 22 | frequência 23 | funcionando 24 | incorreto 25 | jsession 26 | matricula 27 | momento 28 | nota 29 | notas 30 | noticias 31 | reprovado 32 | restante 33 | senha 34 | sippa 35 | sisac 36 | snackbar 37 | vazio 38 | verifique 39 | 40 | 41 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0) 2 | 3 | Get it on Google Play 4 | 5 | # Sippa Android 6 | 7 | - Este é um app desenvolvido para facilitar o uso do sippa e visualizar horas complementares em um celular android. 8 | 9 | # Youtube 10 | 13 | 14 | ## Dependências presentes no gradle 15 | [OkHttp](https://square.github.io/okhttp/) 16 | 17 | [Material Theme](https://material.io) 18 | 19 | [Android Room Persistence](https://developer.android.com/topic/libraries/architecture/room) 20 | 21 | ## Screenshots Dark Theme 22 | | Disciplinas | Horas Complementares | Nav View | Login | 23 | |---|---|---|---| 24 | |![](https://user-images.githubusercontent.com/7853887/59478646-71c7ba80-8e30-11e9-94fb-c06b073ea7f9.png)|![](https://user-images.githubusercontent.com/7853887/59478656-72605100-8e30-11e9-9a35-74d3761cf49e.png)|![](https://user-images.githubusercontent.com/7853887/59478655-72605100-8e30-11e9-9cae-41c95deb56ea.png)|![](https://user-images.githubusercontent.com/7853887/59478645-712f2400-8e30-11e9-807d-055bb2990ff8.png)| 25 | 26 | 27 | | Notícias | Notas | Plano | Arquivos | 28 | |---|---|---|---| 29 | |![](https://user-images.githubusercontent.com/7853887/59478648-71c7ba80-8e30-11e9-804b-f5d1c8f06703.png)|![](https://user-images.githubusercontent.com/7853887/59478650-71c7ba80-8e30-11e9-8cb3-0e0e3e4faece.png)|![](https://user-images.githubusercontent.com/7853887/59478652-71c7ba80-8e30-11e9-913e-26ae2d6d22ce.png)|![](https://user-images.githubusercontent.com/7853887/59478653-71c7ba80-8e30-11e9-9579-c12a2043dd2b.png)| 30 | 31 | 32 | ## Screenshots Light Theme 33 | | Disciplinas | Horas Complementares | Nav View | Login | 34 | |---|---|---|---| 35 | |![](https://user-images.githubusercontent.com/7853887/59478822-2530af00-8e31-11e9-80a1-a8e75876e13f.png)|![](https://user-images.githubusercontent.com/7853887/59478831-2661dc00-8e31-11e9-8d75-70979903d21b.png)|![](https://user-images.githubusercontent.com/7853887/59478823-2530af00-8e31-11e9-8855-8fe832d499e2.png)|![](https://user-images.githubusercontent.com/7853887/59479056-f1a25480-8e31-11e9-9124-791a17b118a6.png)| 36 | 37 | 38 | | Notícias | Notas | Plano | Arquivos | 39 | |---|---|---|---| 40 | |![](https://user-images.githubusercontent.com/7853887/59478826-25c94580-8e31-11e9-9943-4d9f8f41dd04.png)|![](https://user-images.githubusercontent.com/7853887/59478827-25c94580-8e31-11e9-8c9b-05635673ba1e.png)|![](https://user-images.githubusercontent.com/7853887/59478828-25c94580-8e31-11e9-8ce8-b31ad0e66f25.png)|![](https://user-images.githubusercontent.com/7853887/59478829-25c94580-8e31-11e9-8e31-0a318a031ebf.png)| 41 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | apply plugin: 'kotlin-android' 4 | 5 | apply plugin: 'kotlin-android-extensions' 6 | 7 | apply plugin: "kotlin-kapt" 8 | 9 | apply plugin: 'com.google.gms.google-services' 10 | 11 | apply plugin: 'com.google.firebase.crashlytics' 12 | 13 | android { 14 | compileSdkVersion 29 15 | defaultConfig { 16 | applicationId "com.rodrigmatrix.sippa" 17 | minSdkVersion 21 18 | targetSdkVersion 29 19 | versionCode 35 20 | versionName "2.4.1" 21 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 22 | } 23 | buildTypes { 24 | release { 25 | minifyEnabled true 26 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 27 | } 28 | } 29 | compileOptions { 30 | sourceCompatibility JavaVersion.VERSION_1_8 31 | targetCompatibility JavaVersion.VERSION_1_8 32 | } 33 | kotlinOptions { 34 | jvmTarget = '1.8' 35 | } 36 | 37 | } 38 | 39 | dependencies { 40 | implementation fileTree(dir: 'libs', include: ['*.jar']) 41 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 42 | 43 | // Firebase 44 | implementation 'com.google.firebase:firebase-core:18.0.2' 45 | implementation 'com.google.firebase:firebase-inappmessaging-display:19.1.5' 46 | implementation 'com.google.firebase:firebase-messaging:21.0.1' 47 | implementation 'com.google.firebase:firebase-analytics:18.0.2' 48 | implementation platform('com.google.firebase:firebase-bom:26.6.0') 49 | implementation 'com.google.firebase:firebase-crashlytics-ktx' 50 | implementation 'com.google.firebase:firebase-analytics-ktx' 51 | implementation 'com.google.firebase:firebase-config:20.0.4' 52 | implementation 'com.google.android.play:core:1.10.0' 53 | 54 | implementation 'androidx.appcompat:appcompat:1.2.0' 55 | implementation 'androidx.constraintlayout:constraintlayout:2.1.0-beta01' 56 | implementation 'androidx.legacy:legacy-support-v4:1.0.0' 57 | implementation 'androidx.core:core-ktx:1.3.2' 58 | implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' 59 | 60 | 61 | implementation 'androidx.gridlayout:gridlayout:1.0.0' 62 | implementation 'com.google.android.material:material:1.4.0-alpha01' 63 | implementation 'com.github.kittinunf.fuel:fuel:2.0.1' 64 | implementation 'com.squareup.picasso:picasso:2.71828' 65 | implementation "org.jetbrains.anko:anko:0.10.8" 66 | implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2' 67 | implementation "androidx.room:room-runtime:2.2.6" 68 | implementation 'org.jsoup:jsoup:1.12.1' 69 | kapt "androidx.room:room-compiler:2.2.6" 70 | implementation 'androidx.recyclerview:recyclerview:1.2.0-beta02' 71 | 72 | 73 | testImplementation 'junit:junit:4.13.2' 74 | androidTestImplementation 'androidx.test:runner:1.3.0' 75 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 76 | 77 | } 78 | -------------------------------------------------------------------------------- /app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "621636618585", 4 | "firebase_url": "https://ufc-apps.firebaseio.com", 5 | "project_id": "ufc-apps", 6 | "storage_bucket": "ufc-apps.appspot.com" 7 | }, 8 | "client": [ 9 | { 10 | "client_info": { 11 | "mobilesdk_app_id": "1:621636618585:android:8937bbd9819ff47e536448", 12 | "android_client_info": { 13 | "package_name": "com.rodrigmatrix.sigaaufc" 14 | } 15 | }, 16 | "oauth_client": [ 17 | { 18 | "client_id": "621636618585-ivm4p1dmb2s2r916s52bu08fjto95qd3.apps.googleusercontent.com", 19 | "client_type": 1, 20 | "android_info": { 21 | "package_name": "com.rodrigmatrix.sigaaufc", 22 | "certificate_hash": "abed0555bcecfa3f3f82e36b00186848401e426d" 23 | } 24 | }, 25 | { 26 | "client_id": "621636618585-psifoapo0a4p9f6546rfpjhoh7tfi86f.apps.googleusercontent.com", 27 | "client_type": 1, 28 | "android_info": { 29 | "package_name": "com.rodrigmatrix.sigaaufc", 30 | "certificate_hash": "dee77cf537eb798ff1d7abcc1a1f3196c976266a" 31 | } 32 | }, 33 | { 34 | "client_id": "621636618585-2v9vvh5hld2bn6cfql04j91g77j46gpo.apps.googleusercontent.com", 35 | "client_type": 3 36 | } 37 | ], 38 | "api_key": [ 39 | { 40 | "current_key": "AIzaSyCamAO4J48RbK7ZHdJt6WjPcd2YwL7D-P0" 41 | } 42 | ], 43 | "services": { 44 | "appinvite_service": { 45 | "other_platform_oauth_client": [ 46 | { 47 | "client_id": "621636618585-2v9vvh5hld2bn6cfql04j91g77j46gpo.apps.googleusercontent.com", 48 | "client_type": 3 49 | } 50 | ] 51 | } 52 | } 53 | }, 54 | { 55 | "client_info": { 56 | "mobilesdk_app_id": "1:621636618585:android:4cde0c575340d935536448", 57 | "android_client_info": { 58 | "package_name": "com.rodrigmatrix.sippa" 59 | } 60 | }, 61 | "oauth_client": [ 62 | { 63 | "client_id": "621636618585-h6rgh13rg46jlqkvskeidm0g86rp87e6.apps.googleusercontent.com", 64 | "client_type": 1, 65 | "android_info": { 66 | "package_name": "com.rodrigmatrix.sippa", 67 | "certificate_hash": "7303de637c135adcc2e2c68a71c045fdb984beb8" 68 | } 69 | }, 70 | { 71 | "client_id": "621636618585-j4a7os7m6v9fdg9feqsplshttdh51t6u.apps.googleusercontent.com", 72 | "client_type": 1, 73 | "android_info": { 74 | "package_name": "com.rodrigmatrix.sippa", 75 | "certificate_hash": "abed0555bcecfa3f3f82e36b00186848401e426d" 76 | } 77 | }, 78 | { 79 | "client_id": "621636618585-2v9vvh5hld2bn6cfql04j91g77j46gpo.apps.googleusercontent.com", 80 | "client_type": 3 81 | } 82 | ], 83 | "api_key": [ 84 | { 85 | "current_key": "AIzaSyCamAO4J48RbK7ZHdJt6WjPcd2YwL7D-P0" 86 | } 87 | ], 88 | "services": { 89 | "appinvite_service": { 90 | "other_platform_oauth_client": [ 91 | { 92 | "client_id": "621636618585-2v9vvh5hld2bn6cfql04j91g77j46gpo.apps.googleusercontent.com", 93 | "client_type": 3 94 | } 95 | ] 96 | } 97 | } 98 | } 99 | ], 100 | "configuration_version": "1" 101 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/rodrigmatrix/sippa/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa 2 | 3 | import androidx.test.InstrumentationRegistry 4 | import androidx.test.runner.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getTargetContext() 22 | assertEquals("com.rodrigmatrix.sippa", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 21 | 22 | 25 | 28 | 31 | 32 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 45 | 46 | 50 | 51 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/Adapters/ArquivosAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa 2 | 3 | import android.Manifest 4 | import android.app.Activity 5 | import android.app.DownloadManager 6 | import android.content.Context.DOWNLOAD_SERVICE 7 | import android.content.pm.PackageManager 8 | import android.net.Uri 9 | import android.os.Build 10 | import android.os.Environment 11 | import android.view.LayoutInflater 12 | import android.view.View 13 | import android.view.ViewGroup 14 | import androidx.core.app.ActivityCompat 15 | import androidx.core.content.ContextCompat.* 16 | import androidx.recyclerview.widget.RecyclerView 17 | import androidx.room.Room 18 | import com.google.android.material.snackbar.Snackbar 19 | import com.rodrigmatrix.sippa.persistance.File 20 | import com.rodrigmatrix.sippa.persistence.StudentsDatabase 21 | import kotlinx.android.synthetic.main.arquivo_row.view.* 22 | 23 | class ArquivosAdapter(private val arquivos: MutableList): RecyclerView.Adapter() { 24 | 25 | override fun getItemCount(): Int { 26 | return arquivos.size 27 | } 28 | 29 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArquivosViewHolder { 30 | val layoutInflater = LayoutInflater.from(parent.context) 31 | val arquivosRow = layoutInflater.inflate(R.layout.arquivo_row, parent, false) 32 | return ArquivosViewHolder(arquivosRow) 33 | } 34 | 35 | override fun onBindViewHolder(holder: ArquivosViewHolder, position: Int) { 36 | val arquivoData = arquivos[position] 37 | holder.view.arquivo_name?.text = arquivoData.name 38 | } 39 | } 40 | 41 | class ArquivosViewHolder(val view: View): RecyclerView.ViewHolder(view){ 42 | init { 43 | view.download_button.setOnClickListener { 44 | val url = """https://academico.quixada.ufc.br/ServletCentral?comando=CmdLoadArquivo&id=${view.arquivo_name.text}""" 45 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){ 46 | if(checkSelfPermission(view.context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED){ 47 | makeRequest() 48 | } 49 | else{ 50 | startDownload(url, view.arquivo_name.text.toString()) 51 | } 52 | } 53 | else{ 54 | startDownload(url, view.arquivo_name.text.toString()) 55 | } 56 | } 57 | } 58 | private fun startDownload(url: String, name: String){ 59 | val database = Room.databaseBuilder( 60 | view.context, 61 | StudentsDatabase::class.java, "database.db") 62 | .fallbackToDestructiveMigration() 63 | .allowMainThreadQueries() 64 | .build() 65 | if(database.studentDao().getStudent().jsession == "offline"){ 66 | Snackbar.make(view,"Download em modo offline disponível em breve(próximo semestre)", Snackbar.LENGTH_LONG).show() 67 | } 68 | else{ 69 | if(name == "Nenhum arquivo disponível nessa disciplina"){ 70 | Snackbar.make(view,"Nenhum arquivo disponível nessa disciplina", Snackbar.LENGTH_LONG).show() 71 | } 72 | else{ 73 | Snackbar.make(view,"Iniciando Download. Verifique suas notificações", Snackbar.LENGTH_LONG).show() 74 | val request = DownloadManager.Request(Uri.parse(url)) 75 | request.addRequestHeader("Cookie", database.studentDao().getStudent().jsession) 76 | request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE) 77 | request.setTitle("Sippa - " + view.arquivo_name.text) 78 | request.setDescription("Baixando arquivo...") 79 | request.allowScanningByMediaScanner() 80 | request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) 81 | request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, name) 82 | val manager = view.context.getSystemService(DOWNLOAD_SERVICE) as DownloadManager 83 | manager.enqueue(request) 84 | } 85 | } 86 | 87 | } 88 | private fun makeRequest() { 89 | ActivityCompat.requestPermissions( 90 | view.context as Activity, 91 | arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 92 | 1000) 93 | } 94 | } -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/Adapters/DisciplinasAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import android.widget.TextView 10 | import androidx.core.content.ContextCompat 11 | import androidx.recyclerview.widget.RecyclerView 12 | import com.rodrigmatrix.sippa.persistance.Class 13 | import kotlinx.android.synthetic.main.disciplina_row.view.* 14 | import org.jetbrains.anko.textColor 15 | 16 | 17 | class DisciplinasAdapter(private val classes: MutableList): RecyclerView.Adapter() { 18 | override fun getItemCount(): Int { 19 | return classes.size 20 | } 21 | 22 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DisciplinasViewHolder { 23 | val layoutInflater = LayoutInflater.from(parent.context) 24 | val disciplaRow = layoutInflater.inflate(R.layout.disciplina_row, parent, false) 25 | return DisciplinasViewHolder(disciplaRow) 26 | } 27 | 28 | @SuppressLint("SetTextI18n") 29 | override fun onBindViewHolder(holder: DisciplinasViewHolder, position: Int) { 30 | val classData = classes[position] 31 | holder.view.id_disciplina?.text = classData.id 32 | holder.view.class_name_text?.text = classData.name 33 | holder.view.class_professor_text?.text = classData.professorName 34 | holder.view.percentage_attendance_text?.text = "Frequência: " + classData.percentageAttendance + "%" 35 | holder.view.class_missed_text?.text = "Faltas: " + (classData.missed/2) + " Aula(s)" 36 | holder.view.professor_email_text?.text = classData.professorEmail 37 | convertColors(classData, holder.view.class_name_text, holder.view.class_missed_text, holder.view.class_missed_text.context) 38 | } 39 | @SuppressLint("SetTextI18n") 40 | private fun convertColors(classData: Class, classNameView: TextView, missed: TextView, context: Context){ 41 | if(classData.credits != 2){ 42 | val cmd = (classData.credits/2) * 0.25 43 | val missedClasses = classData.missed/2 44 | val missedText = missed.text 45 | val className = classNameView.text 46 | classNameView.text = "$className - ${classData.credits} Horas" 47 | missed.text = "$missedText/Restante: ${(cmd - missedClasses).toInt()}" 48 | when { 49 | cmd.toInt() == 12 -> { 50 | when{ 51 | missedClasses <= 6 ->{ 52 | missed.textColor = ContextCompat.getColor(context, R.color.colorSisac) 53 | } 54 | missedClasses in 7..9 ->{ 55 | missed.textColor = ContextCompat.getColor(context, R.color.Yellow) 56 | } 57 | missedClasses in 9..12 ->{ 58 | missed.textColor = ContextCompat.getColor(context, R.color.Orange) 59 | } 60 | else -> { 61 | missed.textColor = ContextCompat.getColor(context, R.color.Red) 62 | missed.text = "$missedText/Reprovado" 63 | } 64 | } 65 | } 66 | cmd.toInt() == 8 -> { 67 | when{ 68 | missedClasses <= 3 ->{ 69 | missed.textColor = ContextCompat.getColor(context, R.color.colorSisac) 70 | } 71 | missedClasses in 4..6 ->{ 72 | missed.textColor = ContextCompat.getColor(context, R.color.Yellow) 73 | } 74 | missedClasses in 7..8 ->{ 75 | missed.textColor = ContextCompat.getColor(context, R.color.Orange) 76 | } 77 | else -> { 78 | missed.textColor = ContextCompat.getColor(context, R.color.Red) 79 | missed.text = "$missedText/Reprovado" 80 | } 81 | } 82 | } 83 | else -> { 84 | when{ 85 | missedClasses <= 2 ->{ 86 | missed.textColor = ContextCompat.getColor(context, R.color.colorSisac) 87 | } 88 | missedClasses == 3 ->{ 89 | missed.textColor = ContextCompat.getColor(context, R.color.Yellow) 90 | } 91 | missedClasses == 4 ->{ 92 | missed.textColor = ContextCompat.getColor(context, R.color.Orange) 93 | } 94 | else -> { 95 | missed.textColor = ContextCompat.getColor(context, R.color.Red) 96 | missed.text = "$missedText/Reprovado" 97 | } 98 | } 99 | } 100 | } 101 | } 102 | } 103 | } 104 | 105 | class DisciplinasViewHolder(val view: View): RecyclerView.ViewHolder(view){ 106 | init { 107 | view.card.setOnClickListener { 108 | view.see_more_button.performClick() 109 | } 110 | view.see_more_button.setOnClickListener { 111 | val intent = Intent(view.context, DisciplinaActivity::class.java) 112 | intent.putExtra("id", view.id_disciplina.text.toString()) 113 | intent.putExtra("name", view.class_name_text.text.toString()) 114 | intent.putExtra("option", "all") 115 | view.context.startActivity(intent) 116 | } 117 | view.see_grades_button.setOnClickListener { 118 | val intent = Intent(view.context, DisciplinaActivity::class.java) 119 | intent.putExtra("id", view.id_disciplina.text.toString()) 120 | intent.putExtra("name", view.class_name_text.text.toString()) 121 | intent.putExtra("option", "grades") 122 | view.context.startActivity(intent) 123 | } 124 | 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/Adapters/HorasAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa.adapters 2 | 3 | import android.view.LayoutInflater 4 | import android.view.View 5 | import android.view.ViewGroup 6 | import androidx.recyclerview.widget.RecyclerView 7 | import com.rodrigmatrix.sippa.R 8 | import com.rodrigmatrix.sippa.persistance.HoraComplementar 9 | import kotlinx.android.synthetic.main.horas_row.view.* 10 | 11 | class HorasAdapter(private val horas: MutableList): RecyclerView.Adapter() { 12 | override fun getItemCount(): Int { 13 | return horas.size 14 | } 15 | 16 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HorasViewHolder { 17 | val layoutInflater = LayoutInflater.from(parent.context) 18 | val horasRow = layoutInflater.inflate(R.layout.horas_row, parent, false) 19 | return HorasViewHolder(horasRow) 20 | } 21 | 22 | override fun onBindViewHolder(holder: HorasViewHolder, position: Int) { 23 | val horasData = horas[position] 24 | holder.view.atividade_horas_text?.text = horasData.name 25 | holder.view.cadastro_horas_text?.text = horasData.professor 26 | holder.view.horas_text?.text = horasData.total 27 | if(horasData.professor.isBlank()){ 28 | holder.view.cadastro_horas_text?.visibility = View.GONE 29 | } 30 | } 31 | } 32 | 33 | class HorasViewHolder(val view: View): RecyclerView.ViewHolder(view) 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/Adapters/NotasAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa 2 | 3 | import android.view.LayoutInflater 4 | import android.view.View 5 | import android.view.ViewGroup 6 | import androidx.recyclerview.widget.RecyclerView 7 | import com.rodrigmatrix.sippa.persistance.Grade 8 | import kotlinx.android.synthetic.main.nota_row.view.* 9 | 10 | 11 | class NotasAdapter(private val notas: MutableList): RecyclerView.Adapter() { 12 | 13 | override fun getItemCount(): Int { 14 | return notas.size 15 | } 16 | 17 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NotasViewHolder { 18 | val layoutInflater = LayoutInflater.from(parent.context) 19 | val notasRow = layoutInflater.inflate(R.layout.nota_row, parent, false) 20 | return NotasViewHolder(notasRow) 21 | } 22 | 23 | override fun onBindViewHolder(holder: NotasViewHolder, position: Int) { 24 | val notasData = notas[position] 25 | holder.view.nome_nota_text.text = notasData.name 26 | if(notasData.grade == ""){ 27 | holder.view.nota_text.text = "Não cadastrada" 28 | } 29 | else{ 30 | holder.view.nota_text.text = notasData.grade 31 | } 32 | } 33 | } 34 | 35 | class NotasViewHolder(val view: View): RecyclerView.ViewHolder(view){ 36 | init { 37 | 38 | 39 | } 40 | } -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/Adapters/NoticiasAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa 2 | 3 | import android.view.LayoutInflater 4 | import android.view.View 5 | import android.view.ViewGroup 6 | import androidx.recyclerview.widget.RecyclerView 7 | import com.rodrigmatrix.sippa.persistance.News 8 | import kotlinx.android.synthetic.main.noticia_row.view.* 9 | 10 | class NoticiasAdapter(private val newsList: MutableList): RecyclerView.Adapter() { 11 | 12 | override fun getItemCount(): Int { 13 | return newsList.size 14 | } 15 | 16 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NoticiasViewHolder { 17 | val layoutInflater = LayoutInflater.from(parent.context) 18 | val notasRow = layoutInflater.inflate(R.layout.noticia_row, parent, false) 19 | return NoticiasViewHolder(notasRow) 20 | } 21 | 22 | override fun onBindViewHolder(holder: NoticiasViewHolder, position: Int) { 23 | val news = newsList[position] 24 | holder.view.news_date.text = news.date 25 | holder.view.news_content.text = news.content 26 | } 27 | } 28 | 29 | class NoticiasViewHolder(val view: View): RecyclerView.ViewHolder(view){ 30 | init { 31 | 32 | 33 | } 34 | } -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/Adapters/PlanoAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa 2 | 3 | import android.annotation.SuppressLint 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import androidx.recyclerview.widget.RecyclerView 8 | import com.rodrigmatrix.sippa.persistance.ClassPlan 9 | import kotlinx.android.synthetic.main.plano_row.view.* 10 | 11 | class PlanoAdapter(private val aulas: MutableList): RecyclerView.Adapter() { 12 | override fun getItemCount(): Int { 13 | return aulas.size 14 | } 15 | 16 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PlanoViewHolder { 17 | val layoutInflater = LayoutInflater.from(parent.context) 18 | val planoRow = layoutInflater.inflate(R.layout.plano_row, parent, false) 19 | return PlanoViewHolder(planoRow) 20 | } 21 | 22 | @SuppressLint("SetTextI18n") 23 | override fun onBindViewHolder(holder: PlanoViewHolder, position: Int) { 24 | val aulaData = aulas[position] 25 | holder.view.data_aula_text?.text = "${position+1} ${aulaData.date}" 26 | holder.view.diario_aula_text.text = aulaData.diary 27 | holder.view.plano_aula_text.text = aulaData.attendance 28 | holder.view.presenca_aula_text.text = aulaData.planned 29 | 30 | } 31 | } 32 | 33 | class PlanoViewHolder(val view: View): RecyclerView.ViewHolder(view) 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/ConnectionDetector.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa 2 | 3 | import android.content.Context 4 | import android.net.ConnectivityManager 5 | import android.net.NetworkInfo 6 | 7 | @Suppress("DEPRECATION") 8 | class ConnectionDetector { 9 | fun isConnectingToInternet(context: Context): Boolean { 10 | val connectivity = context.getSystemService( 11 | Context.CONNECTIVITY_SERVICE) as ConnectivityManager 12 | if (connectivity != null) { 13 | val info = connectivity.allNetworkInfo 14 | if (info != null) 15 | for (i in info) 16 | if (i.state == NetworkInfo.State.CONNECTED) { 17 | return true 18 | } 19 | } 20 | return false 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/DisciplinaActivity.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.pm.ActivityInfo 5 | import android.os.Bundle 6 | import androidx.appcompat.app.AppCompatActivity 7 | import com.rodrigmatrix.sippa.fragments.NotasFragment 8 | import com.rodrigmatrix.sippa.ui.main.SectionsPagerAdapter 9 | import kotlinx.android.synthetic.main.activity_disciplina.* 10 | 11 | class DisciplinaActivity : AppCompatActivity() { 12 | private lateinit var sectionsPagerAdapter: SectionsPagerAdapter 13 | @SuppressLint("SourceLockedOrientationActivity") 14 | override fun onCreate(savedInstanceState: Bundle?) { 15 | requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT 16 | super.onCreate(savedInstanceState) 17 | setContentView(R.layout.activity_disciplina) 18 | sectionsPagerAdapter = SectionsPagerAdapter(this, supportFragmentManager) 19 | val id = intent.getStringExtra("id") 20 | sectionsPagerAdapter.removeFragments() 21 | sectionsPagerAdapter.addFragment(NoticiasFragment.newInstance(id)) 22 | sectionsPagerAdapter.addFragment(NotasFragment.newInstance(id)) 23 | sectionsPagerAdapter.addFragment(PlanoAulaFragment.newInstance(id)) 24 | sectionsPagerAdapter.addFragment(ArquivosFragment.newInstance(id)) 25 | view_pager.offscreenPageLimit = 4 26 | setSupportActionBar(toolbar) 27 | supportActionBar!!.setDisplayHomeAsUpEnabled(true) 28 | toolbar.setNavigationIcon(R.drawable.ic_arrow_back_24dp) 29 | val name = intent.getStringExtra("name") 30 | title = if(name.contains(" -")){ 31 | name!!.split(" -")[0] 32 | } else{ 33 | name 34 | } 35 | 36 | toolbar.setNavigationOnClickListener { 37 | sectionsPagerAdapter.removeFragments() 38 | this.finish() 39 | } 40 | tabs.setupWithViewPager(view_pager) 41 | view_pager.adapter = sectionsPagerAdapter 42 | tabs.getTabAt(0)?.setIcon(R.drawable.ic_noticias_24dp) 43 | tabs.getTabAt(1)?.setIcon(R.drawable.ic_notas_24dp) 44 | tabs.getTabAt(2)?.setIcon(R.drawable.ic_plano_24dp) 45 | tabs.getTabAt(3)?.setIcon(R.drawable.ic_arquivos_24dp) 46 | if(intent.getStringExtra("option") == "grades"){ 47 | val op = tabs.getTabAt(1) 48 | op?.select() 49 | } 50 | else{ 51 | val op = tabs.getTabAt(0) 52 | op?.select() 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/Fragments/ArquivosFragment.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa 2 | 3 | 4 | import android.os.Bundle 5 | import android.util.Log 6 | import androidx.fragment.app.Fragment 7 | import android.view.LayoutInflater 8 | import android.view.View 9 | import android.view.ViewGroup 10 | import androidx.core.content.ContextCompat 11 | import androidx.recyclerview.widget.LinearLayoutManager 12 | import com.google.android.material.snackbar.Snackbar 13 | import com.rodrigmatrix.sippa.persistence.StudentsDatabase 14 | import com.rodrigmatrix.sippa.serializer.Serializer 15 | import kotlinx.android.synthetic.main.fragment_arquivos.* 16 | import kotlinx.coroutines.* 17 | import okhttp3.OkHttpClient 18 | import okhttp3.Request 19 | import org.jetbrains.anko.support.v4.runOnUiThread 20 | import kotlin.coroutines.CoroutineContext 21 | 22 | 23 | class ArquivosFragment : Fragment(), CoroutineScope { 24 | var id = "" 25 | private var job: Job = Job() 26 | override val coroutineContext: CoroutineContext get() = Dispatchers.IO + job 27 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 28 | swiperefresh_arquivos.setColorSchemeResources(R.color.colorPrimary) 29 | val database = StudentsDatabase.invoke(context!!) 30 | val jsession = database.studentDao().getStudent().jsession 31 | swiperefresh_arquivos?.isRefreshing = true 32 | swiperefresh_arquivos?.setProgressBackgroundColorSchemeColor(ContextCompat.getColor(view.context, R.color.colorSwipeRefresh)) 33 | launch(handler) { 34 | setClass(id, jsession) 35 | } 36 | swiperefresh_arquivos?.setOnRefreshListener { 37 | swiperefresh_arquivos?.isRefreshing = true 38 | launch(handler) { 39 | setClass(id, jsession) 40 | } 41 | } 42 | } 43 | override fun onStop() { 44 | job.cancel() 45 | coroutineContext.cancel() 46 | super.onStop() 47 | } 48 | override fun onDestroy() { 49 | job.cancel() 50 | coroutineContext.cancel() 51 | super.onDestroy() 52 | } 53 | private val handler = CoroutineExceptionHandler { _, throwable -> 54 | Log.e("Exception", ":$throwable") 55 | } 56 | 57 | private suspend fun setClass(id: String, jsession: String){ 58 | if(!isConnected()) { 59 | return 60 | } 61 | val client = OkHttpClient() 62 | val request = Request.Builder() 63 | .url("""https://academico.quixada.ufc.br/ServletCentral?comando=CmdListarFrequenciaTurmaAluno&id=$id""") 64 | .header("Content-Type", "application/x-www-form-urlencoded") 65 | .header("Cookie", jsession) 66 | .build() 67 | withContext(Dispatchers.IO){ 68 | val response = client.newCall(request).execute() 69 | when { 70 | !response.isSuccessful -> showErrorConnection() 71 | else -> launch(handler) { 72 | getFiles(jsession) 73 | } 74 | } 75 | } 76 | } 77 | 78 | private fun isConnected(): Boolean{ 79 | val cd = ConnectionDetector() 80 | if(!cd.isConnectingToInternet(view!!.context)){ 81 | runOnUiThread { 82 | val snackbar = Snackbar.make(view!!, "Verifique sua conexão com a internet", Snackbar.LENGTH_LONG) 83 | snackbar.show() 84 | swiperefresh_arquivos.isRefreshing = false 85 | } 86 | return false 87 | } 88 | return true 89 | } 90 | 91 | private fun showErrorConnection(){ 92 | runOnUiThread { 93 | swiperefresh_arquivos.isRefreshing = false 94 | val snackbar = 95 | Snackbar.make(view!!, "Verifique sua conexão com a internet", Snackbar.LENGTH_LONG) 96 | snackbar.show() 97 | } 98 | } 99 | 100 | private suspend fun getFiles(jsession: String){ 101 | if(!isConnected()){return} 102 | val client = OkHttpClient() 103 | val request = Request.Builder() 104 | .url("https://academico.quixada.ufc.br/sippa/aluno_visualizar_arquivos.jsp?sorter=1") 105 | .header("Content-Type", "application/x-www-form-urlencoded") 106 | .header("Cookie", jsession) 107 | .build() 108 | withContext(Dispatchers.IO){ 109 | val response = client.newCall(request).execute() 110 | if (!response.isSuccessful) { 111 | runOnUiThread { 112 | showErrorConnection() 113 | } 114 | } 115 | else{ 116 | val res = response.body()!!.string() 117 | val serializer = Serializer() 118 | val files = serializer.parseFiles(id,res) 119 | runOnUiThread { 120 | swiperefresh_arquivos.isRefreshing = false 121 | recyclerView_arquivos.layoutManager = LinearLayoutManager(context) 122 | recyclerView_arquivos.adapter = ArquivosAdapter(files) 123 | } 124 | 125 | } 126 | } 127 | 128 | } 129 | 130 | override fun onCreateView( 131 | inflater: LayoutInflater, container: ViewGroup?, 132 | savedInstanceState: Bundle? 133 | ): View? { 134 | return inflater.inflate(R.layout.fragment_arquivos, container, false) 135 | } 136 | 137 | 138 | companion object { 139 | @JvmStatic 140 | fun newInstance(idDisciplina: String) = 141 | ArquivosFragment().apply { 142 | arguments = Bundle().apply { 143 | id = idDisciplina 144 | } 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/Fragments/DisciplinasFragment.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa.fragments 2 | 3 | import android.content.Context 4 | import android.net.Uri 5 | import android.os.Bundle 6 | import android.util.Log 7 | import androidx.fragment.app.Fragment 8 | import android.view.LayoutInflater 9 | import android.view.View 10 | import android.view.ViewGroup 11 | import androidx.core.content.ContextCompat 12 | import androidx.recyclerview.widget.LinearLayoutManager 13 | import com.google.android.gms.ads.* 14 | import com.google.android.material.snackbar.Snackbar 15 | import com.rodrigmatrix.sippa.BuildConfig 16 | import com.rodrigmatrix.sippa.ConnectionDetector 17 | import com.rodrigmatrix.sippa.DisciplinasAdapter 18 | import com.rodrigmatrix.sippa.R 19 | import com.rodrigmatrix.sippa.persistance.Class 20 | import com.rodrigmatrix.sippa.persistence.StudentsDatabase 21 | import com.rodrigmatrix.sippa.serializer.Serializer 22 | import kotlinx.android.synthetic.main.fragment_disciplinas.* 23 | import kotlinx.coroutines.* 24 | import okhttp3.OkHttpClient 25 | import okhttp3.Request 26 | import org.jetbrains.anko.support.v4.runOnUiThread 27 | import java.lang.Exception 28 | import java.text.SimpleDateFormat 29 | import java.util.* 30 | import java.util.concurrent.TimeoutException 31 | import kotlin.coroutines.CoroutineContext 32 | 33 | class DisciplinasFragment : Fragment(R.layout.fragment_disciplinas), CoroutineScope { 34 | 35 | 36 | override val coroutineContext: CoroutineContext get() = Dispatchers.IO 37 | private lateinit var database: StudentsDatabase 38 | 39 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 40 | swiperefresh!!.setColorSchemeResources(R.color.colorPrimary) 41 | database = StudentsDatabase.invoke(context!!) 42 | swiperefresh?.setProgressBackgroundColorSchemeColor(ContextCompat.getColor(view.context, 43 | R.color.colorSwipeRefresh 44 | )) 45 | val jsession = database.studentDao().getStudent().jsession 46 | swiperefresh?.isRefreshing = false 47 | swiperefresh?.setOnRefreshListener { 48 | try { 49 | launch(handler){ 50 | setClasses(jsession, database) 51 | } 52 | }catch(e: Exception){ 53 | runOnUiThread { 54 | swiperefresh?.isRefreshing = false 55 | Snackbar.make(view, e.toString(), Snackbar.LENGTH_LONG).show() 56 | } 57 | } 58 | } 59 | try { 60 | launch(handler){ 61 | setClasses(jsession, database) 62 | } 63 | }catch(e: Exception){ 64 | runOnUiThread { 65 | swiperefresh?.isRefreshing = false 66 | Snackbar.make(view, e.toString(), Snackbar.LENGTH_LONG).show() 67 | } 68 | } 69 | } 70 | 71 | private val handler = CoroutineExceptionHandler { _, throwable -> 72 | runOnUiThread { 73 | swiperefresh?.isRefreshing = false 74 | Snackbar.make(fragment_disciplinas, "${throwable.message}", Snackbar.LENGTH_INDEFINITE).show() 75 | } 76 | Log.e("Exception", ":${throwable.message}") 77 | } 78 | 79 | override fun onStop() { 80 | coroutineContext.cancel() 81 | swiperefresh?.isRefreshing = false 82 | super.onStop() 83 | } 84 | override fun onDestroy() { 85 | coroutineContext.cancel() 86 | swiperefresh?.isRefreshing = false 87 | super.onDestroy() 88 | } 89 | 90 | private suspend fun setClasses(jsession: String, database: StudentsDatabase){ 91 | swiperefresh?.isRefreshing = true 92 | if(jsession == "offline"){ 93 | val classes = database.studentDao().getClasses() 94 | if(classes.size != 0){ 95 | runOnUiThread { 96 | recyclerView_disciplinas.layoutManager = LinearLayoutManager(context) 97 | recyclerView_disciplinas.adapter = DisciplinasAdapter(classes) 98 | swiperefresh.isRefreshing = false 99 | } 100 | } 101 | else{ 102 | runOnUiThread { 103 | swiperefresh.isRefreshing = false 104 | Snackbar.make(view!!, "Nenhuma disciplina encontrada em sua conta", Snackbar.LENGTH_LONG).show() 105 | } 106 | } 107 | } 108 | else{ 109 | val cd = ConnectionDetector() 110 | val serializer = Serializer() 111 | val classes = serializer.parseClasses(database.studentDao().getStudent().responseHtml) 112 | val client = OkHttpClient() 113 | var parsed = true 114 | database.studentDao().deleteClasses() 115 | database.studentDao().deleteHoras() 116 | database.studentDao().deleteGrades() 117 | database.studentDao().deleteClassPlan() 118 | database.studentDao().deleteFiles() 119 | database.studentDao().deleteNews() 120 | val context = context 121 | if(context != null){ 122 | if(!cd.isConnectingToInternet(context)){ 123 | runOnUiThread { 124 | Snackbar.make(view!!, "Verifique sua conexão com a internet", Snackbar.LENGTH_LONG) 125 | .show() 126 | swiperefresh.isRefreshing = false 127 | } 128 | return 129 | } 130 | } 131 | for (it in classes) { 132 | val request = Request.Builder() 133 | .url("""https://academico.quixada.ufc.br/ServletCentral?comando=CmdListarFrequenciaTurmaAluno&id=${it.id}""") 134 | .header("Content-Type", "application/x-www-form-urlencoded") 135 | .header("Cookie", jsession) 136 | .build() 137 | withContext(Dispatchers.IO) { 138 | try { 139 | val response = client.newCall(request).execute() 140 | if (response.isSuccessful) { 141 | val res = response.body()!!.string() 142 | val attendance = serializer.parseAttendance(res) 143 | it.totalAttendance = attendance.totalAttendance 144 | it.missed = attendance.totalMissed 145 | it.professorEmail = serializer.parseProfessorEmail(res) 146 | val credits = serializer.parseClassPlan(it.id, res) 147 | it.credits = credits.size * 2 148 | val studentClass = Class(it.id, it.name, it.professorName, it.professorEmail, it.percentageAttendance, it.credits, it.missed, it.totalAttendance) 149 | database.studentDao().insertClass(studentClass) 150 | val news = serializer.parseNews(it.id, res) 151 | val classPlan = serializer.parseClassPlan(it.id, res) 152 | classPlan.forEach { 153 | database.studentDao().insertClassPlan(it) 154 | } 155 | news.forEach { 156 | database.studentDao().insertNews(it) 157 | } 158 | setGrades(it.id, jsession) 159 | } 160 | else{ 161 | parsed = false 162 | runOnUiThread { 163 | swiperefresh.isRefreshing = false 164 | Snackbar.make(view!!, "Verifique sua conexão com a internet", Snackbar.LENGTH_LONG).show() 165 | } 166 | } 167 | }catch(e: TimeoutException){ 168 | parsed = false 169 | runOnUiThread { 170 | swiperefresh.isRefreshing = false 171 | Snackbar.make(view!!, "Tempo de conexao expirou", Snackbar.LENGTH_LONG).show() 172 | } 173 | } 174 | 175 | } 176 | if(!parsed){ 177 | return 178 | } 179 | } 180 | if(parsed){ 181 | try { 182 | if(classes.size != 0){ 183 | runOnUiThread { 184 | val sdf = SimpleDateFormat("dd/MM/yy hh:mm") 185 | val currentDate = sdf.format(Date()) 186 | val student = database.studentDao().getStudent() 187 | student.lastUpdate = currentDate 188 | student.hasSavedData = true 189 | database.studentDao().deleteStudent() 190 | database.studentDao().insertStudent(student) 191 | recyclerView_disciplinas.layoutManager = LinearLayoutManager(context) 192 | recyclerView_disciplinas.adapter = DisciplinasAdapter(classes) 193 | swiperefresh.isRefreshing = false 194 | } 195 | } 196 | else{ 197 | val sdf = SimpleDateFormat("dd/MM/yy hh:mm") 198 | val currentDate = sdf.format(Date()) 199 | val student = database.studentDao().getStudent() 200 | student.lastUpdate = currentDate 201 | student.hasSavedData = true 202 | database.studentDao().deleteStudent() 203 | database.studentDao().insertStudent(student) 204 | swiperefresh.isRefreshing = false 205 | runOnUiThread { 206 | swiperefresh.isRefreshing = false 207 | Snackbar.make(view!!, "Nenhuma disciplina cadastrada em sua conta", Snackbar.LENGTH_LONG).show() 208 | } 209 | return 210 | } 211 | }catch (e: Exception){ 212 | runOnUiThread { 213 | swiperefresh.isRefreshing = false 214 | Snackbar.make(view!!, "Erro ao exibir disciplinas. Tente novamente", Snackbar.LENGTH_LONG).show() 215 | } 216 | return 217 | } 218 | } 219 | } 220 | } 221 | 222 | private suspend fun setGrades(id: String, jsession: String){ 223 | val request = Request.Builder() 224 | .url("https://academico.quixada.ufc.br/ServletCentral?comando=CmdVisualizarAvaliacoesAluno") 225 | .header("Content-Type", "application/x-www-form-urlencoded") 226 | .header("Cookie", jsession) 227 | .build() 228 | try { 229 | val client = OkHttpClient() 230 | withContext(Dispatchers.IO) { 231 | val response = client.newCall(request).execute() 232 | if (response.isSuccessful) { 233 | val serializer = Serializer() 234 | val grades = serializer.parseGrades(id, response.body()!!.string()) 235 | grades.forEach { 236 | database.studentDao().insertGrade(it) 237 | } 238 | } 239 | } 240 | }catch(e: TimeoutException){ 241 | runOnUiThread { 242 | swiperefresh.isRefreshing = false 243 | Snackbar.make(view!!, "Tempo de conexão expirou", Snackbar.LENGTH_LONG).show() 244 | } 245 | } 246 | 247 | } 248 | 249 | 250 | } -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/Fragments/HorasFragment.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa 2 | 3 | import android.net.Uri 4 | import android.os.Bundle 5 | import android.util.Log 6 | import androidx.fragment.app.Fragment 7 | import android.view.LayoutInflater 8 | import android.view.View 9 | import android.view.ViewGroup 10 | import androidx.core.content.ContextCompat 11 | import androidx.recyclerview.widget.LinearLayoutManager 12 | import com.google.android.material.snackbar.Snackbar 13 | import com.rodrigmatrix.sippa.adapters.HorasAdapter 14 | import com.rodrigmatrix.sippa.persistence.StudentsDatabase 15 | import com.rodrigmatrix.sippa.serializer.Serializer 16 | import kotlinx.android.synthetic.main.fragment_horas.* 17 | import kotlinx.coroutines.* 18 | import okhttp3.OkHttpClient 19 | import okhttp3.Request 20 | import org.jetbrains.anko.support.v4.runOnUiThread 21 | import kotlin.coroutines.CoroutineContext 22 | 23 | class HorasFragment : Fragment(), CoroutineScope { 24 | private var job: Job = Job() 25 | override val coroutineContext: CoroutineContext get() = Dispatchers.IO + job 26 | private lateinit var database: StudentsDatabase 27 | override fun onCreate(savedInstanceState: Bundle?) { 28 | super.onCreate(savedInstanceState) 29 | retainInstance = true 30 | } 31 | 32 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 33 | swiperefresh_horas!!.setColorSchemeResources(R.color.colorSisac) 34 | database = StudentsDatabase.invoke(context!!) 35 | swiperefresh_horas?.isRefreshing = false 36 | swiperefresh_horas?.setProgressBackgroundColorSchemeColor(ContextCompat.getColor(view.context, R.color.colorSwipeRefresh)) 37 | var student = database.studentDao().getStudent() 38 | swiperefresh_horas?.setOnRefreshListener { 39 | launch(handler){ 40 | runOnUiThread { 41 | swiperefresh_horas?.isRefreshing = true 42 | } 43 | setHoras(student?.jsession) 44 | } 45 | } 46 | launch(handler){ 47 | runOnUiThread { 48 | swiperefresh_horas?.isRefreshing = true 49 | } 50 | setHoras(student?.jsession) 51 | } 52 | } 53 | override fun onStop() { 54 | job.cancel() 55 | coroutineContext.cancel() 56 | swiperefresh_horas?.isRefreshing = false 57 | super.onStop() 58 | } 59 | override fun onDestroy() { 60 | job.cancel() 61 | coroutineContext.cancel() 62 | swiperefresh_horas?.isRefreshing = false 63 | super.onDestroy() 64 | } 65 | private val handler = CoroutineExceptionHandler { _, throwable -> 66 | Log.e("Exception", ":$throwable") 67 | } 68 | 69 | private suspend fun setHoras(jsession: String){ 70 | 71 | if(jsession == "offline"){ 72 | val horas = database.studentDao().getHoras() 73 | runOnUiThread { 74 | recyclerView_horas?.layoutManager = LinearLayoutManager(context) 75 | recyclerView_horas?.adapter = HorasAdapter(horas) 76 | swiperefresh_horas?.isRefreshing = false 77 | } 78 | } 79 | else{ 80 | database.studentDao().deleteHoras() 81 | val cd = ConnectionDetector() 82 | val serializer = Serializer() 83 | val client = OkHttpClient() 84 | if(!cd.isConnectingToInternet(view!!.context)){ 85 | runOnUiThread { 86 | Snackbar.make(view!!, "Verifique sua conexão com a internet", Snackbar.LENGTH_LONG).show() 87 | swiperefresh_horas?.isRefreshing = false 88 | } 89 | return 90 | } 91 | val request = Request.Builder() 92 | .url("https://academico.quixada.ufc.br/ServletCentral?comando=CmdLoginSisacAluno") 93 | .header("Content-Type", "application/x-www-form-urlencoded") 94 | .header("Cookie", jsession) 95 | .build() 96 | withContext(Dispatchers.IO){ 97 | val response = client.newCall(request).execute() 98 | if (response.isSuccessful) { 99 | val res = response.body()!!.string() 100 | val horas = serializer.parseHorasComplementares(res) 101 | horas.forEach { 102 | database.studentDao().insertHora(it) 103 | } 104 | runOnUiThread { 105 | recyclerView_horas?.layoutManager = LinearLayoutManager(context) 106 | recyclerView_horas?.adapter = HorasAdapter(horas) 107 | swiperefresh_horas?.isRefreshing = false 108 | } 109 | } 110 | else{ 111 | runOnUiThread { 112 | swiperefresh_horas?.isRefreshing = false 113 | val snackbar = Snackbar.make(view!!, "Verifique sua conexão com a internet", Snackbar.LENGTH_LONG) 114 | snackbar.show() 115 | } 116 | } 117 | } 118 | } 119 | } 120 | 121 | override fun onCreateView( 122 | inflater: LayoutInflater, container: ViewGroup?, 123 | savedInstanceState: Bundle? 124 | ): View? { 125 | // Inflate the layout for this fragment 126 | return inflater.inflate(R.layout.fragment_horas, container, false) 127 | } 128 | 129 | interface OnFragmentInteractionListener { 130 | fun onFragmentInteraction(uri: Uri) 131 | } 132 | 133 | companion object { 134 | @JvmStatic 135 | fun newInstance() = 136 | HorasFragment().apply { 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/Fragments/InfoFragment.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa 2 | 3 | 4 | import android.os.Bundle 5 | import androidx.fragment.app.Fragment 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.ViewGroup 9 | 10 | 11 | class InfoFragment : Fragment() { 12 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { 13 | return inflater.inflate(R.layout.fragment_info, container, false) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/Fragments/NotasFragment.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa.fragments 2 | 3 | 4 | import android.os.Bundle 5 | import android.util.Log 6 | import androidx.fragment.app.Fragment 7 | import android.view.LayoutInflater 8 | import android.view.View 9 | import android.view.ViewGroup 10 | import androidx.core.content.ContextCompat 11 | import androidx.recyclerview.widget.LinearLayoutManager 12 | import com.google.android.material.snackbar.Snackbar 13 | import com.rodrigmatrix.sippa.ConnectionDetector 14 | import com.rodrigmatrix.sippa.NotasAdapter 15 | import com.rodrigmatrix.sippa.R 16 | import com.rodrigmatrix.sippa.persistence.StudentsDatabase 17 | import com.rodrigmatrix.sippa.serializer.Serializer 18 | import kotlinx.android.synthetic.main.fragment_notas.* 19 | import kotlinx.coroutines.* 20 | import okhttp3.OkHttpClient 21 | import okhttp3.Request 22 | import org.jetbrains.anko.support.v4.runOnUiThread 23 | import kotlin.coroutines.CoroutineContext 24 | 25 | 26 | class NotasFragment : Fragment(), CoroutineScope { 27 | var id = "" 28 | private var job: Job = Job() 29 | override val coroutineContext: CoroutineContext get() = Dispatchers.IO + job 30 | lateinit var database: StudentsDatabase 31 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 32 | swiperefresh_notas.setColorSchemeResources(R.color.colorPrimary) 33 | database = StudentsDatabase.invoke(context!!) 34 | val jsession = database.studentDao().getStudent().jsession 35 | setNotas(jsession) 36 | swiperefresh_notas?.setProgressBackgroundColorSchemeColor(ContextCompat.getColor(view.context, 37 | R.color.colorSwipeRefresh 38 | )) 39 | swiperefresh_notas?.setOnRefreshListener { 40 | setNotas(jsession) 41 | } 42 | } 43 | private fun setNotas(jsession: String){ 44 | if(jsession == "offline"){ 45 | var grades = database.studentDao().getGrades(id) 46 | runOnUiThread { 47 | var lastUpdate = database.studentDao().getStudent().lastUpdate 48 | Snackbar.make(view!!, "Modo offline. Última atualização de dados: $lastUpdate", Snackbar.LENGTH_LONG).show() 49 | swiperefresh_notas?.isRefreshing = false 50 | recyclerView_notas?.layoutManager = LinearLayoutManager(context) 51 | recyclerView_notas?.adapter = NotasAdapter(grades) 52 | } 53 | } 54 | else{ 55 | swiperefresh_notas?.isRefreshing = true 56 | launch(handler) { 57 | setClass(id, jsession) 58 | } 59 | } 60 | } 61 | override fun onStop() { 62 | job.cancel() 63 | coroutineContext.cancel() 64 | super.onStop() 65 | } 66 | override fun onDestroy() { 67 | job.cancel() 68 | coroutineContext.cancel() 69 | super.onDestroy() 70 | } 71 | private val handler = CoroutineExceptionHandler { _, throwable -> 72 | Log.e("Exception", ":$throwable") 73 | } 74 | private fun isConnected(): Boolean{ 75 | val cd = ConnectionDetector() 76 | if(!cd.isConnectingToInternet(view!!.context)){ 77 | runOnUiThread { 78 | val snackbar = Snackbar.make(view!!, "Verifique sua conexão com a internet", Snackbar.LENGTH_LONG) 79 | snackbar.show() 80 | swiperefresh_notas?.isRefreshing = false 81 | } 82 | return false 83 | } 84 | return true 85 | } 86 | private fun showErrorConnection(){ 87 | runOnUiThread { 88 | swiperefresh_notas?.isRefreshing = false 89 | val snackbar = 90 | Snackbar.make(view!!, "Verifique sua conexão com a internet", Snackbar.LENGTH_LONG) 91 | snackbar.show() 92 | } 93 | } 94 | 95 | private suspend fun setClass(id: String, jsession: String){ 96 | if(!isConnected()){return} 97 | val client = OkHttpClient() 98 | val request = Request.Builder() 99 | .url("""https://academico.quixada.ufc.br/ServletCentral?comando=CmdListarFrequenciaTurmaAluno&id=$id""") 100 | .header("Content-Type", "application/x-www-form-urlencoded") 101 | .header("Cookie", jsession) 102 | .build() 103 | withContext(Dispatchers.IO){ 104 | val response = client.newCall(request).execute() 105 | if (!response.isSuccessful) { 106 | runOnUiThread { 107 | showErrorConnection() 108 | } 109 | } 110 | else{ 111 | getGrades(jsession) 112 | } 113 | } 114 | } 115 | 116 | private suspend fun getGrades(jsession: String){ 117 | val client = OkHttpClient() 118 | val serializer = Serializer() 119 | val request = Request.Builder() 120 | .url("https://academico.quixada.ufc.br/ServletCentral?comando=CmdVisualizarAvaliacoesAluno") 121 | .header("Content-Type", "application/x-www-form-urlencoded") 122 | .header("Cookie", jsession) 123 | .build() 124 | withContext(Dispatchers.IO){ 125 | val response = client.newCall(request).execute() 126 | if (response.isSuccessful) { 127 | val res = response.body()!!.string() 128 | var grades = serializer.parseGrades(id, res) 129 | runOnUiThread { 130 | swiperefresh_notas.isRefreshing = false 131 | recyclerView_notas.layoutManager = LinearLayoutManager(context) 132 | recyclerView_notas.adapter = NotasAdapter(grades) 133 | } 134 | } 135 | else{ 136 | runOnUiThread { 137 | showErrorConnection() 138 | } 139 | } 140 | } 141 | 142 | } 143 | 144 | override fun onCreateView( 145 | inflater: LayoutInflater, container: ViewGroup?, 146 | savedInstanceState: Bundle? 147 | ): View? { 148 | // Inflate the layout for this fragment 149 | return inflater.inflate(R.layout.fragment_notas, container, false) 150 | } 151 | 152 | 153 | companion object { 154 | @JvmStatic 155 | fun newInstance(idDisciplina: String) = 156 | NotasFragment().apply { 157 | id = idDisciplina 158 | } 159 | } 160 | } -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/Fragments/NoticiasFragment.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa 2 | 3 | 4 | import android.os.Bundle 5 | import android.util.Log 6 | import androidx.fragment.app.Fragment 7 | import android.view.LayoutInflater 8 | import android.view.View 9 | import android.view.ViewGroup 10 | import androidx.core.content.ContextCompat 11 | import androidx.recyclerview.widget.LinearLayoutManager 12 | import com.google.android.material.snackbar.Snackbar 13 | import com.rodrigmatrix.sippa.persistence.StudentsDatabase 14 | import com.rodrigmatrix.sippa.serializer.Serializer 15 | import kotlinx.android.synthetic.main.fragment_noticias.* 16 | import kotlinx.coroutines.* 17 | import okhttp3.OkHttpClient 18 | import okhttp3.Request 19 | import org.jetbrains.anko.support.v4.runOnUiThread 20 | import kotlin.coroutines.CoroutineContext 21 | 22 | 23 | class NoticiasFragment : Fragment(), CoroutineScope { 24 | var id = "" 25 | private var job: Job = Job() 26 | override val coroutineContext: CoroutineContext get() = Dispatchers.IO + job 27 | lateinit var database: StudentsDatabase 28 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 29 | swiperefresh_noticias.setColorSchemeResources(R.color.colorPrimary) 30 | database = StudentsDatabase.invoke(context!!) 31 | val jsession = database.studentDao().getStudent().jsession 32 | setNoticias(jsession) 33 | swiperefresh_noticias?.setProgressBackgroundColorSchemeColor(ContextCompat.getColor(view.context, R.color.colorSwipeRefresh)) 34 | swiperefresh_noticias?.setOnRefreshListener { 35 | setNoticias(jsession) 36 | } 37 | } 38 | private fun setNoticias(jsession: String){ 39 | swiperefresh_noticias?.isRefreshing = true 40 | if(jsession == "offline"){ 41 | val news = database.studentDao().getNews(id) 42 | runOnUiThread { 43 | val lastUpdate = database.studentDao().getStudent().lastUpdate 44 | Snackbar.make(view!!, "Modo offline. Última atualização de dados: $lastUpdate", Snackbar.LENGTH_LONG).show() 45 | swiperefresh_noticias.isRefreshing = false 46 | recyclerView_noticias.layoutManager = LinearLayoutManager(context) 47 | recyclerView_noticias.adapter = NoticiasAdapter(news) 48 | } 49 | } 50 | else{ 51 | launch(handler) { 52 | setClass(id, jsession) 53 | } 54 | } 55 | } 56 | private val handler = CoroutineExceptionHandler { _, throwable -> 57 | Log.e("Exception", ":$throwable") 58 | } 59 | 60 | override fun onStop() { 61 | job.cancel() 62 | coroutineContext.cancel() 63 | super.onStop() 64 | } 65 | override fun onDestroy() { 66 | job.cancel() 67 | coroutineContext.cancel() 68 | super.onDestroy() 69 | } 70 | private fun isConnected(): Boolean{ 71 | val cd = ConnectionDetector() 72 | if(!cd.isConnectingToInternet(view!!.context)){ 73 | runOnUiThread { 74 | val snackbar = Snackbar.make(view!!, "Verifique sua conexão com a internet", Snackbar.LENGTH_LONG) 75 | snackbar.show() 76 | swiperefresh_noticias.isRefreshing = false 77 | } 78 | return false 79 | } 80 | return true 81 | } 82 | private fun showErrorConnection(){ 83 | runOnUiThread { 84 | swiperefresh_noticias.isRefreshing = false 85 | val snackbar = 86 | Snackbar.make(view!!, "Verifique sua conexão com a internet", Snackbar.LENGTH_LONG) 87 | snackbar.show() 88 | } 89 | } 90 | 91 | private suspend fun setClass(id: String, jsession: String){ 92 | if(!isConnected()){return} 93 | val client = OkHttpClient() 94 | val request = Request.Builder() 95 | .url("""https://academico.quixada.ufc.br/ServletCentral?comando=CmdListarFrequenciaTurmaAluno&id=$id""") 96 | .header("Content-Type", "application/x-www-form-urlencoded") 97 | .header("Cookie", jsession) 98 | .build() 99 | withContext(Dispatchers.IO){ 100 | val response = client.newCall(request).execute() 101 | if (!response.isSuccessful) { 102 | showErrorConnection() 103 | } 104 | else{ 105 | val res = response.body()!!.string() 106 | val serializer = Serializer() 107 | val news = serializer.parseNews(id, res) 108 | println(news) 109 | runOnUiThread { 110 | swiperefresh_noticias.isRefreshing = false 111 | recyclerView_noticias.layoutManager = LinearLayoutManager(context) 112 | recyclerView_noticias.adapter = NoticiasAdapter(news) 113 | } 114 | } 115 | } 116 | 117 | } 118 | override fun onCreateView( 119 | inflater: LayoutInflater, container: ViewGroup?, 120 | savedInstanceState: Bundle? 121 | ): View? { 122 | return inflater.inflate(R.layout.fragment_noticias, container, false) 123 | } 124 | 125 | 126 | companion object { 127 | @JvmStatic 128 | fun newInstance(idDisciplina: String) = 129 | NoticiasFragment().apply { 130 | arguments = Bundle().apply { 131 | id = idDisciplina 132 | } 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/Fragments/PlanoAulaFragment.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa 2 | 3 | 4 | import android.os.Bundle 5 | import android.util.Log 6 | import androidx.fragment.app.Fragment 7 | import android.view.LayoutInflater 8 | import android.view.View 9 | import android.view.ViewGroup 10 | import androidx.core.content.ContextCompat 11 | import androidx.recyclerview.widget.LinearLayoutManager 12 | import com.google.android.material.snackbar.Snackbar 13 | import com.rodrigmatrix.sippa.persistence.StudentsDatabase 14 | import com.rodrigmatrix.sippa.serializer.Serializer 15 | import kotlinx.android.synthetic.main.fragment_plano_aula.* 16 | import kotlinx.coroutines.* 17 | import okhttp3.OkHttpClient 18 | import okhttp3.Request 19 | import org.jetbrains.anko.support.v4.runOnUiThread 20 | import kotlin.coroutines.CoroutineContext 21 | 22 | 23 | class PlanoAulaFragment : Fragment(), CoroutineScope { 24 | var id = "" 25 | private var job: Job = Job() 26 | override val coroutineContext: CoroutineContext get() = Dispatchers.IO + job 27 | lateinit var database: StudentsDatabase 28 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 29 | swiperefresh_plano.setColorSchemeResources(R.color.colorPrimary) 30 | database = StudentsDatabase.invoke(context!!) 31 | var jsession = database.studentDao().getStudent().jsession 32 | launch(handler) { 33 | setPlano(jsession) 34 | } 35 | swiperefresh_plano?.setProgressBackgroundColorSchemeColor(ContextCompat.getColor(view.context, R.color.colorSwipeRefresh)) 36 | swiperefresh_plano?.setOnRefreshListener { 37 | setPlano(jsession) 38 | } 39 | } 40 | private fun setPlano(jsession: String){ 41 | if(jsession == "offline"){ 42 | var plan = database.studentDao().getClassPlan(id) 43 | runOnUiThread { 44 | var lastUpdate = database.studentDao().getStudent().lastUpdate 45 | Snackbar.make(view!!, "Modo offline. Última atualização de dados: $lastUpdate", Snackbar.LENGTH_LONG).show() 46 | swiperefresh_plano.isRefreshing = false 47 | recyclerView_plano.layoutManager = LinearLayoutManager(context) 48 | recyclerView_plano.adapter = PlanoAdapter(plan) 49 | } 50 | } 51 | else{ 52 | swiperefresh_plano?.isRefreshing = true 53 | launch(handler) { 54 | setClass(id, jsession) 55 | } 56 | } 57 | } 58 | override fun onStop() { 59 | job.cancel() 60 | coroutineContext.cancel() 61 | super.onStop() 62 | } 63 | override fun onDestroy() { 64 | job.cancel() 65 | coroutineContext.cancel() 66 | super.onDestroy() 67 | } 68 | private val handler = CoroutineExceptionHandler { _, throwable -> 69 | Log.e("Exception", ":$throwable") 70 | } 71 | private fun isConnected(): Boolean{ 72 | val cd = ConnectionDetector() 73 | if(!cd.isConnectingToInternet(view!!.context)){ 74 | runOnUiThread { 75 | val snackbar = Snackbar.make(view!!, "Verifique sua conexão com a internet", Snackbar.LENGTH_LONG) 76 | snackbar.show() 77 | swiperefresh_plano.isRefreshing = false 78 | } 79 | return false 80 | } 81 | return true 82 | } 83 | private fun showErrorConnection(){ 84 | runOnUiThread { 85 | swiperefresh_plano!!.isRefreshing = false 86 | val snackbar = Snackbar.make(view!!, "Verifique sua conexão com a internet", Snackbar.LENGTH_LONG) 87 | snackbar.show() 88 | } 89 | } 90 | private suspend fun setClass(id: String, jsession: String){ 91 | if(!isConnected()){return} 92 | val client = OkHttpClient() 93 | val request = Request.Builder() 94 | .url("""https://academico.quixada.ufc.br/ServletCentral?comando=CmdListarFrequenciaTurmaAluno&id=$id""") 95 | .header("Content-Type", "application/x-www-form-urlencoded") 96 | .header("Cookie", jsession) 97 | .build() 98 | withContext(Dispatchers.IO){ 99 | val response = client.newCall(request).execute() 100 | if (!response.isSuccessful) { 101 | runOnUiThread { 102 | showErrorConnection() 103 | } 104 | } 105 | else{ 106 | val res = response.body()!!.string() 107 | val serializer = Serializer() 108 | var plan = serializer.parseClassPlan(id, res) 109 | runOnUiThread { 110 | swiperefresh_plano.isRefreshing = false 111 | recyclerView_plano.layoutManager = LinearLayoutManager(context) 112 | recyclerView_plano.adapter = PlanoAdapter(plan) 113 | } 114 | } 115 | } 116 | } 117 | 118 | 119 | override fun onCreateView( 120 | inflater: LayoutInflater, container: ViewGroup?, 121 | savedInstanceState: Bundle? 122 | ): View? { 123 | // Inflate the layout for this fragment 124 | return inflater.inflate(R.layout.fragment_plano_aula, container, false) 125 | } 126 | 127 | 128 | companion object { 129 | @JvmStatic 130 | fun newInstance(idDisciplina: String) = 131 | PlanoAulaFragment().apply { 132 | id = idDisciplina 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/RemoteConfig.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa 2 | 3 | import com.google.firebase.remoteconfig.FirebaseRemoteConfig 4 | import com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings 5 | import com.google.gson.Gson 6 | import com.rodrigmatrix.sippa.entity.Version 7 | import com.rodrigmatrix.sippa.entity.Versions 8 | import java.lang.Exception 9 | 10 | // Created by Rodrigo G. Resende on 2019-12-25. 11 | 12 | class RemoteConfig(private val remoteConfig: FirebaseRemoteConfig){ 13 | 14 | fun initRemoteConfig(){ 15 | val configSettings = FirebaseRemoteConfigSettings.Builder() 16 | .setMinimumFetchIntervalInSeconds(3600) 17 | .build() 18 | remoteConfig.setConfigSettingsAsync(configSettings) 19 | remoteConfig.fetch() 20 | .addOnSuccessListener { 21 | remoteConfig.activate() 22 | } 23 | } 24 | 25 | fun getVersions(): List { 26 | val versions = remoteConfig.getString("sippa_updates") 27 | return try { 28 | Gson().fromJson(versions, Versions::class.java).versions 29 | } 30 | catch(e: Exception){ 31 | listOf() 32 | } 33 | } 34 | 35 | 36 | } -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/Serializer/Attendance.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa.serializer 2 | 3 | data class Attendance ( 4 | var totalAttendance: Int, 5 | var totalMissed: Int 6 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/Serializer/Serializer.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa.serializer 2 | 3 | import com.rodrigmatrix.sippa.persistance.* 4 | import org.jsoup.Jsoup 5 | import java.lang.IndexOutOfBoundsException 6 | import java.lang.Math.random 7 | 8 | class Serializer { 9 | 10 | fun parseClasses(response: String): MutableList{ 11 | val classes: MutableList = mutableListOf() 12 | var size = 1 13 | var count = 0 14 | val studentClass = Class("", "", "", "", "", 0, 0, 0) 15 | Jsoup.parse(response).run { 16 | val tag = select("a[href]") 17 | tag.forEach{ 18 | if(it.attr("href").contains("id=")){ 19 | count++ 20 | when (count) { 21 | 1 -> { 22 | val arr = it.attr("href").split("id=") 23 | when { 24 | arr.size >= 2 -> studentClass.id = arr[1] 25 | else -> studentClass.id = "1" 26 | } 27 | } 28 | 2 -> { 29 | studentClass.name = it.text() 30 | } 31 | 3 -> { 32 | studentClass.professorName = it.text() 33 | } 34 | 5 -> { 35 | studentClass.percentageAttendance = it.text() 36 | count = 0 37 | size++ 38 | classes.add(Class(studentClass.id, studentClass.name, studentClass.professorName, studentClass.professorEmail, 39 | studentClass.percentageAttendance, 0, studentClass.missed, 1)) 40 | } 41 | } 42 | } 43 | } 44 | } 45 | return classes 46 | } 47 | 48 | fun parseAttendance(response: String): Attendance{ 49 | val attendance = response.split("de Frequência; ", " Presenças em Horas;") 50 | val missed = response.split("Presenças em Horas; ", " Faltas em Horas") 51 | return if(attendance.size >= 2 && missed.size >= 2){ 52 | Attendance(attendance[1].toInt(), missed[1].toInt()) 53 | } else{ 54 | Attendance(0,0) 55 | } 56 | } 57 | 58 | fun parseClassPlan(classId: String, response: String): MutableList{ 59 | val res = response.replace("", "") 60 | val classesPlan = mutableListOf() 61 | val classPlan = ClassPlan(random().toInt(), "", "", "", "", "") 62 | val document = Jsoup.parse(res) 63 | val tbody = document.getElementsByTag("tbody") 64 | val plan = tbody.select("td") 65 | var count = 1 66 | plan.forEach{ 67 | when(count){ 68 | 1 -> { 69 | classPlan.date = "Nº " + it.text() 70 | } 71 | 2 -> { 72 | val arr = it.text() 73 | var date = "Data não cadastrada" 74 | var content = "Plano não cadastrado" 75 | if(arr.isNotEmpty() && arr.length >= 10){ 76 | date = arr.replaceRange(10, arr.length, "") 77 | content = arr.replaceRange(0,10, "") 78 | } 79 | classPlan.date = date 80 | classPlan.planned = content 81 | } 82 | 3 -> { 83 | val arr = it.text() 84 | when { 85 | arr != "" -> { 86 | var content = "" 87 | if(arr.isNotEmpty() && arr.length >= 10){ 88 | content = arr.replaceRange(0,10, "") 89 | } 90 | when(content){ 91 | "" -> classPlan.diary = "Não cadastrado" 92 | else -> classPlan.diary = content 93 | } 94 | } 95 | else -> classPlan.diary = "Aula ainda não foi apresentada" 96 | } 97 | } 98 | 4 -> { 99 | when { 100 | it.text() == "" -> classPlan.attendance = "Frequência não cadastrada" 101 | it.text().toInt() > 0 -> classPlan.attendance = "Presente: " + "2" + " horas" 102 | else -> classPlan.attendance = "Falta: 2 horas" 103 | } 104 | classesPlan.add(ClassPlan(random().toInt(), classId, classPlan.date, classPlan.planned, classPlan.attendance, classPlan.diary)) 105 | count = 0 106 | } 107 | } 108 | count++ 109 | } 110 | if(classesPlan.size == 0){ 111 | classesPlan.add(ClassPlan(random().toInt(), classId,"Plano não criado","Este professor não cadastrou nenhum plano de aula nessa disciplina", "", "")) 112 | } 113 | return classesPlan 114 | } 115 | 116 | fun parseProfessorEmail(response: String): String{ 117 | Jsoup.parse(response).run { 118 | val email = getElementsByTag("h2") 119 | return try { 120 | val arr = email[0] 121 | val split = arr.text().split("- ", "<") 122 | if(split.isNotEmpty() && split.size >= 2){ 123 | split[1] 124 | } else{ 125 | "Email não cadastrado" 126 | } 127 | }catch(e: IndexOutOfBoundsException){ 128 | "Email não encontrado" 129 | } 130 | } 131 | } 132 | 133 | fun parseGrades(classId: String, response: String): MutableList{ 134 | //Precisa usar api.setClass para não dar erro 135 | val gradesList: MutableList = mutableListOf() 136 | Jsoup.parse(response).run { 137 | val thead = getElementsByTag("thead") 138 | val names = thead.select("th") 139 | val tbody = getElementsByTag("tbody") 140 | val grades = tbody.select("td") 141 | var index = 2 142 | names.forEach{ 143 | if(it.text() != "Aluno"){ 144 | val grade = Grade(random().toInt(), classId, it.text(), grades[index].text()) 145 | gradesList.add(grade) 146 | index++ 147 | } 148 | } 149 | } 150 | return gradesList 151 | } 152 | 153 | fun parseNews(classId: String, response: String): MutableList{ 154 | //Precisa usar api.setClass para não dar erro 155 | val newsList: MutableList = mutableListOf() 156 | Jsoup.parse(response).run { 157 | val coluna0 = getElementsByClass("tabela-coluna0") 158 | val coluna1 = getElementsByClass("tabela-coluna1") 159 | for ((index, date) in coluna0.withIndex()) { 160 | val news = News(random().toInt(), classId, date.text(), coluna1[index].text()) 161 | newsList.add(news) 162 | } 163 | } 164 | return newsList 165 | } 166 | 167 | fun parseHorasComplementares(response: String): MutableList{ 168 | val horas = mutableListOf() 169 | var id = 0 170 | Jsoup.parse(response).run { 171 | val body = getElementsByTag("td") 172 | val horaDef = HoraComplementar(random().toInt(), "", "", "") 173 | var index = 1 174 | body.forEach{ 175 | when(index){ 176 | 1 -> { 177 | horaDef.name = it.text() 178 | } 179 | 3 -> { 180 | horaDef.professor = it.text() 181 | } 182 | 4 -> { 183 | horaDef.total = """Horas ganhas: ${it.text()}""" 184 | horas.add(HoraComplementar(id, horaDef.name, "Professor: " + horaDef.professor, horaDef.total)) 185 | index = 0 186 | } 187 | } 188 | id++ 189 | index++ 190 | } 191 | } 192 | var arr = response.split("Total de Horas em Atividades Complementares: ") 193 | arr = arr[1].split("") 194 | horas.add(HoraComplementar(id,"Total de Horas Complementares", " ", "Total: "+arr[0])) 195 | return horas 196 | } 197 | 198 | fun parseFiles(classId: String,response: String): MutableList{ 199 | //Precisa usar api.setClass para não dar erro 200 | val filesList: MutableList = mutableListOf() 201 | var id = 0 202 | Jsoup.parse(response).run { 203 | val files = select("a[href]") 204 | files.forEach{ 205 | if(it.attr("href").contains("id=")){ 206 | val arr = it.attr("href").split("id=") 207 | filesList.add(File(random().toInt(), classId, arr[1])) 208 | } 209 | id++ 210 | } 211 | } 212 | if(filesList.size == 0){ 213 | filesList.add(File(random().toInt(),classId,"Nenhum arquivo disponível nessa disciplina")) 214 | } 215 | return filesList 216 | } 217 | } -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/SippaApp.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa 2 | 3 | import android.app.Application 4 | import android.util.Log 5 | import androidx.appcompat.app.AppCompatDelegate 6 | import com.google.android.gms.tasks.OnCompleteListener 7 | import com.google.firebase.iid.FirebaseInstanceId 8 | import com.google.firebase.remoteconfig.FirebaseRemoteConfig 9 | import com.rodrigmatrix.sippa.persistence.StudentsDatabase 10 | 11 | // Created by Rodrigo G. Resende on 2019-11-16. 12 | 13 | class SippaApp : Application(){ 14 | 15 | 16 | override fun onCreate() { 17 | super.onCreate() 18 | RemoteConfig(FirebaseRemoteConfig.getInstance()).initRemoteConfig() 19 | setTheme() 20 | //fcmId() 21 | } 22 | 23 | private fun setTheme(){ 24 | val db = StudentsDatabase(applicationContext) 25 | var student = db.studentDao().getStudent() 26 | if(student != null){ 27 | when (student.theme) { 28 | "light" -> { 29 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) 30 | } 31 | "dark" -> { 32 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) 33 | } 34 | "automatic" -> { 35 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) 36 | } 37 | } 38 | } 39 | } 40 | 41 | private fun fcmId(){ 42 | val TAG = "fcm" 43 | FirebaseInstanceId.getInstance().instanceId 44 | .addOnCompleteListener(OnCompleteListener { task -> 45 | if (!task.isSuccessful) { 46 | Log.w(TAG, "getInstanceId failed", task.exception) 47 | return@OnCompleteListener 48 | } 49 | 50 | // Get new Instance ID token 51 | val token = task.result?.token 52 | 53 | Log.d(TAG, token) 54 | }) 55 | } 56 | } -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/entity/Version.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa.entity 2 | 3 | 4 | import com.google.gson.annotations.SerializedName 5 | 6 | data class Version( 7 | @SerializedName("updateType") 8 | val updateType: Int, 9 | @SerializedName("versionCode") 10 | val versionCode: Int 11 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/entity/Versions.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa.entity 2 | 3 | 4 | import com.google.gson.annotations.SerializedName 5 | 6 | data class Versions( 7 | @SerializedName("versions") 8 | val versions: List 9 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/firebase/FirebaseCloudMessaging.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa.firebase 2 | 3 | import android.annotation.TargetApi 4 | import android.app.NotificationChannel 5 | import android.app.NotificationManager 6 | import android.app.PendingIntent 7 | import android.content.Context 8 | import android.content.Intent 9 | import android.media.RingtoneManager 10 | import android.os.Build 11 | import androidx.core.app.NotificationCompat 12 | import com.google.firebase.messaging.FirebaseMessagingService 13 | import com.google.firebase.messaging.RemoteMessage 14 | import com.rodrigmatrix.sippa.HomeActivity 15 | import com.rodrigmatrix.sippa.LoginActivity 16 | import com.rodrigmatrix.sippa.R 17 | 18 | // Created by Rodrigo G. Resende on 2019-11-16. 19 | 20 | class FirebaseCloudMessaging: FirebaseMessagingService() { 21 | 22 | 23 | private val channelId = "GENERAL" 24 | 25 | override fun onMessageReceived(remoteMessage: RemoteMessage) { 26 | handleOnlyDataPayload(remoteMessage.data, remoteMessage.notification?.title, remoteMessage.notification?.body) 27 | } 28 | 29 | private fun handleOnlyDataPayload(payload: MutableMap, title: String?, body: String?) { 30 | if (payload.containsKey("link")) { 31 | openLink(payload["link"]!!, title, body) 32 | return 33 | } 34 | else { 35 | openNormalNotification(title, body) 36 | } 37 | } 38 | 39 | @TargetApi(Build.VERSION_CODES.O) 40 | private fun createNotificationChannel() { 41 | val name = "Geral" 42 | val descriptionText = "Notificações gerais do app" 43 | val importance = NotificationManager.IMPORTANCE_DEFAULT 44 | val mChannel = NotificationChannel(channelId, name, importance) 45 | mChannel.description = descriptionText 46 | val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager 47 | notificationManager.createNotificationChannel(mChannel) 48 | } 49 | 50 | private fun openLink(link: String?, title: String?, body: String?) { 51 | val intent = Intent(this, LoginActivity::class.java) 52 | intent.putExtra("link", link) 53 | val pendingIntent = PendingIntent.getActivity(this, 0, intent, 54 | PendingIntent.FLAG_UPDATE_CURRENT) 55 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 56 | createNotificationChannel() 57 | } 58 | showNotification(title, body, pendingIntent) 59 | } 60 | 61 | 62 | private fun showNotification(title: String?, body: String?, pendingIntent: PendingIntent) { 63 | val soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) 64 | val notificationBuilder = NotificationCompat.Builder(this, channelId) 65 | .setContentTitle(title) 66 | .setSmallIcon(R.drawable.ic_stat_sippa) 67 | .setContentText(body) 68 | .setAutoCancel(true) 69 | .setSound(soundUri) 70 | .setContentIntent(pendingIntent) 71 | val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager 72 | notificationManager.notify(0, notificationBuilder.build()) 73 | } 74 | 75 | private fun openNormalNotification(title: String?, body: String?) { 76 | val intent = Intent(this, HomeActivity::class.java) 77 | intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) 78 | val pendingIntent = PendingIntent.getActivity(this, 0, intent, 79 | PendingIntent.FLAG_ONE_SHOT) 80 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 81 | createNotificationChannel() 82 | } 83 | showNotification(title, body, pendingIntent) 84 | } 85 | } -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/persistence/Student.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa.persistance 2 | 3 | import androidx.room.Entity 4 | import androidx.room.PrimaryKey 5 | 6 | @Entity(tableName = "students") 7 | data class Student( 8 | @PrimaryKey 9 | var id: Int, 10 | var jsession: String, 11 | var responseHtml: String, 12 | var classSetHtml: String, 13 | var login: String, 14 | var password: String, 15 | var name: String, 16 | var matricula: String, 17 | var theme: String, 18 | var hasSavedData: Boolean, 19 | var lastUpdate: String 20 | ) 21 | 22 | @Entity(tableName = "classes") 23 | data class Class( 24 | @PrimaryKey 25 | var id: String, 26 | var name: String, 27 | var professorName: String, 28 | var professorEmail: String, 29 | var percentageAttendance: String, 30 | var credits: Int, 31 | var missed: Int, 32 | var totalAttendance: Int 33 | ) 34 | 35 | @Entity(tableName = "news") 36 | data class News( 37 | @PrimaryKey(autoGenerate = true) 38 | var id: Int, 39 | var classId: String, 40 | var date: String, 41 | var content: String 42 | ) 43 | 44 | @Entity(tableName = "grades") 45 | class Grade( 46 | @PrimaryKey(autoGenerate = true) 47 | var id: Int, 48 | var classId: String, 49 | var name: String, 50 | var grade: String 51 | ) 52 | 53 | @Entity(tableName = "classPlan") 54 | data class ClassPlan( 55 | @PrimaryKey(autoGenerate = true) 56 | var id: Int, 57 | var classId: String, 58 | var date: String, 59 | var attendance: String, 60 | var planned: String, 61 | var diary: String 62 | ) 63 | 64 | @Entity(tableName = "files") 65 | data class File( 66 | @PrimaryKey 67 | var id: Int, 68 | var classId: String, 69 | var name: String 70 | ) 71 | 72 | @Entity(tableName = "horasComplementares") 73 | data class HoraComplementar( 74 | @PrimaryKey 75 | var id: Int, 76 | var name: String, 77 | var professor: String, 78 | var total: String 79 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/persistence/StudentDao.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa.persistance 2 | 3 | import androidx.room.* 4 | 5 | 6 | @Dao 7 | interface StudentDao { 8 | 9 | @Query("SELECT * FROM students where id = 0") 10 | fun getStudent(): Student 11 | 12 | @Insert(onConflict = OnConflictStrategy.REPLACE) 13 | fun insertStudent(student: Student) 14 | 15 | @Query("DELETE FROM students") 16 | fun deleteStudent() 17 | 18 | 19 | 20 | @Query("SELECT * FROM classes") 21 | fun getClasses(): MutableList 22 | 23 | @Insert(onConflict = OnConflictStrategy.REPLACE) 24 | fun insertClass(studentClass: Class) 25 | 26 | @Query("DELETE FROM classes") 27 | fun deleteClasses() 28 | 29 | 30 | 31 | @Query("SELECT * FROM news WHERE classId LIKE :id") 32 | fun getNews(id: String): MutableList 33 | 34 | @Insert(onConflict = OnConflictStrategy.REPLACE) 35 | fun insertNews(news: News) 36 | 37 | @Query("DELETE FROM news") 38 | fun deleteNews() 39 | 40 | @Query("DELETE FROM news WHERE classId LIKE :id") 41 | fun deleteNewsFromClass(id: String) 42 | 43 | 44 | 45 | @Query("SELECT * FROM grades WHERE classId LIKE :id") 46 | fun getGrades(id: String): MutableList 47 | 48 | @Insert(onConflict = OnConflictStrategy.REPLACE) 49 | fun insertGrade(grade: Grade) 50 | 51 | @Query("DELETE FROM grades") 52 | fun deleteGrades() 53 | 54 | @Query("DELETE FROM grades WHERE classId LIKE :id") 55 | fun deleteGradesFromClass(id: String) 56 | 57 | 58 | 59 | @Query("SELECT * FROM classPlan WHERE classId LIKE :id") 60 | fun getClassPlan(id: String): MutableList 61 | 62 | @Insert(onConflict = OnConflictStrategy.REPLACE) 63 | fun insertClassPlan(classPlan: ClassPlan) 64 | 65 | @Query("DELETE FROM classPlan") 66 | fun deleteClassPlan() 67 | 68 | @Query("DELETE FROM classPlan WHERE classId LIKE :id") 69 | fun deleteClassPlanFromClass(id: String) 70 | 71 | 72 | 73 | @Query("SELECT * FROM files WHERE classId LIKE :id") 74 | fun getFiles(id: String): MutableList 75 | 76 | @Insert(onConflict = OnConflictStrategy.REPLACE) 77 | fun insertFile(file: File) 78 | 79 | @Query("DELETE FROM files") 80 | fun deleteFiles() 81 | 82 | @Query("DELETE FROM files WHERE classId LIKE :id") 83 | fun deleteFilesFromClass(id: String) 84 | 85 | 86 | 87 | @Query("SELECT * FROM horasComplementares") 88 | fun getHoras(): MutableList 89 | 90 | @Insert(onConflict = OnConflictStrategy.REPLACE) 91 | fun insertHora(hora: HoraComplementar) 92 | 93 | @Query("DELETE FROM horasComplementares") 94 | fun deleteHoras() 95 | } -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/persistence/StudentsDatabase.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa.persistence 2 | 3 | import android.content.Context 4 | import androidx.room.Database 5 | import androidx.room.Room 6 | import androidx.room.RoomDatabase 7 | import com.rodrigmatrix.sippa.persistance.* 8 | 9 | @Database(entities = [Student::class, Class::class, News::class, Grade::class, ClassPlan::class, File::class, HoraComplementar::class], version = 19, exportSchema = false) 10 | abstract class StudentsDatabase : RoomDatabase() { 11 | 12 | abstract fun studentDao(): StudentDao 13 | 14 | companion object { 15 | 16 | @Volatile private var instance: StudentsDatabase? = null 17 | private val LOCK = Any() 18 | 19 | operator fun invoke(context: Context)= instance ?: synchronized(LOCK){ 20 | instance ?: buildDatabase(context).also { instance = it} 21 | } 22 | 23 | private fun buildDatabase(context: Context) = 24 | Room.databaseBuilder( 25 | context.applicationContext, 26 | StudentsDatabase::class.java, "database.db") 27 | .fallbackToDestructiveMigration() 28 | .allowMainThreadQueries() 29 | .build() 30 | } 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/ui/main/PageViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa.ui.main 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.lifecycle.MutableLiveData 5 | import androidx.lifecycle.Transformations 6 | import androidx.lifecycle.ViewModel 7 | import androidx.lifecycle.ViewModelProvider 8 | 9 | class PageViewModel : ViewModel() { 10 | 11 | private val _index = MutableLiveData() 12 | val text: LiveData = Transformations.map(_index) { 13 | "Hello world from section: $it" 14 | } 15 | 16 | fun setIndex(index: Int) { 17 | _index.value = index 18 | } 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/ui/main/PlaceholderFragment.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa.ui.main 2 | 3 | import android.os.Bundle 4 | import androidx.fragment.app.Fragment 5 | import androidx.lifecycle.ViewModelProviders 6 | 7 | class PlaceholderFragment : Fragment() { 8 | 9 | private lateinit var pageViewModel: PageViewModel 10 | 11 | override fun onCreate(savedInstanceState: Bundle?) { 12 | super.onCreate(savedInstanceState) 13 | pageViewModel = ViewModelProviders.of(this).get(PageViewModel::class.java).apply { 14 | } 15 | } 16 | 17 | 18 | companion object { 19 | @JvmStatic 20 | fun newInstance(): PlaceholderFragment { 21 | return PlaceholderFragment().apply { 22 | arguments = Bundle().apply { 23 | } 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/rodrigmatrix/sippa/ui/main/SectionsPagerAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa.ui.main 2 | 3 | import android.content.Context 4 | import androidx.fragment.app.Fragment 5 | import androidx.fragment.app.FragmentManager 6 | import androidx.fragment.app.FragmentPagerAdapter 7 | import com.rodrigmatrix.sippa.* 8 | import java.util.ArrayList 9 | 10 | private var fragmentList = arrayListOf() 11 | private val titleList = listOf( "Avisos", "Notas", "Aulas", "Arquivos") 12 | 13 | class SectionsPagerAdapter(private val context: Context, fm: FragmentManager) : FragmentPagerAdapter(fm) { 14 | 15 | override fun getItem(position: Int): Fragment { 16 | return fragmentList[position] 17 | } 18 | 19 | fun addFragment(fragment: Fragment){ 20 | fragmentList.add(fragment) 21 | } 22 | 23 | fun removeFragments(){ 24 | fragmentList.removeAll(fragmentList) 25 | } 26 | 27 | override fun getPageTitle(position: Int): CharSequence? { 28 | return titleList[position] 29 | } 30 | 31 | override fun getCount(): Int { 32 | return titleList.size 33 | } 34 | } -------------------------------------------------------------------------------- /app/src/main/res/anim/item_animation_fall_down.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 9 | 10 | 15 | 16 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/anim/layout_animation_fall_down.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/book_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/campus.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/drawable/campus.jpeg -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arquivos_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_back_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_detalhes_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_group_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 22 | 24 | 26 | 28 | 30 | 32 | 34 | 36 | 38 | 40 | 42 | 44 | 46 | 48 | 50 | 52 | 54 | 56 | 58 | 60 | 62 | 64 | 66 | 68 | 70 | 72 | 74 | 75 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_notas_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_noticias_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_person_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_plano_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_refresh_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_stat_sippa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/drawable/ic_stat_sippa.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_sigaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/drawable/icon_sigaa.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/info_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/profile_pic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/drawable/profile_pic.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/side_nav_bar.xml: -------------------------------------------------------------------------------- 1 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/sippa_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/drawable/sippa_logo.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_disciplina.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 24 | 31 | 32 | 39 | 40 | 41 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 16 | 17 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_login.xml: -------------------------------------------------------------------------------- 1 | 10 | 19 | 24 | 31 | 38 | 39 | 49 | 50 | 55 | 56 | 57 | 66 | 67 | 72 | 73 | 74 | 80 | 81 | 87 | 88 | 98 | 99 | 104 | 105 | 106 | 116 | 117 | 118 | 125 | 126 | 127 | 128 | 129 | 130 | 136 | 140 | 149 | 150 | 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /app/src/main/res/layout/app_bar_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 24 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/res/layout/arquivo_row.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 20 | 21 | 25 | 26 | 36 | 37 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /app/src/main/res/layout/aula_row.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 20 | 23 | 24 | 25 | 35 | 45 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /app/src/main/res/layout/content_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/layout/disciplina_row.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 20 | 21 | 25 | 26 | 40 | 41 | 51 | 61 | 62 | 72 | 73 | 83 | 84 | 89 | 93 | 97 | 109 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_arquivos.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_disciplina.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_disciplinas.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 18 | 19 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_horas.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 13 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_info.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 22 | 23 | 29 | 39 | 49 | 50 | 62 | 63 | 75 | 76 | 86 | 99 | 105 | 106 | 118 | 119 | 131 | 132 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_notas.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_noticias.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_plano_aula.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/horas_row.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 22 | 23 | 27 | 28 | 42 | 53 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /app/src/main/res/layout/nav_header_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 28 | 39 | 40 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /app/src/main/res/layout/nota_row.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 23 | 24 | 28 | 29 | 42 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /app/src/main/res/layout/noticia_row.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 21 | 22 | 26 | 27 | 28 | 39 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /app/src/main/res/layout/plano_row.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 21 | 22 | 26 | 27 | 41 | 42 | 51 | 52 | 66 | 67 | 80 | 81 | 94 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /app/src/main/res/menu/activity_home_drawer.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 15 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_theme.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 10 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #6175B1 4 | #6175B1 5 | #6175B1 6 | #FFFFFF 7 | #121212 8 | #121212 9 | #202020 10 | #84c8a6 11 | #6175B1 12 | #cf6679 13 | #fff356 14 | #36f725 15 | #f2851f 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values-v27/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #6175B1 4 | #6175B1 5 | #6175B1 6 | #FFFFFF 7 | #121212 8 | #FFFFFF 9 | #FFFFFF 10 | #84c8a6 11 | #6175B1 12 | #b00020 13 | #fff356 14 | #54ff05 15 | #f2851f 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 25dp 5 | 5dp 6 | 176dp 7 | 16dp 8 | 16dp 9 | 8dp 10 | 16dp 11 | -------------------------------------------------------------------------------- /app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Sippa 3 | Efetue login em sua conta do SIPPA 4 | Login 5 | Senha 6 | Login 7 | TesteActivity 8 | Venda 9 | Conexão 10 | Histórico 11 | Caixa 12 | Captcha 13 | Home 14 | Open navigation drawer 15 | Close navigation drawer 16 | Nome do Aluno 17 | Matrícula 18 | Navigation header 19 | Settings 20 | Disciplinas 21 | Horas Complementares 22 | Gallery 23 | Slideshow 24 | Tools 25 | Sobre 26 | Disciplina 27 | Tab 1 28 | Tab 2 29 | Qualidade de Software 30 | Hello blank fragment 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | -------------------------------------------------------------------------------- /app/src/test/java/com/rodrigmatrix/sippa/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.rodrigmatrix.sippa 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext.kotlin_version = '1.4.20' 5 | repositories { 6 | google() 7 | jcenter() 8 | maven { 9 | url 'https://maven.fabric.io/public' 10 | } 11 | } 12 | dependencies { 13 | classpath 'com.android.tools.build:gradle:3.5.4' 14 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 15 | classpath 'com.google.gms:google-services:4.3.5' 16 | classpath 'com.google.firebase:firebase-crashlytics-gradle:2.5.1' 17 | // NOTE: Do not place your application dependencies here; they belong 18 | // in the individual module build.gradle files 19 | } 20 | } 21 | 22 | 23 | 24 | allprojects { 25 | repositories { 26 | google() 27 | jcenter() 28 | maven { 29 | url 'https://jitpack.io' 30 | } 31 | } 32 | } 33 | 34 | task clean(type: Delete) { 35 | delete rootProject.buildDir 36 | } 37 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official 22 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Jun 09 11:30:23 BRT 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/gradlew -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /keystore/keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigmatrix/sippa_android/2414421f9a925c1e2ce5509949b08c369191fb4f/keystore/keystore -------------------------------------------------------------------------------- /privacy_policy: -------------------------------------------------------------------------------- 1 | Política de privacidade para Sippa 2 | Todas as suas informações pessoais recolhidas, serão usadas para o ajudar a tornar a sua visita no nosso site o mais produtiva e agradável possível. 3 | 4 | A garantia da confidencialidade dos dados pessoais dos utilizadores do nosso site é importante para o Sippa. 5 | 6 | Todas as informações pessoais relativas a membros, assinantes, clientes ou visitantes que usem o Sippa serão tratadas em concordância com a Lei da Proteção de Dados Pessoais de 26 de outubro de 1998 (Lei n.º 67/98). 7 | 8 | A informação pessoal recolhida pode incluir o seu nome, e-mail, número de telefone e/ou telemóvel, morada, data de nascimento e/ou outros. 9 | 10 | O uso do Sippa pressupõe a aceitação deste Acordo de privacidade. A equipa do Sippa reserva-se ao direito de alterar este acordo sem aviso prévio. Deste modo, recomendamos que consulte a nossa política de privacidade com regularidade de forma a estar sempre atualizado. 11 | 12 | Os anúncios 13 | Tal como outros websites, coletamos e utilizamos informação contida nos anúncios. A informação contida nos anúncios, inclui o seu endereço IP (Internet Protocol), o seu ISP (Internet Service Provider, como o Sapo, Clix, ou outro), o browser que utilizou ao visitar o nosso website (como o Internet Explorer ou o Firefox), o tempo da sua visita e que páginas visitou dentro do nosso website. 14 | 15 | Cookie DoubleClick Dart 16 | O Google, como fornecedor de terceiros, utiliza cookies para exibir anúncios no nosso website; 17 | 18 | Com o cookie DART, o Google pode exibir anúncios com base nas visitas que o leitor fez a outros websites na Internet; 19 | 20 | Os utilizadores podem desativar o cookie DART visitando a Política de privacidade da rede de conteúdo e dos anúncios do Google. 21 | 22 | Ligações a Sites de terceiros 23 | O Sippa possui ligações para outros sites, os quais, a nosso ver, podem conter informações / ferramentas úteis para os nossos visitantes. A nossa política de privacidade não é aplicada a sites de terceiros, pelo que, caso visite outro site a partir do nosso deverá ler a politica de privacidade do mesmo. 24 | 25 | Não nos responsabilizamos pela política de privacidade ou conteúdo presente nesses mesmos sites. 26 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | --------------------------------------------------------------------------------