Browse Source

first commit

master
Chris Cromer 1 year ago
commit
4b9235a7b2
100 changed files with 10725 additions and 0 deletions
  1. +8
    -0
      .gitignore
  2. +1
    -0
      .idea/.name
  3. +22
    -0
      .idea/compiler.xml
  4. +3
    -0
      .idea/copyright/profiles_settings.xml
  5. +3
    -0
      .idea/dictionaries/cromer.xml
  6. +6
    -0
      .idea/encodings.xml
  7. +19
    -0
      .idea/gradle.xml
  8. +36
    -0
      .idea/misc.xml
  9. +9
    -0
      .idea/modules.xml
  10. +12
    -0
      .idea/runConfigurations.xml
  11. +15
    -0
      .navigation/attendance-ubb/raw/main.nvg.xml
  12. +1
    -0
      attendance-ubb/.gitignore
  13. +45
    -0
      attendance-ubb/build.gradle
  14. BIN
      attendance-ubb/libs/poi-3.14-beta1-20151223.jar
  15. +27
    -0
      attendance-ubb/proguard-rules.pro
  16. +123
    -0
      attendance-ubb/src/main/AndroidManifest.xml
  17. +44
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/About.java
  18. +60
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/Attendance.java
  19. +122
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/Class.java
  20. +1056
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/ClassList.java
  21. +77
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/ClassListAdapter.java
  22. +968
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/ClassReport.java
  23. +508
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/CorrectAttendance.java
  24. +126
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/Course.java
  25. +976
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/CourseList.java
  26. +80
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/CourseListAdapter.java
  27. +867
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/CourseReport.java
  28. +80
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/DBSchema.java
  29. +171
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/Excel.java
  30. +264
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/FileSystem.java
  31. +751
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/ImportExcel.java
  32. +411
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/ImportPhotos.java
  33. +508
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/LateStudentAttendance.java
  34. +11
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/ListenerDownload.java
  35. +81
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/Major.java
  36. +175
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/Progress.java
  37. +194
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/RUT.java
  38. +51
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/RecyclerClickListener.java
  39. +155
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/SQLParser.java
  40. +29
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/StaticVariables.java
  41. +27
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/StringFixer.java
  42. +113
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/Student.java
  43. +104
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/Subject.java
  44. +1584
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/SubjectList.java
  45. +96
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/SubjectListAdapter.java
  46. +572
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/TakeAttendance.java
  47. +7
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/TakeAttendanceListener.java
  48. +57
    -0
      attendance-ubb/src/main/java/cl/cromer/ubb/attendance/ZipFile.java
  49. +16
    -0
      attendance-ubb/src/main/res/anim/expand.xml
  50. +6
    -0
      attendance-ubb/src/main/res/anim/hold_back.xml
  51. +5
    -0
      attendance-ubb/src/main/res/anim/push_down_in.xml
  52. +6
    -0
      attendance-ubb/src/main/res/anim/push_right_out.xml
  53. +12
    -0
      attendance-ubb/src/main/res/anim/rotate.xml
  54. +16
    -0
      attendance-ubb/src/main/res/anim/shrink.xml
  55. BIN
      attendance-ubb/src/main/res/drawable-hdpi-v11/ic_stat_ubb.png
  56. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ic_stat_ubb.png
  57. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ic_ubb.png
  58. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ubb_logo.png
  59. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ubbtheme_btn_default_disabled_focused_holo_light.9.png
  60. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ubbtheme_btn_default_disabled_holo_light.9.png
  61. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ubbtheme_btn_default_focused_holo_light.9.png
  62. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ubbtheme_btn_default_normal_holo_light.9.png
  63. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ubbtheme_btn_default_pressed_holo_light.9.png
  64. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ubbtheme_list_focused_holo.9.png
  65. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ubbtheme_list_longpressed_holo.9.png
  66. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ubbtheme_list_pressed_holo_light.9.png
  67. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ubbtheme_list_selector_disabled_holo_light.9.png
  68. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ubbtheme_spinner_default_holo_light.9.png
  69. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ubbtheme_spinner_disabled_holo_light.9.png
  70. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ubbtheme_spinner_focused_holo_light.9.png
  71. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ubbtheme_spinner_pressed_holo_light.9.png
  72. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ubbtheme_textfield_activated_holo_light.9.png
  73. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ubbtheme_textfield_default_holo_light.9.png
  74. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ubbtheme_textfield_disabled_focused_holo_light.9.png
  75. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ubbtheme_textfield_disabled_holo_light.9.png
  76. BIN
      attendance-ubb/src/main/res/drawable-hdpi/ubbtheme_textfield_focused_holo_light.9.png
  77. BIN
      attendance-ubb/src/main/res/drawable-mdpi-v11/ic_stat_ubb.png
  78. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ic_stat_ubb.png
  79. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ic_ubb.png
  80. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ubb_logo.png
  81. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ubbtheme_btn_default_disabled_focused_holo_light.9.png
  82. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ubbtheme_btn_default_disabled_holo_light.9.png
  83. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ubbtheme_btn_default_focused_holo_light.9.png
  84. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ubbtheme_btn_default_normal_holo_light.9.png
  85. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ubbtheme_btn_default_pressed_holo_light.9.png
  86. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ubbtheme_list_focused_holo.9.png
  87. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ubbtheme_list_longpressed_holo.9.png
  88. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ubbtheme_list_pressed_holo_light.9.png
  89. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ubbtheme_list_selector_disabled_holo_light.9.png
  90. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ubbtheme_spinner_default_holo_light.9.png
  91. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ubbtheme_spinner_disabled_holo_light.9.png
  92. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ubbtheme_spinner_focused_holo_light.9.png
  93. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ubbtheme_spinner_pressed_holo_light.9.png
  94. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ubbtheme_textfield_activated_holo_light.9.png
  95. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ubbtheme_textfield_default_holo_light.9.png
  96. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ubbtheme_textfield_disabled_focused_holo_light.9.png
  97. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ubbtheme_textfield_disabled_holo_light.9.png
  98. BIN
      attendance-ubb/src/main/res/drawable-mdpi/ubbtheme_textfield_focused_holo_light.9.png
  99. +9
    -0
      attendance-ubb/src/main/res/drawable-v21/ic_menu_add.xml
  100. +0
    -0
      attendance-ubb/src/main/res/drawable-v21/ic_menu_correct.xml

+ 8
- 0
.gitignore View File

@@ -0,0 +1,8 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures

+ 1
- 0
.idea/.name View File

@@ -0,0 +1 @@
UBBAttendance

+ 22
- 0
.idea/compiler.xml View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
<entry name="!?*.aj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
</project>

+ 3
- 0
.idea/copyright/profiles_settings.xml View File

@@ -0,0 +1,3 @@
<component name="CopyrightManager">
<settings default="" />
</component>

+ 3
- 0
.idea/dictionaries/cromer.xml View File

@@ -0,0 +1,3 @@
<component name="ProjectDictionaryState">
<dictionary name="cromer" />
</component>

+ 6
- 0
.idea/encodings.xml View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>

+ 19
- 0
.idea/gradle.xml View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="1.7" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/attendance-ubb" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>

+ 36
- 0
.idea/misc.xml View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

+ 9
- 0
.idea/modules.xml View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/UBBAttendance.iml" filepath="$PROJECT_DIR$/UBBAttendance.iml" />
<module fileurl="file://$PROJECT_DIR$/attendance-ubb/attendance-ubb.iml" filepath="$PROJECT_DIR$/attendance-ubb/attendance-ubb.iml" />
</modules>
</component>
</project>

+ 12
- 0
.idea/runConfigurations.xml View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>

+ 15
- 0
.navigation/attendance-ubb/raw/main.nvg.xml View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<navigationModel
ns = "http://schemas.android.com?import=com.android.tools.idea.editors.navigation.model.*">
<locations
class = "java.util.ArrayList">
<statePointEntry>
<state
class = "com.android.tools.idea.editors.navigation.model.ActivityState"
className = "cl.cromer.attendance.SubjectList"/>
<point
x = "196"
y = "52"/>
</statePointEntry>
</locations>
</navigationModel>

+ 1
- 0
attendance-ubb/.gitignore View File

@@ -0,0 +1 @@
/build

+ 45
- 0
attendance-ubb/build.gradle View File

@@ -0,0 +1,45 @@
apply plugin: 'com.android.application'

android {
signingConfigs {
cromer {
keyAlias 'cromer'
keyPassword 'K7PRxe4eyeXGr3FeULSapUEqHcKAZgkaGe6HmX7cNd873XBLwR'
storeFile file('/home/cromer/cromer_cl/keystore/keystore')
storePassword 'K7PRxe4eyeXGr3FeULSapUEqHcKAZgkaGe6HmX7cNd873XBLwR'
}
}
compileSdkVersion 27
buildToolsVersion "27"
defaultConfig {
applicationId "cl.cromer.ubb.attendance"
minSdkVersion 14
targetSdkVersion 27
versionCode 1
versionName "1.0"
signingConfig signingConfigs.cromer
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
signingConfig signingConfigs.cromer
proguardFile '/home/cromer/StudioProjects/UBBAttendance/attendance-ubb/proguard-rules.pro'
}
debug {
debuggable true
jniDebuggable true
minifyEnabled false
}
}
productFlavors {
}
}

dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:27.0.0'
compile 'com.android.support:design:27.0.0'
compile 'com.android.support:cardview-v7:27.0.0'
compile 'com.android.support:recyclerview-v7:27.0.0'
}

BIN
attendance-ubb/libs/poi-3.14-beta1-20151223.jar View File


+ 27
- 0
attendance-ubb/proguard-rules.pro View File

@@ -0,0 +1,27 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /mnt/storage/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
-keep public class org.apache.poi.** {*;}
-dontwarn org.apache.poi.**

-dontwarn android.support.v7.**
-keep class android.support.v7.** { *; }
-keep interface android.support.v7.** { *; }

-dontwarn android.support.v4.**
-keep class android.support.v4.** { *; }
-keep interface android.support.v4.** { *; }

+ 123
- 0
attendance-ubb/src/main/AndroidManifest.xml View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="cl.cromer.ubb.attendance"
xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/UBBTheme">
<activity
android:name=".SubjectList"
android:label="@string/app_name"
android:theme="@style/UBBTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".CourseList"
android:label="@string/app_name"
android:parentActivityName=".SubjectList"
android:theme="@style/UBBTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="cl.cromer.ubb.attendance.SubjectList"/>
</activity>
<activity
android:name=".ClassList"
android:label="@string/app_name"
android:parentActivityName=".CourseList"
android:theme="@style/UBBTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="cl.cromer.ubb.attendance.CourseList"/>
</activity>
<activity
android:name=".ImportExcel"
android:label="@string/app_name"
android:parentActivityName=".SubjectList"
android:screenOrientation="portrait"
android:theme="@style/UBBTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="cl.cromer.ubb.attendance.SubjectList"/>
</activity>
<activity
android:name=".ImportPhotos"
android:label="@string/app_name"
android:parentActivityName=".SubjectList"
android:screenOrientation="portrait"
android:theme="@style/UBBTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="cl.cromer.ubb.attendance.SubjectList"/>
>
</activity>
<activity
android:name=".TakeAttendance"
android:label="@string/app_name"
android:parentActivityName=".ClassList"
android:screenOrientation="portrait"
android:theme="@style/UBBTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="cl.cromer.ubb.attendance.ClassList"/>
</activity>
<activity
android:name=".CorrectAttendance"
android:label="@string/app_name"
android:parentActivityName=".ClassList"
android:theme="@style/UBBTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="cl.cromer.ubb.attendance.ClassList"/>
</activity>
<activity
android:name=".LateStudentAttendance"
android:label="@string/app_name"
android:parentActivityName=".ClassList"
android:theme="@style/UBBTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="cl.cromer.ubb.attendance.ClassList"/>
</activity>
<activity
android:name=".ClassReport"
android:label="@string/app_name"
android:parentActivityName=".SubjectList"
android:screenOrientation="portrait"
android:theme="@style/UBBTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="cl.cromer.ubb.attendance.SubjectList"/>
</activity>
<activity
android:name=".About"
android:label="@string/app_name"
android:parentActivityName=".SubjectList"
android:screenOrientation="portrait"
android:theme="@style/UBBTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="cl.cromer.ubb.attendance.SubjectList"/>
</activity>
<activity
android:name=".CourseReport"
android:label="@string/app_name"
android:parentActivityName=".SubjectList"
android:screenOrientation="portrait"
android:theme="@style/UBBTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="cl.cromer.ubb.attendance.SubjectList"/>
</activity>
</application>

</manifest>

+ 44
- 0
attendance-ubb/src/main/java/cl/cromer/ubb/attendance/About.java View File

@@ -0,0 +1,44 @@
package cl.cromer.ubb.attendance;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;

public class About extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_about);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setHomeButtonEnabled(true);
actionBar.setDisplayHomeAsUpEnabled(true);
}
}

@Override
public void onBackPressed() {
super.onBackPressed();
}

@Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}

public void sendEmail(View view) {
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:"));
intent.putExtra(Intent.EXTRA_EMAIL, "chris@cromer.cl");
intent.putExtra(Intent.EXTRA_SUBJECT, "Attendance");
startActivity(Intent.createChooser(intent, getResources().getString(R.string.about_email)));
}
}

+ 60
- 0
attendance-ubb/src/main/java/cl/cromer/ubb/attendance/Attendance.java View File

@@ -0,0 +1,60 @@
package cl.cromer.ubb.attendance;

public class Attendance extends Student {
private int status;
// 0 - uninitialized
// 1 - present
// 2 - justified
// 3 - absent
// 4 - late

private int present;
private int justified;
private int absent;
private int late;

public Attendance(int status, int studentId, String run, String firstName, String secondName, String firstLastName, String secondLastName, int major, int enrolled, String email, byte[] photo) {
super(studentId, run, firstName, secondName, firstLastName, secondLastName, major, enrolled, email, photo);
this.setStatus(status);
}

protected int getStatus() {
return status;
}

protected void setStatus(int status) {
this.status = status;
}

protected int getPresent() {
return present;
}

protected void setPresent(int present) {
this.present = present;
}

protected int getJustified() {
return justified;
}

protected void setJustified(int justified) {
this.justified = justified;
}

protected int getAbsent() {
return absent;
}

protected void setAbsent(int absent) {
this.absent = absent;
}

protected int getLate() {
return late;
}

protected void setLate(int late) {
this.late = late;
}
}

+ 122
- 0
attendance-ubb/src/main/java/cl/cromer/ubb/attendance/Class.java View File

@@ -0,0 +1,122 @@
package cl.cromer.ubb.attendance;

import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;

import java.text.DateFormat;
import java.util.Calendar;

public class Class extends Course implements Parcelable {
private int classId;
private long date;

public Class() {}

public Class(Course course, long date) {
super(course.getCourseId(), course.getCourseSection(), course.getCourseSemester(), course.getYear());
this.setDate(date);
}

public Class(Course course, int classId, long date) {
super(course.getCourseId(), course.getCourseSection(), course.getCourseSemester(), course.getYear());
this.setClassId(classId);
this.setDate(date);
}

protected void setClass(Class classObject) {
this.setClassId(classObject.getClassId());
this.setDate(classObject.getDate());
}

protected int getClassId() {
return classId;
}

protected void setClassId(int classId) {
this.classId = classId;
}

protected long getDate() {
return date;
}

protected void setDate(long date) {
// Remove the time, I only need the date
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(date);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
date = calendar.getTimeInMillis();

this.date = date;
}

protected String getFormattedDate(Context context) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(date);
DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.LONG, context.getResources().getConfiguration().locale);
return dateFormat.format(calendar.getTime());
}

protected String getFormattedShortDate(Context context) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(date);
DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, context.getResources().getConfiguration().locale);
return dateFormat.format(calendar.getTime());
}

// Parcelable
@Override
public int describeContents() {
//Must be overridden, but I don't need it.
return 0;
}

@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(majorId);
out.writeString(majorName);
out.writeInt(majorCode);
out.writeInt(subjectId);
out.writeInt(subjectCode);
out.writeString(subjectName);
out.writeInt(courseId);
out.writeInt(courseSection);
out.writeInt(courseSemester);
out.writeInt(courseYear);
out.writeInt(classId);
out.writeLong(date);
}

private void readFromParcel(Parcel in) {
majorId = in.readInt();
majorName = in.readString();
majorCode = in.readInt();
subjectId = in.readInt();
subjectCode = in.readInt();
subjectName = in.readString();
courseId = in.readInt();
courseSection = in.readInt();
courseSemester = in.readInt();
courseYear = in.readInt();
classId = in.readInt();
date = in.readLong();
}

private Class(Parcel in) {
readFromParcel(in);
}

public static final Parcelable.Creator<Class> CREATOR = new Parcelable.Creator<Class>() {
public Class createFromParcel(Parcel in) {
return new Class(in);
}

public Class[] newArray(int size) {
return new Class[size];
}
};
}

+ 1056
- 0
attendance-ubb/src/main/java/cl/cromer/ubb/attendance/ClassList.java
File diff suppressed because it is too large
View File


+ 77
- 0
attendance-ubb/src/main/java/cl/cromer/ubb/attendance/ClassListAdapter.java View File

@@ -0,0 +1,77 @@
package cl.cromer.ubb.attendance;

import android.content.Context;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.List;

public class ClassListAdapter extends RecyclerView.Adapter<ClassListAdapter.ClassViewHolder> {

private List<Class> classes;
private Context context;

public ClassListAdapter(List<Class> classes, Context context) {
this.classes = classes;
this.context = context;
}

@Override
public int getItemCount() {
return classes.size();
}

@Override
public ClassViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_class_list_card, viewGroup, false);
return new ClassViewHolder(view);
}

@Override
public void onBindViewHolder(ClassViewHolder classViewHolder, int i) {
classViewHolder.classDate.setText(String.valueOf(classes.get(i).getFormattedDate(context)));
classViewHolder.classId.setText(String.valueOf(classes.get(i).getClassId()));
classViewHolder.itemView.setLongClickable(true);
}

@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}

public void addClass(Class classObject) {
classes.add(getItemCount(), classObject);
notifyItemInserted(getItemCount());
}

public void updateClass(int index, Class classObject) {
classes.set(index, classObject);
notifyItemChanged(index);
}

public Class getClass(int index) {
return classes.get(index);
}

public void deleteClass(Class classObject) {
classes.remove(classObject);
}

public static class ClassViewHolder extends RecyclerView.ViewHolder {
public CardView cardView;
public TextView classDate;
public TextView classId;

public ClassViewHolder(View itemView) {
super(itemView);
cardView = (CardView) itemView.findViewById(R.id.class_card_view);
classDate = (TextView) itemView.findViewById(R.id.class_date);
classId = (TextView) itemView.findViewById(R.id.class_id);
}
}

}

+ 968
- 0
attendance-ubb/src/main/java/cl/cromer/ubb/attendance/ClassReport.java View File

@@ -0,0 +1,968 @@
package cl.cromer.ubb.attendance;

import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.PowerManager;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.Toast;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import cl.cromer.ubb.attendance.Progress;
import cl.cromer.ubb.attendance.DBSchema.*;

public class ClassReport extends AppCompatActivity {

// SQLite database
private SQLParser sqlParser = null;
private SQLiteDatabase ubbDB = null;

// Background thread for the database
private Thread thread = null;
private Handler threadHandler = new Handler();

// Progress bar
private Progress progress = null;

private AlertDialog choiceDialog = null;
private AlertDialog confirmDialog = null;
private View reportView;

private List<Subject> subjects = new ArrayList<>();
private List<Course> courses = new ArrayList<>();
private List<Class> classes = new ArrayList<>();
private List<Attendance> students = new ArrayList<>();

private Class classObject = new Class();

private int disabledButtonColor;

private Context context;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_class_report);

this.context = this;

LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
reportView = inflater.inflate(R.layout.view_class_report, new RelativeLayout(this), false);

// Build the add subject dialog window using the subject view
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(reportView);
builder.setPositiveButton(R.string.input_accept, null);
builder.setNegativeButton(R.string.input_cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});

choiceDialog = builder.create();

choiceDialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialogInterface) {
ColorStateList colorStateList = choiceDialog.getButton(AlertDialog.BUTTON_POSITIVE).getTextColors();
choiceDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
choiceDialog.getButton(AlertDialog.BUTTON_POSITIVE).setClickable(false);
choiceDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimaryDark));

if (colorStateList != null) {
disabledButtonColor = colorStateList.getColorForState(new int[] {-android.R.attr.state_enabled}, R.color.colorPrimary);
}
}
});

choiceDialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation;
choiceDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
finish();
}
});
choiceDialog.setCanceledOnTouchOutside(false);

// Create a progress dialog for slow devices
progress = new Progress();
progress.show(this, 1);
progress.setCancelable(false);

// Load the SQLite database
sqlParser = new SQLParser(this);
thread = new Thread(new Runnable() {
public void run() {
ubbDB = sqlParser.getWritableDatabase();
threadHandler.post(new Runnable() {
public void run() {
databaseLoaded();
}
});
}
});
thread.start();
progress.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
thread.interrupt();
finish();
}
});
}

@Override
protected void onDestroy() {
super.onDestroy();
// We need to get rid of the progressbar if it's showing
if (progress != null && progress.isShowing()) {
progress.dismiss();
}
if (choiceDialog != null && choiceDialog.isShowing()) {
choiceDialog.dismiss();
}
}

@Override
public void onBackPressed() {
super.onBackPressed();
}

@Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}

private void databaseLoaded() {
final GetSubjects getSubjects = new GetSubjects(getApplicationContext());
getSubjects.execute();

progress.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
getSubjects.cancel(true);
finish();
}
});
}

private AdapterView.OnItemSelectedListener subjectListener() {
return new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
courses = new ArrayList<>();
classes = new ArrayList<>();
if (position == 0) {
choiceDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(disabledButtonColor);
choiceDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
choiceDialog.getButton(AlertDialog.BUTTON_POSITIVE).setClickable(false);

Spinner spinner = (Spinner) reportView.findViewById(R.id.course_spinner);

List<String> options = new ArrayList<>();
options.add(getResources().getString(R.string.report_course));

ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(getApplicationContext(), R.layout.view_spinner_selected_item, options);
arrayAdapter.setDropDownViewResource(R.layout.view_spinner_dropdown_item);

spinner.setAdapter(arrayAdapter);
spinner.setSelection(0);
spinner.setEnabled(false);
spinner.setClickable(false);
spinner.setOnItemSelectedListener(null);

spinner = (Spinner) reportView.findViewById(R.id.class_spinner);

options = new ArrayList<>();
options.add(getResources().getString(R.string.report_class));

arrayAdapter = new ArrayAdapter<>(getApplicationContext(), R.layout.view_spinner_selected_item, options);
arrayAdapter.setDropDownViewResource(R.layout.view_spinner_dropdown_item);

spinner.setAdapter(arrayAdapter);
spinner.setSelection(0);
spinner.setEnabled(false);
spinner.setClickable(false);
spinner.setOnItemSelectedListener(null);
}
else {
progress = new Progress();
progress.show(context, 1);
progress.setCancelable(false);

final int thePosition = position - 1;

classObject.setSubject(subjects.get(thePosition));

sqlParser = new SQLParser(getApplicationContext());
thread = new Thread(new Runnable() {
public void run() {
ubbDB = sqlParser.getWritableDatabase();
threadHandler.post(new Runnable() {
public void run() {

final GetCourses getCourses = new GetCourses(getApplicationContext());
getCourses.execute(thePosition);

progress.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
getCourses.cancel(true);
finish();
}
});
}
});
}
});
thread.start();
progress.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
thread.interrupt();
finish();
}
});
}
}

@Override
public void onNothingSelected(AdapterView<?> parent) {

}
};
}

private AdapterView.OnItemSelectedListener courseListener() {
return new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
classes = new ArrayList<>();
if (position == 0) {
choiceDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(disabledButtonColor);
choiceDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
choiceDialog.getButton(AlertDialog.BUTTON_POSITIVE).setClickable(false);

Spinner spinner = (Spinner) reportView.findViewById(R.id.class_spinner);

List<String> options = new ArrayList<>();
options.add(getResources().getString(R.string.report_class));

ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(getApplicationContext(), R.layout.view_spinner_selected_item, options);
arrayAdapter.setDropDownViewResource(R.layout.view_spinner_dropdown_item);

spinner.setAdapter(arrayAdapter);
spinner.setSelection(0);
spinner.setEnabled(false);
spinner.setClickable(false);
spinner.setOnItemSelectedListener(null);
}
else {
progress = new Progress();
progress.show(context, 1);
progress.setCancelable(false);

final int thePosition = position - 1;

classObject.setCourse(courses.get(thePosition));

sqlParser = new SQLParser(getApplicationContext());
thread = new Thread(new Runnable() {
public void run() {
ubbDB = sqlParser.getWritableDatabase();
threadHandler.post(new Runnable() {
public void run() {

final GetClasses getClasses = new GetClasses(getApplicationContext());
getClasses.execute(thePosition);

progress.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
getClasses.cancel(true);
finish();
}
});
}
});
}
});
thread.start();
progress.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
thread.interrupt();
finish();
}
});
}
}

@Override
public void onNothingSelected(AdapterView<?> parent) {

}
};
}

private AdapterView.OnItemSelectedListener classListener() {
return new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (position == 0) {
choiceDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(disabledButtonColor);
choiceDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
choiceDialog.getButton(AlertDialog.BUTTON_POSITIVE).setClickable(false);
choiceDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(null);
}
else {
classObject.setClass(classes.get(position - 1));

choiceDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimaryDark));
choiceDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true);
choiceDialog.getButton(AlertDialog.BUTTON_POSITIVE).setClickable(true);
choiceDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(acceptListener());
}
}

@Override
public void onNothingSelected(AdapterView<?> parent) {

}
};
}

private View.OnClickListener acceptListener() {
return new View.OnClickListener() {
@Override
public void onClick(View view) {
progress = new Progress();
progress.show(context, 1);
progress.setCancelable(false);

choiceDialog.dismiss();

sqlParser = new SQLParser(getApplicationContext());
thread = new Thread(new Runnable() {
public void run() {
ubbDB = sqlParser.getWritableDatabase();
threadHandler.post(new Runnable() {
public void run() {

final GetAttendance getAttendance = new GetAttendance(getApplicationContext());
getAttendance.execute();

progress.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
getAttendance.cancel(true);
finish();
}
});
}
});
}
});
thread.start();
progress.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
thread.interrupt();
finish();
}
});
}
};
}

private class GetSubjects extends AsyncTask<Void, Void, Void> {
private Context context;
private PowerManager.WakeLock wakeLock;

protected GetSubjects(Context context) {
this.context = context;
}

@Override
protected void onPreExecute() {
super.onPreExecute();
// Let's make sure the CPU doesn't go to sleep
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
if (!wakeLock.isHeld()) {
wakeLock.acquire();
}
}

@Override
protected Void doInBackground(Void... voids) {
if (isCancelled()) {
return null;
}

// Get subjects by name in ascending order
String query = "SELECT " + sqlParser.combineColumnsStrings(DBSubjects.ALL_COLUMNS, DBMajors.ALL_COLUMNS) + " FROM " + DBSubjects.TABLE_NAME + " INNER JOIN (SELECT " + sqlParser.combineColumnsStrings(DBMajors.ALL_COLUMNS) +" FROM " + DBMajors.TABLE_NAME + ") " + DBMajors.TABLE_NAME + " ON " + DBSubjects.TABLE_NAME + "." + DBSubjects.COLUMN_MAJOR + "=" + DBMajors.TABLE_NAME + "." + DBMajors.COLUMN_ID + " ORDER BY " + DBSubjects.COLUMN_NAME + " ASC";
if (BuildConfig.DEBUG) {
Log.d("ClassReport", query);
}
Cursor cursor = ubbDB.rawQuery(query, null);

// Iterate through the database rows
while (cursor.moveToNext()) {
if (isCancelled()) {
return null;
}
Major major = new Major(
cursor.getInt(cursor.getColumnIndex(DBMajors.COLUMN_ID)),
cursor.getString(cursor.getColumnIndex(DBMajors.COLUMN_NAME)),
cursor.getInt(cursor.getColumnIndex(DBMajors.COLUMN_CODE)));
subjects.add(
new Subject(
major,
cursor.getInt(cursor.getColumnIndex(DBSubjects.COLUMN_ID)),
cursor.getString(cursor.getColumnIndex(DBSubjects.COLUMN_NAME)),
cursor.getInt(cursor.getColumnIndex(DBSubjects.COLUMN_CODE))
)
);
}
cursor.close();

// Close the database connection
ubbDB.close();
sqlParser.close();

return null;
}

@Override
protected void onPostExecute(Void result) {
// Release the kraken errr wakelock
List<String> options = new ArrayList<>();
options.add(getResources().getString(R.string.report_subject));
for (Subject subject : subjects) {
options.add(subject.getSubjectName());
}

Spinner spinner = (Spinner) reportView.findViewById(R.id.subject_spinner);

ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(getApplicationContext(), R.layout.view_spinner_selected_item, options);
arrayAdapter.setDropDownViewResource(R.layout.view_spinner_dropdown_item);

spinner.setAdapter(arrayAdapter);
spinner.setSelection(0);

spinner.setOnItemSelectedListener(subjectListener());
progress.dismiss();
wakeLock.release();
choiceDialog.show();
}
}

private class GetCourses extends AsyncTask<Integer, Void, Void> {
private Context context;
private PowerManager.WakeLock wakeLock;

protected GetCourses(Context context) {
this.context = context;
}

@Override
protected void onPreExecute() {
super.onPreExecute();
// Let's make sure the CPU doesn't go to sleep
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
if (!wakeLock.isHeld()) {
wakeLock.acquire();
}
}

@Override
protected Void doInBackground(Integer... position) {
if (isCancelled()) {
return null;
}

Cursor cursor = ubbDB.query(
DBCourses.TABLE_NAME,
DBCourses.ALL_COLUMNS,
DBCourses.COLUMN_SUBJECT + "=" + subjects.get(position[0]).getSubjectId(),
null,
null,
null,
DBCourses.COLUMN_YEAR + " DESC, " + DBCourses.COLUMN_SEMESTER + " DESC, " + DBCourses.COLUMN_SECTION + " ASC",
null);

// Iterate through the database rows
while (cursor.moveToNext()) {
if (isCancelled()) {
return null;
}
courses.add(
new Course(
subjects.get(position[0]),
cursor.getInt(cursor.getColumnIndex(DBCourses.COLUMN_ID)),
cursor.getInt(cursor.getColumnIndex(DBCourses.COLUMN_SECTION)),
cursor.getInt(cursor.getColumnIndex(DBCourses.COLUMN_SEMESTER)),
cursor.getInt(cursor.getColumnIndex(DBCourses.COLUMN_YEAR))
)
);
}
cursor.close();

// Close the database connection
ubbDB.close();
sqlParser.close();

return null;
}

@Override
protected void onPostExecute(Void result) {
// Release the kraken errr wakelock
List<String> options = new ArrayList<>();
options.add(getResources().getString(R.string.report_course));
for (Course course : courses) {
options.add(course.getYear() + "-" + course.getCourseSemester() + " " + getResources().getString(R.string.report_section) + " " + course.getCourseSection());
}

Spinner spinner = (Spinner) reportView.findViewById(R.id.course_spinner);

ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(getApplicationContext(), R.layout.view_spinner_selected_item, options);
arrayAdapter.setDropDownViewResource(R.layout.view_spinner_dropdown_item);

spinner.setAdapter(arrayAdapter);
spinner.setSelection(0);
spinner.setEnabled(true);
spinner.setClickable(true);

spinner.setOnItemSelectedListener(courseListener());
progress.dismiss();
wakeLock.release();
}
}

private class GetClasses extends AsyncTask<Integer, Void, Void> {
private Context context;
private PowerManager.WakeLock wakeLock;

protected GetClasses(Context context) {
this.context = context;
}

@Override
protected void onPreExecute() {
super.onPreExecute();
// Let's make sure the CPU doesn't go to sleep
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
if (!wakeLock.isHeld()) {
wakeLock.acquire();
}
}

@Override
protected Void doInBackground(Integer... position) {
if (isCancelled()) {
return null;
}

Cursor cursor = ubbDB.query(
DBClasses.TABLE_NAME,
DBClasses.ALL_COLUMNS,
DBClasses.COLUMN_COURSE + "=" + courses.get(position[0]).getCourseId(),
null,
null,
null,
DBClasses.COLUMN_DATE + " DESC",
null);

// Iterate through the database rows
while (cursor.moveToNext()) {
if (isCancelled()) {
return null;
}
classes.add(
new Class(
courses.get(position[0]),
cursor.getInt(cursor.getColumnIndex(DBClasses.COLUMN_ID)),
cursor.getLong(cursor.getColumnIndex(DBClasses.COLUMN_DATE))
)
);
}
cursor.close();

// Close the database connection
ubbDB.close();
sqlParser.close();

return null;
}

@Override
protected void onPostExecute(Void result) {
// Release the kraken errr wakelock
List<String> options = new ArrayList<>();
options.add(getResources().getString(R.string.report_class));
for (Class classObject : classes) {
options.add(classObject.getFormattedDate(getApplicationContext()));
}

Spinner spinner = (Spinner) reportView.findViewById(R.id.class_spinner);

ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(getApplicationContext(), R.layout.view_spinner_selected_item, options);
arrayAdapter.setDropDownViewResource(R.layout.view_spinner_dropdown_item);

spinner.setAdapter(arrayAdapter);
spinner.setSelection(0);
spinner.setEnabled(true);
spinner.setClickable(true);

spinner.setOnItemSelectedListener(classListener());
progress.dismiss();
wakeLock.release();
}
}

private class GetAttendance extends AsyncTask<Void, Void, Boolean> {
private Context context;
private PowerManager.WakeLock wakeLock;

protected GetAttendance(Context context) {
this.context = context;
}

@Override
protected void onPreExecute() {
super.onPreExecute();
// Let's make sure the CPU doesn't go to sleep
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
if (!wakeLock.isHeld()) {
wakeLock.acquire();
}
}

@Override
protected Boolean doInBackground(Void... voids) {
if (isCancelled()) {
return false;
}

String query = "SELECT " + sqlParser.combineColumnsStrings(DBStudents.ALL_COLUMNS, DBAttendance.ALL_COLUMNS) + " FROM " + DBStudents.TABLE_NAME +
" INNER JOIN (SELECT " + sqlParser.combineColumnsStrings(DBCoursesStudents.ALL_COLUMNS) + " FROM " + DBCoursesStudents.TABLE_NAME + " WHERE " + DBCoursesStudents.COLUMN_COURSE + "=" + classObject.getCourseId() + ") AS " + DBCoursesStudents.TABLE_NAME + " ON " + DBStudents.TABLE_NAME + "." + DBStudents.COLUMN_ID + "=" + DBCoursesStudents.TABLE_NAME + "." + DBCoursesStudents.COLUMN_STUDENT +
" LEFT OUTER JOIN (SELECT " + sqlParser.combineColumnsStrings(DBAttendance.ALL_COLUMNS) + " FROM " + DBAttendance.TABLE_NAME + " WHERE " + DBAttendance.COLUMN_CLASS + "=" + classObject.getClassId() + ") AS " + DBAttendance.TABLE_NAME + " ON " + DBStudents.TABLE_NAME + "." + DBStudents.COLUMN_ID + "=" + DBAttendance.TABLE_NAME + "." + DBAttendance.COLUMN_STUDENT +
" ORDER BY " + DBStudents.COLUMN_FIRST_LAST_NAME + " ASC, " + DBStudents.COLUMN_FIRST_NAME + " ASC";
if (BuildConfig.DEBUG) {
Log.d("ClassReport", query);
}
Cursor cursor = ubbDB.rawQuery(query, null);

// Iterate through the database rows
while (cursor.moveToNext()) {
if (isCancelled()) {
return null;
}
students.add(new Attendance(
cursor.getInt(cursor.getColumnIndex(DBAttendance.COLUMN_ATTENDANCE)),
cursor.getInt(cursor.getColumnIndex(DBStudents.COLUMN_ID)),
cursor.getString(cursor.getColumnIndex(DBStudents.COLUMN_RUN)),
cursor.getString(cursor.getColumnIndex(DBStudents.COLUMN_FIRST_NAME)),
cursor.getString(cursor.getColumnIndex(DBStudents.COLUMN_SECOND_NAME)),
cursor.getString(cursor.getColumnIndex(DBStudents.COLUMN_FIRST_LAST_NAME)),
cursor.getString(cursor.getColumnIndex(DBStudents.COLUMN_SECOND_LAST_NAME)),
cursor.getInt(cursor.getColumnIndex(DBStudents.COLUMN_MAJOR)),
cursor.getInt(cursor.getColumnIndex(DBStudents.COLUMN_ENROLLED)),
cursor.getString(cursor.getColumnIndex(DBStudents.COLUMN_EMAIL)),
cursor.getBlob(cursor.getColumnIndex(DBStudents.COLUMN_PHOTO))
));
}
cursor.close();

Workbook workbook = new HSSFWorkbook();
Sheet sheet = workbook.createSheet(getResources().getString(R.string.app_name));

Excel excel = new Excel(workbook);
excel.createStyles();

Row row;
Cell cell;
// Major
row = sheet.createRow(0);
cell = row.createCell(0);
cell.setCellValue(classObject.getMajorName() + " - " + classObject.getMajorCode());
cell.setCellStyle(excel.getCellStyle("left"));
for (int i = 1; i < 7; i++) {
cell = row.createCell(i);
if (i == 6) {
cell.setCellStyle(excel.getCellStyle("right"));
}
else {
cell.setCellStyle(excel.getCellStyle("middle"));
}
}

// Subject
row = sheet.createRow(1);
cell = row.createCell(0);
cell.setCellValue(classObject.getSubjectName() + " - " + classObject.getSubjectCode());
cell.setCellStyle(excel.getCellStyle("left"));
for (int i = 1; i < 7; i++) {
cell = row.createCell(i);
if (i == 6) {
cell.setCellStyle(excel.getCellStyle("right"));
}
else {
cell.setCellStyle(excel.getCellStyle("middle"));
}
}

// Columns
row = sheet.createRow(2);

cell = row.createCell(0);
cell.setCellValue(getResources().getString(R.string.report_names));
cell.setCellStyle(excel.getCellStyle("blue"));

cell = row.createCell(1);
cell.setCellValue(getResources().getString(R.string.report_first_last_name));
cell.setCellStyle(excel.getCellStyle("blue"));

cell = row.createCell(2);
cell.setCellValue(getResources().getString(R.string.report_second_last_name));
cell.setCellStyle(excel.getCellStyle("blue"));

cell = row.createCell(3);
cell.setCellValue(getResources().getString(R.string.report_present));
cell.setCellStyle(excel.getCellStyle("green"));

cell = row.createCell(4);
cell.setCellValue(getResources().getString(R.string.report_late));
cell.setCellStyle(excel.getCellStyle("yellow"));

cell = row.createCell(5);
cell.setCellValue(getResources().getString(R.string.report_justified));
cell.setCellStyle(excel.getCellStyle("orange"));

cell = row.createCell(6);
cell.setCellValue(getResources().getString(R.string.report_absent));
cell.setCellStyle(excel.getCellStyle("red"));

int cellSize1 = getResources().getString(R.string.report_names).length();
int cellSize2 = getResources().getString(R.string.report_first_last_name).length();
int cellSize3 = getResources().getString(R.string.report_second_last_name).length();
int rowNumber = 3;
String value;
for (Attendance student : students) {
row = sheet.createRow(rowNumber);

// First and second name
cell = row.createCell(0);
value = student.getFirstName() + " " + student.getSecondName();
if (value.length() > cellSize1) {
cellSize1 = value.length();
}
cell.setCellValue(value);
cell.setCellStyle(excel.getCellStyle("main"));

// First last name
cell = row.createCell(1);
value = student.getFirstLastName();
if (value.length() > cellSize2) {
cellSize2 = value.length();
}
cell.setCellValue(value);
cell.setCellStyle(excel.getCellStyle("main"));

// Second last name
cell = row.createCell(2);
value = student.getSecondLastName();
if (value.length() > cellSize3) {
cellSize3 = value.length();
}
cell.setCellValue(value);
cell.setCellStyle(excel.getCellStyle("main"));

int status = student.getStatus();
int attendanceCell = 3;
if (status != 0) {
switch (status) {
case 1:
attendanceCell = 3;
break;
case 4:
attendanceCell = 4;
break;
case 2:
attendanceCell = 5;
break;
case 3:
attendanceCell = 6;
break;
}
}

CellStyle attendanceColor = null;
for (int i = 3; i < 7; i++) {
cell = row.createCell(i);
switch (i) {
case 3:
attendanceColor = excel.getCellStyle("green");
break;
case 4:
attendanceColor = excel.getCellStyle("yellow");
break;
case 5:
attendanceColor = excel.getCellStyle("orange");
break;
case 6:
attendanceColor = excel.getCellStyle("red");
break;
}
if (i == attendanceCell) {
cell.setCellValue("X");
}
cell.setCellStyle(attendanceColor);
}

rowNumber++;
}
sheet.setColumnWidth(0, (cellSize1 + 1) * 256);
sheet.setColumnWidth(1, (cellSize2 + 1) * 256);
sheet.setColumnWidth(2, (cellSize3 + 1) * 256);

final String filePath = StringFixer.removeInvalidFileCharacters(Environment.getExternalStorageDirectory() +
"/" + getResources().getString(R.string.app_name) +
"/" + classObject.getMajorName() +
"/" + classObject.getYear() + "-" + classObject.getCourseSemester() + "-" + classObject.getCourseSection());

final String fileName = "/" + getResources().getString(R.string.report_class) + "-" + classObject.getFormattedShortDate(context).replaceAll("/", "-") + ".xls";

try {
File file = new File(filePath);
if (!file.exists()) {
if (!file.mkdirs()) {
return false;
}
}
FileOutputStream fileOutputStream = new FileOutputStream(filePath + fileName);
workbook.write(fileOutputStream);
fileOutputStream.close();
}
catch (FileNotFoundException e) {
if (BuildConfig.DEBUG) {
e.printStackTrace();
}
return false;
}
catch (IOException e) {
if (BuildConfig.DEBUG) {
e.printStackTrace();
}
return false;
}

// Close the database connection
ubbDB.close();
sqlParser.close();

return true;
}

@Override
protected void onPostExecute(Boolean result) {
// Release the kraken errr wakelock
if (result) {
confirmOpen();
}
else {
Toast.makeText(getApplicationContext(), R.string.report_fail, Toast.LENGTH_SHORT).show();
finish();
}
progress.dismiss();
wakeLock.release();
}
}

private void confirmOpen() {
final String filePath = StringFixer.removeInvalidFileCharacters(Environment.getExternalStorageDirectory() +
"/" + getResources().getString(R.string.app_name) +
"/" + classObject.getMajorName() +
"/" + classObject.getYear() + "-" + classObject.getCourseSemester() + "-" + classObject.getCourseSection());

final String fileName = "/" + getResources().getString(R.string.report_class) + "-" + classObject.getFormattedShortDate(context).replaceAll("/", "-") + ".xls";

AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage(R.string.report_created);
builder.setPositiveButton(R.string.input_yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
File file = new File(filePath + fileName);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.ms-excel");

try {
startActivity(intent);
}
catch (ActivityNotFoundException e) {
Toast.makeText(ClassReport.this, "No Application Available to View Excel", Toast.LENGTH_SHORT).show();
}
confirmDialog.dismiss();
finish();
}
});
builder.setNegativeButton(R.string.input_no, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
confirmDialog.dismiss();
finish();
}
});

builder.setCancelable(true);
confirmDialog = builder.create();

confirmDialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialogInterface) {
confirmDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimaryDark));
confirmDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimaryDark));
}
});

confirmDialog.show();
}
}

+ 508
- 0
attendance-ubb/src/main/java/cl/cromer/ubb/attendance/CorrectAttendance.java View File

@@ -0,0 +1,508 @@
package cl.cromer.ubb.attendance;

import android.app.ActivityManager;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

import cl.cromer.ubb.attendance.Progress;
import cl.cromer.ubb.attendance.DBSchema.DBAttendance;
import cl.cromer.ubb.attendance.DBSchema.DBCoursesStudents;
import cl.cromer.ubb.attendance.DBSchema.DBStudents;

public class CorrectAttendance extends AppCompatActivity implements TakeAttendanceListener {

// SQLite database
private SQLParser sqlParser = null;
private SQLiteDatabase ubbDB = null;

// Background thread for the database
private Thread thread = null;
private Handler threadHandler = new Handler();

// Progress bar
private Progress progress = null;

private Class classObject = null;

private List<Attendance> students = new ArrayList<>();

private int studentShowing = -1;

private Bitmap bitmap = null;

private boolean finalStudent = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// Receive the course from the previous activity
Intent classListIntent = getIntent();
classObject = classListIntent.getParcelableExtra(StaticVariables.CLASS_OBJECT);

setContentView(R.layout.activity_correct_attendance);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle(classObject.getFormattedDate(this));
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setHomeButtonEnabled(true);
actionBar.setDisplayHomeAsUpEnabled(true);
}

if (BuildConfig.DEBUG) {
/*
Pixel Densities
mdpi: 160 dpi 1×
hdpi: 240 dpi 1.5×
xhdpi: 320 dpi 2×
xxhdpi: 490 dpi 3×
xxxhdpi: 640 dpi 4×
*/
switch (getResources().getDisplayMetrics().densityDpi) {
case DisplayMetrics.DENSITY_LOW:
Log.d("TakeAttendance", "Density: ldpi");
break;
case DisplayMetrics.DENSITY_MEDIUM:
Log.d("TakeAttendance", "Density: mdpi");
break;
case DisplayMetrics.DENSITY_HIGH:
Log.d("TakeAttendance", "Density: hdpi");
break;
case DisplayMetrics.DENSITY_XHIGH:
Log.d("TakeAttendance", "Density: xhdpi");
break;
case DisplayMetrics.DENSITY_XXHIGH:
Log.d("TakeAttendance", "Density: xxhdpi");
break;
case DisplayMetrics.DENSITY_XXXHIGH:
Log.d("TakeAttendance", "Density: xxxhdpi");
break;
case DisplayMetrics.DENSITY_560:
Log.d("TakeAttendance", "Density: 560dpi");
break;
default:
Log.d("TakeAttendance", "Density unknown: " + getResources().getDisplayMetrics().densityDpi);
break;
}
}

// Create a progress dialog for slow devices
progress = new Progress();
progress.show(this, 1);
progress.setCancelable(false);

// Load the SQLite database
sqlParser = new SQLParser(this);
thread = new Thread(new Runnable() {
public void run() {
ubbDB = sqlParser.getWritableDatabase();
threadHandler.post(new Runnable() {
public void run() {
databaseLoaded();
}
});
}
});
thread.start();
progress.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
thread.interrupt();
finish();
}
});
}

@Override
protected void onDestroy() {
super.onDestroy();
// We need to get rid of the progress bar if it's showing
if (progress != null && progress.isShowing()) {
progress.dismiss();
}
if (ubbDB.isOpen()) {
ubbDB.close();
sqlParser.close();
}
}

@Override
public void onBackPressed() {
if (ubbDB.isOpen()) {
ubbDB.close();
sqlParser.close();
}
super.onBackPressed();
Intent classListIntent = new Intent();
classListIntent.putExtra(StaticVariables.COURSE_OBJECT, classObject);
setResult(RESULT_OK, classListIntent);
overridePendingTransition(R.anim.hold_back, R.anim.push_right_out);
}

@Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}

private void databaseLoaded() {
// The database has finished loading show the content
final ShowContent showContent = new ShowContent(getApplicationContext());
showContent.execute();

progress.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
showContent.cancel(true);
finish();
}
});
}

private class ShowContent extends AsyncTask<Void, Void, Integer> {
private Context context;
private PowerManager.WakeLock wakeLock;

protected ShowContent(Context context) {
this.context = context;
}

@Override
protected void onPreExecute() {
super.onPreExecute();
// Let's make sure the CPU doesn't go to sleep
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
if (!wakeLock.isHeld()) {
wakeLock.acquire();
}
}

@Override
protected Integer doInBackground(Void... voids) {
if (isCancelled()) {
return null;
}

// Get subjects by name in ascending order
String query = "SELECT " + sqlParser.combineColumnsStrings(DBStudents.ALL_COLUMNS, DBAttendance.ALL_COLUMNS) + " FROM " + DBStudents.TABLE_NAME +
" INNER JOIN (SELECT " + sqlParser.combineColumnsStrings(DBCoursesStudents.ALL_COLUMNS) + " FROM " + DBCoursesStudents.TABLE_NAME + " WHERE " + DBCoursesStudents.COLUMN_COURSE + "=" + classObject.getCourseId() + ") AS " + DBCoursesStudents.TABLE_NAME + " ON " + DBStudents.TABLE_NAME + "." + DBStudents.COLUMN_ID + "=" + DBCoursesStudents.TABLE_NAME + "." + DBCoursesStudents.COLUMN_STUDENT +
" INNER JOIN (SELECT " + sqlParser.combineColumnsStrings(DBAttendance.ALL_COLUMNS) + " FROM " + DBAttendance.TABLE_NAME + " WHERE " + DBAttendance.COLUMN_CLASS + "=" + classObject.getClassId() + ") AS " + DBAttendance.TABLE_NAME + " ON " + DBStudents.TABLE_NAME + "." + DBStudents.COLUMN_ID + "=" + DBAttendance.TABLE_NAME + "." + DBAttendance.COLUMN_STUDENT +
" ORDER BY " + DBStudents.COLUMN_FIRST_LAST_NAME + " ASC, " + DBStudents.COLUMN_FIRST_NAME + " ASC";
if (BuildConfig.DEBUG) {
Log.d("SubjectList", query);
}
Cursor cursor = ubbDB.rawQuery(query, null);

if (cursor.getCount() == 0) {
return 1;
}

// Iterate through the database rows
while (cursor.moveToNext()) {
if (isCancelled()) {
return null;
}

int status = cursor.getInt(cursor.getColumnIndex(DBAttendance.COLUMN_ATTENDANCE));
if (status != 0 && status != 3) {
students.add(new Attendance(
status,
cursor.getInt(cursor.getColumnIndex(DBStudents.COLUMN_ID)),
cursor.getString(cursor.getColumnIndex(DBStudents.COLUMN_RUN)),
cursor.getString(cursor.getColumnIndex(DBStudents.COLUMN_FIRST_NAME)),
cursor.getString(cursor.getColumnIndex(DBStudents.COLUMN_SECOND_NAME)),
cursor.getString(cursor.getColumnIndex(DBStudents.COLUMN_FIRST_LAST_NAME)),
cursor.getString(cursor.getColumnIndex(DBStudents.COLUMN_SECOND_LAST_NAME)),
cursor.getInt(cursor.getColumnIndex(DBStudents.COLUMN_MAJOR)),
cursor.getInt(cursor.getColumnIndex(DBStudents.COLUMN_ENROLLED)),
cursor.getString(cursor.getColumnIndex(DBStudents.COLUMN_EMAIL)),
cursor.getBlob(cursor.getColumnIndex(DBStudents.COLUMN_PHOTO))
));
}
}
cursor.close();

return 2;
}

@Override
protected void onPostExecute(Integer result) {
// Release the kraken errr wakelock
progress.dismiss();
wakeLock.release();

if (result == null) {
//The user cancelled the action
finish();
}
else if (result == 1) {
Toast.makeText(context, R.string.attendance_no_students_correct, Toast.LENGTH_SHORT).show();
finish();
}
else if (students.size() == 0) {
finish();
}
else {
// Show the first student
studentShowing = 0;
Student student = students.get(studentShowing);

if (student.getPhoto() == null) {
BitmapFactory.Options options = new BitmapFactory.Options();
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
if (activityManager.getMemoryClass() <= 64) {
options.inSampleSize = 2; // Shrink quality
}
else {
options.inSampleSize = 1; // Full quality
}
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.student_photo, options);
}
else {
BitmapFactory.Options options = new BitmapFactory.Options();
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
if (activityManager.getMemoryClass() <= 64) {
options.inSampleSize = 2; // Shrink quality
}
else {
options.inSampleSize = 1; // Full quality
}
bitmap = BitmapFactory.decodeByteArray(student.getPhoto(), 0, student.getPhoto().length, options);
}
ImageView imageView = (ImageView) findViewById(R.id.student_photo);
imageView.setImageBitmap(bitmap);
studentChecker(student, imageView);

// Show their name
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setSubtitle(student.getFullName());

buttonListeners();
}
}
}

private void buttonListeners() {
// Set up the listeners
Button button = (Button) findViewById(R.id.button_absent);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
attendance(3);
}
});

button = (Button) findViewById(R.id.button_present);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
attendance(-1);
}
});
}

private void attendance(int status) {
Attendance student = students.get(studentShowing);

// Don't change it if they maintain the attendance
if (status != -1) {
student.setStatus(status);

final SaveAttendance saveAttendance = new SaveAttendance(getApplicationContext(), this);
saveAttendance.execute(student);

progress.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
saveAttendance.cancel(true);
finish();
}
});
}

if (students.size() > studentShowing + 1) {
studentShowing++;
student = students.get(studentShowing);

// Really important to recycle the old bitmaps, if not it could crash from lack of heap space
if (bitmap != null) {
bitmap.recycle();
}

if (student.getPhoto() == null) {
BitmapFactory.Options options = new BitmapFactory.Options();
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
if (activityManager.getMemoryClass() <= 64) {
options.inSampleSize = 2; // Shrink quality
}
else {
options.inSampleSize = 1; // Full quality
}
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.student_photo, options);
}
else {
BitmapFactory.Options options = new BitmapFactory.Options();
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
if (activityManager.getMemoryClass() <= 64) {
options.inSampleSize = 2; // Shrink quality
}
else {
options.inSampleSize = 1; // Full quality
}
bitmap = BitmapFactory.decodeByteArray(student.getPhoto(), 0, student.getPhoto().length, options);
}
ImageView imageView = (ImageView) findViewById(R.id.student_photo);
imageView.setImageBitmap(bitmap);
studentChecker(student, imageView);

// Show their name
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setSubtitle(student.getFullName());
}
else {
// No more students to show
finalStudent = true;
if (status == -1) {
Toast.makeText(getApplicationContext(), R.string.attendance_saved, Toast.LENGTH_SHORT).show();

// Really important to recycle the old bitmaps, if not it could crash from lack of heap space
if (bitmap != null) {
bitmap.recycle();
bitmap = null;