├── .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 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
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 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
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 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
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 | [](https://www.apache.org/licenses/LICENSE-2.0)
2 |
3 |
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 | |||||
25 |
26 |
27 | | Notícias | Notas | Plano | Arquivos |
28 | |---|---|---|---|
29 | |||||
30 |
31 |
32 | ## Screenshots Light Theme
33 | | Disciplinas | Horas Complementares | Nav View | Login |
34 | |---|---|---|---|
35 | |||||
36 |
37 |
38 | | Notícias | Notas | Plano | Arquivos |
39 | |---|---|---|---|
40 | |||||
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 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_theme.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------