cleand up the nfc part, added foreground-dispatch

* cleaned up the strings.xml files
* fixed license dialog
This commit is contained in:
Jannik 2019-08-18 22:09:33 +02:00
parent 733b675ffa
commit e74c307566
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
9 changed files with 178 additions and 69 deletions

View File

@ -13,7 +13,7 @@ android {
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 28 targetSdkVersion 28
versionCode 14 versionCode 14
versionName "0.4.94" versionName "0.4.95"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
resValue "string", "build_time", buildTime() resValue "string", "build_time", buildTime()
setProperty("archivesBaseName", "projectlaogai-$versionName") setProperty("archivesBaseName", "projectlaogai-$versionName")
@ -24,6 +24,7 @@ android {
minifyEnabled false minifyEnabled false
shrinkResources false shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
versionNameSuffix "-release"
} }
debug { debug {
versionNameSuffix "-debug" versionNameSuffix "-debug"

View File

@ -22,12 +22,12 @@
package org.mosad.seil0.projectlaogai package org.mosad.seil0.projectlaogai
import android.app.PendingIntent
import android.content.Intent import android.content.Intent
import android.content.IntentFilter
import android.graphics.Color import android.graphics.Color
import android.nfc.NdefMessage
import android.nfc.NfcAdapter import android.nfc.NfcAdapter
import android.nfc.Tag import android.nfc.tech.NfcA
import android.nfc.tech.IsoDep
import android.os.Bundle import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
@ -37,20 +37,16 @@ import androidx.core.view.GravityCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction import androidx.fragment.app.FragmentTransaction
import com.afollestad.aesthetic.Aesthetic import com.afollestad.aesthetic.Aesthetic
import com.afollestad.materialdialogs.MaterialDialog
import com.codebutler.farebot.card.desfire.DesfireProtocol
import com.google.android.material.navigation.NavigationView import com.google.android.material.navigation.NavigationView
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.app_bar_main.* import kotlinx.android.synthetic.main.app_bar_main.*
import org.mosad.seil0.projectlaogai.controller.CacheController import org.mosad.seil0.projectlaogai.controller.CacheController
import org.mosad.seil0.projectlaogai.controller.NFCMensaCard
import org.mosad.seil0.projectlaogai.controller.PreferencesController import org.mosad.seil0.projectlaogai.controller.PreferencesController
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cColorAccent import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cColorAccent
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cColorPrimary import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cColorPrimary
import org.mosad.seil0.projectlaogai.fragments.* import org.mosad.seil0.projectlaogai.fragments.*
import kotlin.system.measureTimeMillis import kotlin.system.measureTimeMillis
import com.codebutler.farebot.Utils.selectAppFile
import com.codebutler.farebot.card.desfire.DesfireFileSettings
import java.lang.Exception
// TODO save the current fragment to show it when the app is restarted // TODO save the current fragment to show it when the app is restarted
@ -58,6 +54,11 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
private var activeFragment: Fragment = HomeFragment() // the currently active fragment, home at the start private var activeFragment: Fragment = HomeFragment() // the currently active fragment, home at the start
private lateinit var adapter: NfcAdapter
private lateinit var pendingIntent: PendingIntent
private lateinit var intentFiltersArray: Array<IntentFilter>
private lateinit var techListsArray: Array<Array<String>>
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
Aesthetic.attach(this) Aesthetic.attach(this)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -67,6 +68,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
// load mensa, timetable and color // load mensa, timetable and color
load() load()
initAesthetic() initAesthetic()
initForegroundDispatch()
//init home fragment //init home fragment
val fragmentTransaction: FragmentTransaction = supportFragmentManager.beginTransaction() val fragmentTransaction: FragmentTransaction = supportFragmentManager.beginTransaction()
@ -81,65 +83,37 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
nav_view.setNavigationItemSelectedListener(this) nav_view.setNavigationItemSelectedListener(this)
// TODO nfc stuff, needs to move to it's own function // if we get an NFC read intent while the app is closed call readBalance
if (NfcAdapter.ACTION_TECH_DISCOVERED == intent.action) { if (NfcAdapter.ACTION_TECH_DISCOVERED == intent.action)
val appId = 0x5F8415 NFCMensaCard.readBalance(intent, this)
val fileId = 1
val tag: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
val isoDep = IsoDep.get(tag)
isoDep.connect()
val card = DesfireProtocol(isoDep)
val settings = selectAppFile(card, appId, fileId)
if (settings is DesfireFileSettings.ValueDesfireFileSettings) {
val data = try {
card.readValue(fileId)
} catch (ex: Exception) { 0 }
MaterialDialog(this)
.title(text = "Mensa balance")
.message(text = "current: ${data / 1000}.${(data % 1000) / 10}\n" +
"latest: ${settings.value / 1000}.${(settings.value % 1000) / 10}")
.show()
}
}
} }
override fun onNewIntent(intent: Intent) { override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent) super.onNewIntent(intent)
if (NfcAdapter.ACTION_TECH_DISCOVERED == intent.action) { if (NfcAdapter.ACTION_TECH_DISCOVERED == intent.action)
intent.getParcelableArrayExtra(NfcAdapter.EXTRA_TAG)?.also { rawMessages -> NFCMensaCard.readBalance(intent, this)
val messages: List<NdefMessage> = rawMessages.map { it as NdefMessage }
// Process the messages array.
MaterialDialog(this)
.title(text = "nfc tag detected (onNewIntent)")
.message(text = messages[0].toString())
.show()
}
}
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
Aesthetic.resume(this) Aesthetic.resume(this)
adapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray)
} }
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
Aesthetic.pause(this) Aesthetic.pause(this)
adapter.disableForegroundDispatch(this)
} }
override fun onBackPressed() { override fun onBackPressed() {
if (drawer_layout.isDrawerOpen(GravityCompat.START)) { if (drawer_layout.isDrawerOpen(GravityCompat.START)) {
drawer_layout.closeDrawer(GravityCompat.START) drawer_layout.closeDrawer(GravityCompat.START)
} else { } else {
// TODO only call on double tap
super.onBackPressed() super.onBackPressed()
} }
} }
@ -214,4 +188,15 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
} }
} }
private fun initForegroundDispatch() {
intentFiltersArray = arrayOf(IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED).apply { addDataType("*/*") })
techListsArray = arrayOf(arrayOf(NfcA::class.java.name))
adapter = NfcAdapter.getDefaultAdapter(this)
pendingIntent = PendingIntent.getActivity(
this, 0,
Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0
)
}
} }

View File

@ -0,0 +1,93 @@
/**
* ProjectLaogai
*
* Copyright 2019 <seil0@mosad.xyz>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
package org.mosad.seil0.projectlaogai.controller
import android.content.Context
import android.content.Intent
import android.nfc.NfcAdapter
import android.nfc.Tag
import android.nfc.tech.IsoDep
import com.afollestad.materialdialogs.MaterialDialog
import com.codebutler.farebot.Utils
import com.codebutler.farebot.card.desfire.DesfireFileSettings
import com.codebutler.farebot.card.desfire.DesfireProtocol
import org.mosad.seil0.projectlaogai.R
import java.lang.Exception
class NFCMensaCard {
companion object {
private const val appId = 0x5F8415
private const val fileId = 1
/**
* read the current balance and last payment from the mensa card
* @param intent a nfc intent
* @param context the context to show the dialog in
*/
fun readBalance(intent: Intent, context: Context) {
val tag: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
val isoDep = IsoDep.get(tag)
isoDep.connect()
val card = DesfireProtocol(isoDep)
val settings = Utils.selectAppFile(card, appId, fileId)
if (settings is DesfireFileSettings.ValueDesfireFileSettings) {
val data = try {
card.readValue(fileId)
} catch (ex: Exception) { 0 }
MaterialDialog(context)
.title(R.string.mensa_credit)
.message(text = lookAtMe(context, data, settings.value))
.show()
}
}
/**
* generate the values for current balance and last payment
* if the easter egg is active use schmeckles as currency
* 0.0000075 = 1.11 / 148 / 1000 (dollar / shm / card multiplier)
* @param context the context to access resources
* @param currentRaw the raw card value of the current balance
* @param lastRaw the raw card value of the last payment
* @return the message containing all values
*/
private fun lookAtMe(context: Context, currentRaw: Int, lastRaw: Int): String {
val current = if (!PreferencesController.oGiants) {
String.format("%.2f €", (currentRaw.toFloat() / 1000))
} else {
String.format("%.4f shm", (currentRaw.toFloat() * 0.0000075))
}
val last = if (!PreferencesController.oGiants) {
String.format("%.2f €", (lastRaw.toFloat() / 1000))
} else {
String.format("%.4f shm", (lastRaw.toFloat() * 0.0000075))
}
return context.resources.getString(R.string.mensa_current, current) + context.resources.getString(R.string.mensa_last, last)
}
}
}

View File

@ -42,6 +42,7 @@ class PreferencesController {
var cColorAccent: Int = Color.parseColor("#3F51B5") var cColorAccent: Int = Color.parseColor("#3F51B5")
var cCourse = Course("https://www.hs-offenburg.de/index.php?id=6627&class=class&iddV=DA64F6FE-9DDB-429E-A677-05D0D40CB636&week=0", "AI3") var cCourse = Course("https://www.hs-offenburg.de/index.php?id=6627&class=class&iddV=DA64F6FE-9DDB-429E-A677-05D0D40CB636&week=0", "AI3")
var cShowBuffet = true var cShowBuffet = true
var oGiants = false
// the save function // the save function
fun save(context: Context) { fun save(context: Context) {

View File

@ -124,6 +124,11 @@ class SettingsFragment : Fragment() {
// open a new dialog // open a new dialog
} }
linLayoutUser.setOnLongClickListener {
PreferencesController.oGiants = true // enable easter egg
return@setOnLongClickListener true
}
linLayoutCourse.setOnClickListener { linLayoutCourse.setOnClickListener {
selectCourse(context!!) selectCourse(context!!)
txtView_Course.text = cCourse.courseName // update txtView txtView_Course.text = cCourse.courseName // update txtView

View File

@ -19,7 +19,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing" android:paddingTop="@dimen/nav_header_vertical_spacing"
app:srcCompat="@mipmap/ic_laogai_icon" app:srcCompat="@mipmap/ic_laogai_icon"
android:contentDescription="@string/nav_header_desc" android:contentDescription="@string/app_name"
android:id="@+id/imageView"/> android:id="@+id/imageView"/>
<TextView <TextView

View File

@ -27,8 +27,8 @@
<notice> <notice>
<name>farebot part for desfire cards</name> <name>farebot part for desfire cards</name>
<url>https://github.com/codebutler/farebot</url> <url>https://github.com/codebutler/farebot</url>
<copyright /> <copyright>Copyright 2011-2012, 2014, 2016 Eric Butler</copyright>
<license>GNU General Public License v3.0</license> <license>GNU General Public License 3.0</license>
</notice> </notice>
<notice> <notice>
<name>Android Support Libraries</name> <name>Android Support Libraries</name>

View File

@ -1,36 +1,50 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="navigation_drawer_close">Navigationsleiste schließen</string>
<string name="navigation_drawer_open">Navigationsleiste öffnen</string>
<!-- nav-view -->
<string name="home">Home</string> <string name="home">Home</string>
<string name="mensa">Mensa</string> <string name="mensa">Mensa</string>
<string name="timetable">Stundenplan</string> <string name="timetable">Stundenplan</string>
<string name="moodle">Moodle</string> <string name="moodle">Moodle</string>
<string name="settings">Einstellungen</string> <string name="settings">Einstellungen</string>
<!-- fragment_home -->
<string name="meal">Essen</string> <string name="meal">Essen</string>
<string name="today_date">Heute, %1$s</string> <string name="today_date">Heute, %1$s</string>
<string name="tomorrow_date">Morgen, %1$s</string> <string name="tomorrow_date">Morgen, %1$s</string>
<string name="mensa_closed">keine Essensausgabe</string> <string name="mensa_closed">keine Essensausgabe</string>
<string name="no_more_food">Diese Woche keine weitere Essensausgabe</string> <string name="no_more_food">Diese Woche keine weitere Essensausgabe</string>
<string name="no_lesson_today">heute keine Vorlesung!</string> <string name="no_lesson_today">heute keine Vorlesung!</string>
<string name="error">Fehler</string>
<string name="timetable_error">Stundenplan konnte nicht geladen werden!</string> <!-- fragment_settings -->
<string name="info">Info</string> <string name="info">Info</string>
<string name="user">Benutzer</string> <string name="user">Benutzer</string>
<string name="course_desc">Tippen, um den Kurs zu ändern</string> <string name="course_desc">Tippen, um den Kurs zu ändern</string>
<string name="primary_color">Hauptfarbe</string>
<string name="primary_color_desc">Die Primärfarbe, Standard ist Schwarz.</string>
<string name="accent_color">Akzentfarbe</string>
<string name="accent_color_desc">Die Akzentfarbe, Standard ist indigo</string>
<string name="select">auswählen</string>
<string name="close">schließen</string>
<string name="about_dialog_heading">Über</string> <string name="about_dialog_heading">Über</string>
<string name="loading_timetable">lade Stundenplan …</string> <string name="licenses">Lizenzen</string>
<string name="navigation_drawer_close">Navigationsleiste schließen</string>
<string name="navigation_drawer_open">Navigationsleiste öffnen</string>
<string name="show_buffet">Buffet immer anzeigen</string>
<string name="select_course">Wähle deinen Studiengang aus</string>
<string name="theme">Design</string> <string name="theme">Design</string>
<string name="themeLight">Hell</string> <string name="themeLight">Hell</string>
<string name="themeDark">Dunkel</string> <string name="themeDark">Dunkel</string>
<string name="themeBlack">Schwarz</string> <string name="themeBlack">Schwarz</string>
<string name="licenses">Lizenzen</string> <string name="primary_color">Hauptfarbe</string>
<string name="primary_color_desc">Die Primärfarbe, Standard ist Schwarz.</string>
<string name="accent_color">Akzentfarbe</string>
<string name="accent_color_desc">Die Akzentfarbe, Standard ist indigo</string>
<string name="show_buffet">Buffet immer anzeigen</string>
<!-- dialogs -->
<string name="select_course">Wähle deinen Studiengang</string>
<string name="loading_timetable">lade Stundenplan …</string>
<string name="select">auswählen</string>
<string name="close">schließen</string>
<string name="mensa_credit">Mensa-Guthaben</string>
<string name="mensa_current">aktuell: %1$s\n</string>
<string name="mensa_last">letzte Abbuchung: %1$s</string>
<!-- errors -->
<string name="error">Fehler</string>
<string name="timetable_error">Stundenplan konnte nicht geladen werden!</string>
</resources> </resources>

View File

@ -4,31 +4,31 @@
<string name="navigation_drawer_close">Close navigation drawer</string> <string name="navigation_drawer_close">Close navigation drawer</string>
<string name="nav_header_title" translatable="false">Project Laogai</string> <string name="nav_header_title" translatable="false">Project Laogai</string>
<string name="nav_header_subtitle" translatable="false">seil0@mosad.xyz</string> <string name="nav_header_subtitle" translatable="false">seil0@mosad.xyz</string>
<string name="nav_header_desc" translatable="false">Project Laogai</string>
<!-- nav-view -->
<string name="home">Home</string> <string name="home">Home</string>
<string name="mensa">Mensa</string> <string name="mensa">Mensa</string>
<string name="timetable">Timetable</string> <string name="timetable">Timetable</string>
<string name="moodle">Moodle</string> <string name="moodle">Moodle</string>
<string name="settings">Settings</string> <string name="settings">Settings</string>
<!-- fragment_home -->
<string name="meal">Meal</string> <string name="meal">Meal</string>
<string name="today_date">Today, %1$s</string> <string name="today_date">Today, %1$s</string>
<string name="tomorrow_date">Tomorrow, %1$s</string> <string name="tomorrow_date">Tomorrow, %1$s</string>
<string name="mensa_closed">the Mensa is closed</string> <string name="mensa_closed">the Mensa is closed</string>
<string name="no_more_food">No more Food this week</string> <string name="no_more_food">No more Food this week</string>
<string name="no_lesson_today">"No lecture today!"</string>
<!-- fragment_settings -->
<string name="info">Info</string> <string name="info">Info</string>
<string name="user">User</string> <string name="user">User</string>
<string name="course_desc">Tap to change course</string> <string name="course_desc">Tap to change course</string>
<string name="select_course">Select your course</string>
<string name="loading_timetable">loading timetable …</string>
<string name="about_dialog_heading">About</string> <string name="about_dialog_heading">About</string>
<string name="about_dialog_text" translatable="false">"This software is made by @Seil0 and is published under the terms and conditions of GPL 3. For further information visit \ngit.mosad.xyz/Seil0/ProjectLaogai \n\n© 2018-2019 seil0@mosad.xyz "</string> <string name="about_dialog_text" translatable="false">"This software is made by @Seil0 and is published under the terms and conditions of GPL 3. For further information visit \ngit.mosad.xyz/Seil0/ProjectLaogai \n\n© 2018-2019 seil0@mosad.xyz "</string>
<string name="about_txtView" translatable="false">hso App by @Seil0</string> <string name="about_txtView" translatable="false">hso App by @Seil0</string>
<string name="about_version" translatable="false">Version %1$s (%2$s)</string> <string name="about_version" translatable="false">Version %1$s (%2$s)</string>
<string name="licenses">Licenses</string> <string name="licenses">Licenses</string>
<string name="theme">Theme</string> <string name="theme">Theme</string>
<string name="themeLight">Light</string> <string name="themeLight">Light</string>
<string name="themeDark">Dark</string> <string name="themeDark">Dark</string>
@ -38,18 +38,28 @@
<string name="accent_color">Accent color</string> <string name="accent_color">Accent color</string>
<string name="accent_color_desc">The accent color, default is indigo.</string> <string name="accent_color_desc">The accent color, default is indigo.</string>
<string name="show_buffet">Always show buffet</string> <string name="show_buffet">Always show buffet</string>
<!-- dialogs -->
<string name="select_course">Select your course</string>
<string name="loading_timetable">loading timetable …</string>
<string name="select">select</string> <string name="select">select</string>
<string name="close">close</string> <string name="close">close</string>
<string name="mensa_credit">Mensa credit</string>
<string name="mensa_current">current: %1$s\n</string>
<string name="mensa_last">last: %1$s</string>
<string name="sample_user" translatable="false">SampleUser@stud.hs-offenburg.de</string>
<!-- sample strings -->
<string name="sample_user" translatable="false">spinefield@stud.hs-offenburg.de</string>
<string name="sample_course" translatable="false">SampleCourse 3</string> <string name="sample_course" translatable="false">SampleCourse 3</string>
<string name="sample_date" translatable="false">Montag, 30.02</string> <string name="sample_date" translatable="false">Montag, 30.02</string>
<string name="a_time" translatable="false">0.00 23.59</string> <string name="a_time" translatable="false">0.00 23.59</string>
<string name="no_lesson_today">"No lecture today!"</string> <!-- errors -->
<string name="error">Error</string> <string name="error">Error</string>
<string name="timetable_error">Could not load timetable!"</string> <string name="timetable_error">Could not load timetable!"</string>
<!-- save keys -->
<string name="save_key_course" translatable="false">org.mosad.seil0.projectlaogai.course</string> <string name="save_key_course" translatable="false">org.mosad.seil0.projectlaogai.course</string>
<string name="save_key_courseTTLink" translatable="false">org.mosad.seil0.projectlaogai.courseTTLink</string> <string name="save_key_courseTTLink" translatable="false">org.mosad.seil0.projectlaogai.courseTTLink</string>
<string name="save_key_colorPrimary" translatable="false">org.mosad.seil0.projectlaogai.colorPrimary</string> <string name="save_key_colorPrimary" translatable="false">org.mosad.seil0.projectlaogai.colorPrimary</string>