Page MenuHomeGitPull.it

D45.1729228210.diff
No OneTemporary

Size
126 KB
Referenced Files
None
Subscribers
None

D45.1729228210.diff

diff --git a/AndroidManifest.xml b/AndroidManifest.xml
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -15,10 +15,12 @@
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application
- android:allowBackup="true"
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- android:theme="@style/AppTheme">
+ android:name=".BustoApp"
+ android:networkSecurityConfig="@xml/networks_security_config"
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme">
<activity
android:name=".ActivityMain"
android:label="@string/app_name"
diff --git a/build.gradle b/build.gradle
--- a/build.gradle
+++ b/build.gradle
@@ -7,10 +7,19 @@
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.1.0'
+
+ classpath 'com.android.tools.build:gradle:4.0.0'
}
ext {
- support_ver = "25.4.0"
+ //libraries versions
+ fragment_version = "1.2.5"
+ activity_version = "1.1.0"
+ appcompat_version = "1.2.0"
+ preference_version = "1.1.1"
+ work_version = "2.4.0"
+
+ acra_version = "5.7.0"
+
}
}
allprojects {
@@ -25,13 +34,13 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 25
- buildToolsVersion '27.0.3'
+ compileSdkVersion 28
+ buildToolsVersion '29.0.3'
defaultConfig {
applicationId "it.reyboz.bustorino"
- minSdkVersion 9
- targetSdkVersion 25
+ minSdkVersion 14
+ targetSdkVersion 28
versionCode 30
versionName "1.13.1"
vectorDrawables.useSupportLibrary = true
@@ -70,18 +79,28 @@
}
dependencies {
- implementation "com.android.support:support-v4:$support_ver"
- implementation "com.android.support:appcompat-v7:$support_ver"
- implementation "com.android.support:design:$support_ver"
- implementation "com.android.support:recyclerview-v7:$support_ver"
- implementation "com.android.support:preference-v7:$support_ver"
- implementation "com.android.support:cardview-v7:$support_ver"
+ //new libraries
+ implementation "androidx.fragment:fragment:$fragment_version"
+ implementation "androidx.activity:activity:$activity_version"
+ implementation "androidx.annotation:annotation:1.1.0"
+ implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
+ implementation "androidx.appcompat:appcompat:$appcompat_version"
+ implementation "androidx.appcompat:appcompat-resources:$appcompat_version"
+ implementation "androidx.preference:preference:$preference_version"
+ implementation "androidx.work:work-runtime:$work_version"
- implementation 'org.jsoup:jsoup:1.11.3'
+ implementation 'com.google.android.material:material:1.2.1'
+
+
+ implementation 'org.jsoup:jsoup:1.13.1'
implementation 'com.readystatesoftware.sqliteasset:sqliteassethelper:2.0.1'
implementation 'com.android.volley:volley:1.1.1'
- implementation 'org.osmdroid:osmdroid-android:6.1.3'
+ implementation 'org.osmdroid:osmdroid-android:6.1.8'
+ // ACRA
+ implementation "ch.acra:acra-mail:$acra_version"
+ implementation "ch.acra:acra-dialog:$acra_version"
+
}
}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1 @@
+android.useAndroidX=true
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,6 @@
+#Thu Oct 01 23:03:06 CEST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
diff --git a/res/drawable/ic_bus_orange.xml b/res/drawable/ic_bus_orange.xml
new file mode 100644
--- /dev/null
+++ b/res/drawable/ic_bus_orange.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="453.543dp"
+ android:height="453.543dp"
+ android:viewportWidth="453.543"
+ android:viewportHeight="453.543">
+ <path
+ android:pathData="M367.524,92.122c-4.208,-21.045 -17.678,-29.463 -37.882,-37.882c-19.918,-8.299 -67.648,-18.229 -102.872,-18.507C191.548,36.012 143.819,45.941 123.9,54.24c-20.204,8.418 -33.673,16.836 -37.882,37.882L70.866,208.794V369.56h26.096v25.211c0,30.739 44.984,30.739 44.984,0V369.56h83.048h0.263h86.341v25.211c0,30.739 44.983,30.739 44.983,0V369.56h26.096V208.794L367.524,92.122zM162.625,65.184h62.631h65.662c12.628,0 12.628,18.941 0,18.941h-65.815h-62.478C149.997,84.125 149.997,65.184 162.625,65.184zM119.472,319.162c-11.918,0 -21.58,-9.662 -21.58,-21.58s9.662,-21.579 21.58,-21.579s21.58,9.661 21.58,21.579S131.39,319.162 119.472,319.162zM225.256,221.09H110.797c-11.206,0 -13.552,-8.051 -12.452,-16.162l11.793,-84.621c1.62,-10.281 5.105,-17.059 18.444,-17.059h96.521h99.857c13.34,0 16.824,6.778 18.443,17.059l11.795,84.621c1.1,8.111 -1.246,16.162 -12.452,16.162H225.256zM334.07,319.162c-11.918,0 -21.579,-9.662 -21.579,-21.58s9.661,-21.579 21.579,-21.579s21.579,9.661 21.579,21.579S345.988,319.162 334.07,319.162z"
+ android:fillColor="#f57c00"/>
+</vector>
diff --git a/res/layout-v11/activity_main.xml b/res/layout-v11/activity_main.xml
--- a/res/layout-v11/activity_main.xml
+++ b/res/layout-v11/activity_main.xml
@@ -1,5 +1,4 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:fab="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -128,7 +127,7 @@
android:textSize="19sp"
android:visibility="gone" />
- <android.support.v4.widget.SwipeRefreshLayout
+ <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/listRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -143,8 +142,8 @@
android:id="@+id/resultFrame"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true" android:layout_alignParentStart="true"/>
- </android.support.v4.widget.SwipeRefreshLayout>
- <android.support.design.widget.FloatingActionButton
+ </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
+ <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/floatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/res/layout/activity_main.xml b/res/layout/activity_main.xml
--- a/res/layout/activity_main.xml
+++ b/res/layout/activity_main.xml
@@ -1,5 +1,4 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:fab="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -128,7 +127,7 @@
android:textColor="@color/grey_100"
android:textSize="19sp"
android:visibility="gone" />
- <android.support.v4.widget.SwipeRefreshLayout
+ <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/listRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -141,9 +140,9 @@
android:layout_height="fill_parent"
android:layout_alignParentLeft="true" android:layout_alignParentStart="true">
</FrameLayout>
- </android.support.v4.widget.SwipeRefreshLayout>
+ </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
- <android.support.design.widget.FloatingActionButton
+ <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/floatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/res/layout/arrivals_nearby_card.xml b/res/layout/arrivals_nearby_card.xml
--- a/res/layout/arrivals_nearby_card.xml
+++ b/res/layout/arrivals_nearby_card.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
-<android.support.v7.widget.CardView
+<androidx.cardview.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools" android:id="@+id/stop_cardView"
+ android:id="@+id/stop_cardView"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
@@ -88,4 +88,4 @@
</RelativeLayout>
-</android.support.v7.widget.CardView>
\ No newline at end of file
+</androidx.cardview.widget.CardView>
\ No newline at end of file
diff --git a/res/layout/fragment_arrivals.xml b/res/layout/fragment_arrivals.xml
new file mode 100644
--- /dev/null
+++ b/res/layout/fragment_arrivals.xml
@@ -0,0 +1,98 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:fab="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/messageCardView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dp"
+ android:layout_marginLeft="16dp"
+ android:layout_marginTop="16dp"
+ android:layout_marginEnd="16dp"
+ android:layout_marginRight="16dp"
+ android:layout_marginBottom="10dp"
+ fab:cardCornerRadius="5dp"
+ fab:cardElevation="2dp">
+
+ <TextView
+ android:id="@+id/messageTextView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="8dp"
+ android:layout_marginLeft="8dp"
+ android:layout_toStartOf="@+id/addToFavorites"
+ android:layout_toLeftOf="@+id/addToFavorites"
+
+ android:foreground="?attr/selectableItemBackground"
+ android:gravity="center_vertical"
+ android:minHeight="40dp"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <ImageButton
+ android:id="@+id/addToFavorites"
+ android:layout_width="45dp"
+ android:layout_height="match_parent"
+ android:layout_gravity="end"
+ android:background="@android:color/transparent"
+ android:foreground="?attr/selectableItemBackground"
+ fab:srcCompat="@drawable/ic_star_outline"
+ tools:ignore="OnClick" />
+
+ </androidx.cardview.widget.CardView>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_below="@+id/messageCardView"
+ android:orientation="vertical"
+
+ android:layout_height="wrap_content">
+
+ <ListView
+ android:id="@+id/resultsListView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="9"
+ android:clickable="true"
+ android:descendantFocusability="blocksDescendants"
+ android:focusable="true"
+ android:scrollbars="vertical"
+ android:visibility="visible">
+
+ </ListView>
+
+ <View
+ android:id="@+id/divider_arr"
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="@color/grey_100"
+ />
+
+ <LinearLayout
+ android:id="@+id/theLinearLayout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+
+ android:layout_marginTop="5dp"
+
+ android:layout_marginBottom="5dp"
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@+id/timesSourceTextView"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="15dp"
+ android:layout_marginLeft="15dp"
+ android:text="Source of arrivals"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="19sp"
+
+ />
+ </LinearLayout>
+ </LinearLayout>
+
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/fragment_list_view.xml b/res/layout/fragment_list_view.xml
--- a/res/layout/fragment_list_view.xml
+++ b/res/layout/fragment_list_view.xml
@@ -4,45 +4,40 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
- <android.support.v7.widget.CardView
- android:id="@+id/favorites_cardView"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/messageCardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
fab:cardElevation="2dp"
fab:cardCornerRadius="5dp"
android:layout_margin="16dp">
- <TextView
- android:id="@+id/messageTextView"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_toLeftOf="@+id/addToFavorites"
- android:gravity="center_vertical"
- android:layout_marginLeft="4dp"
- android:minHeight="48dp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_toStartOf="@+id/addToFavorites"
- android:layout_marginStart="4dp"
- android:foreground="?attr/selectableItemBackground" />
+ <TextView
+ android:id="@+id/messageTextView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_toLeftOf="@+id/addToFavorites"
+ android:gravity="center_vertical"
+ android:layout_marginLeft="15dp"
+ android:layout_marginStart="15dp"
- <ImageButton
- android:id="@+id/addToFavorites"
- android:layout_width="45dp"
- android:layout_height="match_parent"
- android:layout_gravity="end"
- android:background="@android:color/transparent"
- fab:srcCompat="@drawable/ic_star_outline"
- tools:ignore="OnClick"
- android:foreground="?attr/selectableItemBackground" />
+ android:minHeight="48dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_toStartOf="@+id/addToFavorites"
+ android:foreground="?attr/selectableItemBackground" />
- </android.support.v7.widget.CardView>
+ </androidx.cardview.widget.CardView>
<ListView
android:id="@+id/resultsListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_below="@+id/favorites_cardView"
android:clickable="true"
+ android:focusable="true"
+ android:layout_below="@id/messageCardView"
android:descendantFocusability="blocksDescendants"
- android:visibility="visible" />
+ android:visibility="visible" >
+
+
+ </ListView>
</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/fragment_nearby_stops.xml b/res/layout/fragment_nearby_stops.xml
--- a/res/layout/fragment_nearby_stops.xml
+++ b/res/layout/fragment_nearby_stops.xml
@@ -14,7 +14,7 @@
android:layout_toLeftOf="@id/switchButton" android:layout_marginLeft="10dp"
android:layout_marginStart="10dp" android:layout_marginRight="10dp" android:layout_marginEnd="10dp"
/>
- <android.support.v7.widget.AppCompatButton
+ <androidx.appcompat.widget.AppCompatButton
xmlns:app="http://schemas.android.com/apk/res-auto"
android:text="@string/show_arrivals"
android:layout_width="wrap_content"
@@ -27,7 +27,7 @@
/>
- <android.support.v7.widget.RecyclerView
+ <androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_below="@id/titleTextView"
android:id="@+id/stopGridRecyclerView"
diff --git a/res/layout/stop_card.xml b/res/layout/stop_card.xml
--- a/res/layout/stop_card.xml
+++ b/res/layout/stop_card.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
-<android.support.v7.widget.CardView
+<androidx.cardview.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools" android:id="@+id/stop_cardView"
+ android:id="@+id/stop_cardView"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
@@ -113,4 +113,4 @@
android:padding="5dp" android:maxWidth="100sp" android:layout_gravity="center_vertical|end"
android:layout_marginRight="5dp"/>
</LinearLayout>
-</android.support.v7.widget.CardView>
\ No newline at end of file
+</androidx.cardview.widget.CardView>
\ No newline at end of file
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -30,13 +30,16 @@
<string name="cant_add_to_favorites">Impossibile aggiungere ai preferiti (memoria piena o database corrotto?)!</string>
<string name="title_activity_favorites">Preferiti</string>
<string name="title_activity_map">Mappa</string>
- <string name="tip_add_favorite">Nessun preferito? Arghh! Schiaccia sulla stella di una fermata per aggiungerla a questa lista!</string>
+ <string name="tip_add_favorite">Nessun preferito? Arghh!\nSchiaccia sulla stella di una fermata per aggiungerla a questa lista!</string>
<string name="action_remove_from_favourites">Rimuovi</string>
<string name="action_rename_bus_stop_username">Rinomina</string>
<string name="dialog_rename_bus_stop_username_title">Rinomina fermata</string>
<string name="dialog_rename_bus_stop_username_reset_button">Reset</string>
<string name="about">Informazioni</string>
- <string name="howDoesItWork"><b>Tocca la stella</b> per aggiungere la fermata ai preferiti\n\n<b>Come leggere gli orari:</b>\n<b>&#160;&#160;&#160;12:56*</b> Orario in tempo reale\n<b>&#160;&#160;&#160;12:56</b> &#160; Orario programmato\n\n<b>Trascina giù per aggiornare</b> l\'orario.</string>
+ <string name="howDoesItWork"><b>Tocca la stella</b> per aggiungere la fermata ai preferiti\n\n<b>Come leggere gli orari:</b>
+ \n<b>&#160;&#160;&#160;12:56*</b> Orario in tempo reale\n<b>&#160;&#160;&#160;12:56</b> &#160; Orario programmato\n\n<b>Trascina giù per aggiornare</b> l\'orario.
+ \n<b>Tocca a lungo</b> su <b>Fonte Orari</b> per cambiare sorgente degli orari di arrivo.
+ </string>
<string name="hint_button">OK!</string>
<string name="about_history">
<![CDATA[
@@ -115,4 +118,24 @@
<string name="bt_center_map_description">La mia posizione</string>
<string name="bt_follow_me_description">Segui posizione</string>
+ <!--
+ Arrival times sources
+ !-->
+ <string name="times_source_fmt">Fonte orari: %1$s</string>
+ <string name="fivetapifetcher">App GTT</string>
+ <string name="gttjsonfetcher">Sito GTT</string>
+ <string name="fivetscraper">Sito 5T Torino</string>
+ <string name="arrival_source_changing">Cambiamento sorgente orari…</string>
+ <string name="change_arrivals_source_message">Premi a lungo per cambiare la sorgente degli orari</string>
+
+
+ <string name="default_notification_channel_description">Canale unico delle notifiche</string>
+ <string name="too_many_permission_asks">Chiesto troppe volte per il permesso %1$s</string>
+ <string name="permission_storage_maps_msg">Non si può usare questa funzionalità senza il permesso di archivio</string>
+ <string name="storage_permission">di archivio</string>
+ <string name="message_crash">L\'app è andata in crash. Invia il report agli sviluppatori toccando OK.
+ \n Il report potrebbe contenere informazioni sulla tua configurazione del telefono, o sullo stato al momento del crash.
+ \n Tutte le informazioni sensibili nel report verranno utilizzate solo per scopi diagnostici dagli sviluppatori, e non verranno mai pubblicate e/o divulgate.</string>
+ <string name="acra_email_message">L\'applicazione è crashata, e il crash report è stato messo negli allegati. Se vuoi, descrivi cosa stavi facendo prima del crash: \n</string>
+
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -46,6 +46,7 @@
<b>Tap the star</b>
to add the bus stop to the favourites\n\n<b>How to read timelines:</b>\n<b>&#160;&#160;&#160;12:56*</b> Real-time
arrivals\n<b>&#160;&#160;&#160;12:56</b> &#160; Scheduled arrivals\n\n<b>Pull down to refresh</b> the timetable
+ \n <b>Long press on Arrivals source</b> to change the source of the arrival times
</string>
<string name="hint_button">GOT IT!</string>
<string name="about_history">
@@ -126,4 +127,25 @@
<string name="bt_center_map_description">Center on my location</string>
<string name="bt_follow_me_description">Follow me</string>
+ <!--
+ Arrival times sources
+ !-->
+ <string name="times_source_fmt">Arrivals source: %1$s</string>
+ <string name="fivetapifetcher">GTT App</string>
+ <string name="gttjsonfetcher">GTT Website</string>
+ <string name="fivetscraper">5T Torino website</string>
+ <string name="arrival_source_changing">Changing arrival times source…</string>
+ <string name="change_arrivals_source_message">Long press to change the source of arrivals</string>
+
+ <!--
+ Notifications
+ -->
+ <string name="default_notification_channel" translatable="false">Default</string>
+ <string name="default_notification_channel_description">Default channel for notifications</string>
+ <string name="too_many_permission_asks">Asked for %1$s permission too many times</string>
+ <string name="permission_storage_maps_msg">Cannot use the map with the storage permission!</string>
+ <string name="storage_permission">storage</string>
+ <string name="message_crash">The application has crashed. If you want, you can send the send the report via email to the developers by pressing \"OK\".
+ \n Note that sensitive information may be contained in the report, and if so, it will be only used for diagnostic purposes by the developers, and never published.</string>
+ <string name="acra_email_message">The application crashed and the crash report is in the attachments. Please describe what you were doing before the crash: \n</string>
</resources>
diff --git a/res/xml/networks_security_config.xml b/res/xml/networks_security_config.xml
new file mode 100644
--- /dev/null
+++ b/res/xml/networks_security_config.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+ <domain-config cleartextTrafficPermitted="true">
+ <domain includeSubdomains="true">5t.torino.it</domain>
+ <domain includeSubdomains="true">gtt.to.it</domain>
+
+ </domain-config>
+</network-security-config>
\ No newline at end of file
diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml
--- a/res/xml/preferences.xml
+++ b/res/xml/preferences.xml
@@ -1,15 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
-<android.support.v7.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
- <android.support.v7.preference.PreferenceCategory
+ <androidx.preference.PreferenceCategory
android:title="General">
- <android.support.v7.preference.SwitchPreferenceCompat
+ <androidx.preference.SwitchPreferenceCompat
android:defaultValue="false"
android:title="@string/settings_experimental" android:key="@string/pref_key_experimental"/>
- </android.support.v7.preference.PreferenceCategory>
- <android.support.v7.preference.PreferenceCategory
+ </androidx.preference.PreferenceCategory>
+ <androidx.preference.PreferenceCategory
android:title="@string/pref_recents_group_title">
- <android.support.v7.preference.EditTextPreference
+ <androidx.preference.EditTextPreference
android:defaultValue="10"
android:selectAllOnFocus="true"
android:singleLine="true"
@@ -17,7 +17,7 @@
android:digits="0123456789" android:ems="10"
/>
- <android.support.v7.preference.SeekBarPreference
+ <androidx.preference.SeekBarPreference
android:title="@string/settings_search_radius"
android:key="@string/pref_key_radius_recents"
android:defaultValue="500"
@@ -27,6 +27,6 @@
android:layout_height="wrap_content"
android:gravity="center_vertical"
/>
- </android.support.v7.preference.PreferenceCategory>
+ </androidx.preference.PreferenceCategory>
-</android.support.v7.preference.PreferenceScreen>
+</androidx.preference.PreferenceScreen>
diff --git a/src/it/reyboz/bustorino/ActivityAbout.java b/src/it/reyboz/bustorino/ActivityAbout.java
--- a/src/it/reyboz/bustorino/ActivityAbout.java
+++ b/src/it/reyboz/bustorino/ActivityAbout.java
@@ -17,9 +17,9 @@
*/
package it.reyboz.bustorino;
-import android.support.v4.app.NavUtils;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
+import androidx.core.app.NavUtils;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AppCompatActivity;
import android.text.Html;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
diff --git a/src/it/reyboz/bustorino/ActivityFavorites.java b/src/it/reyboz/bustorino/ActivityFavorites.java
--- a/src/it/reyboz/bustorino/ActivityFavorites.java
+++ b/src/it/reyboz/bustorino/ActivityFavorites.java
@@ -18,8 +18,8 @@
package it.reyboz.bustorino;
import android.database.Cursor;
-import android.support.v4.app.LoaderManager;
-import android.support.v4.content.Loader;
+import androidx.loader.app.LoaderManager;
+import androidx.loader.content.Loader;
import android.widget.*;
import it.reyboz.bustorino.backend.Stop;
import it.reyboz.bustorino.adapters.StopAdapter;
@@ -30,11 +30,10 @@
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
-import android.net.Uri;
import android.os.AsyncTask;
-import android.support.v4.app.NavUtils;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
+import androidx.core.app.NavUtils;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AppCompatActivity;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
@@ -46,8 +45,6 @@
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
-import org.osmdroid.util.GeoPoint;
-
import java.util.List;
public class ActivityFavorites extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {
diff --git a/src/it/reyboz/bustorino/ActivityMain.java b/src/it/reyboz/bustorino/ActivityMain.java
--- a/src/it/reyboz/bustorino/ActivityMain.java
+++ b/src/it/reyboz/bustorino/ActivityMain.java
@@ -17,23 +17,37 @@
*/
package it.reyboz.bustorino;
-import android.annotation.SuppressLint;
+import android.Manifest;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.database.sqlite.SQLiteDatabase;
import android.location.*;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
-import android.support.annotation.NonNull;
-import android.support.design.widget.Snackbar;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentTransaction;
-import android.support.v4.app.NavUtils;
-import android.support.v4.widget.SwipeRefreshLayout;
+
+import androidx.annotation.NonNull;
+import androidx.core.app.ActivityCompat;
+import androidx.work.BackoffPolicy;
+import androidx.work.Constraints;
+import androidx.work.ExistingPeriodicWorkPolicy;
+import androidx.work.NetworkType;
+import androidx.work.PeriodicWorkRequest;
+import androidx.work.WorkInfo;
+import androidx.work.WorkManager;
+
+import com.google.android.material.snackbar.Snackbar;
+
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+import androidx.core.app.NavUtils;
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
+
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
@@ -45,13 +59,16 @@
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
-import android.support.design.widget.FloatingActionButton;
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
import it.reyboz.bustorino.backend.*;
import it.reyboz.bustorino.fragments.*;
import it.reyboz.bustorino.middleware.*;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.TimeUnit;
public class ActivityMain extends GeneralActivity implements FragmentListener {
@@ -82,12 +99,7 @@
* Options
*/
private final String OPTION_SHOW_LEGEND = "show_legend";
- private final String LOCATION_PERMISSION_GIVEN = "loc_permission";
- /*
- * Status
- */
- private DBStatusManager prefsManager;
- private DBStatusManager.OnDBUpdateStatusChangeListener updatelistener;
+
private static final String DEBUG_TAG = "BusTO - MainActivity";
/* // useful for testing:
public class MockFetcher implements ArrivalsFetcher {
@@ -99,9 +111,8 @@
}
}
private ArrivalsFetcher[] ArrivalFetchers = {new MockFetcher(), new MockFetcher(), new MockFetcher(), new MockFetcher(), new MockFetcher()};*/
-
- private RecursionHelper<ArrivalsFetcher> ArrivalFetchersRecursionHelper = new RecursionHelper<>(new ArrivalsFetcher[]{new GTTJSONFetcher(), new FiveTScraperFetcher()});
- private RecursionHelper<StopsFinderByName> StopsFindersByNameRecursionHelper = new RecursionHelper<>(new StopsFinderByName[]{new GTTStopsFetcher(), new FiveTStopsFetcher()});
+ private ArrivalsFetcher[] arrivalsFetchers = new ArrivalsFetcher[]{new FiveTAPIFetcher(), new GTTJSONFetcher(), new FiveTScraperFetcher()};
+ private StopsFinderByName[] stopsFinderByNames = new StopsFinderByName[]{new GTTStopsFetcher(), new FiveTStopsFetcher()};
/*
* Position
*/
@@ -109,11 +120,6 @@
private final Criteria cr = new Criteria();
private boolean pendingNearbyStopsRequest = false;
private LocationManager locmgr;
- /*
- * Database Access
- */
- private StopsDB stopsDB;
- private UserDB userDB;
private FragmentHelper fh;
///////////////////////////////// EVENT HANDLERS ///////////////////////////////////////////////
@@ -121,78 +127,64 @@
/*
* @see swipeRefreshLayout
*/
- private Handler handler = new Handler();
+ private final Handler theHandler = new Handler();
private final Runnable refreshing = new Runnable() {
public void run() {
if (framan.findFragmentById(R.id.resultFrame) instanceof ArrivalsFragment) {
ArrivalsFragment fragment = (ArrivalsFragment) framan.findFragmentById(R.id.resultFrame);
String stopName = fragment.getStopID();
- new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS, fh).execute(stopName);
- } else
- new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS, fh).execute();
+
+ new AsyncDataDownload(fh, fragment.getCurrentFetchersAsArray()).execute(stopName);
+ } else //we create a new fragment, which is WRONG
+ new AsyncDataDownload(fh, arrivalsFetchers).execute();
}
};
+
//// MAIN METHOD ///
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
framan = getSupportFragmentManager();
- this.stopsDB = new StopsDB(getApplicationContext());
- this.userDB = new UserDB(getApplicationContext());
+ final SharedPreferences theShPr = getMainSharedPreferences();
+ /*
+ * Database Access
+ */
setContentView(R.layout.activity_main);
- busStopSearchByIDEditText = (EditText) findViewById(R.id.busStopSearchByIDEditText);
- busStopSearchByNameEditText = (EditText) findViewById(R.id.busStopSearchByNameEditText);
- progressBar = (ProgressBar) findViewById(R.id.progressBar);
- howDoesItWorkTextView = (TextView) findViewById(R.id.howDoesItWorkTextView);
- hideHintButton = (Button) findViewById(R.id.hideHintButton);
- swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.listRefreshLayout);
- floatingActionButton = (FloatingActionButton) findViewById(R.id.floatingActionButton);
-
- framan.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
- @Override
- public void onBackStackChanged() {
- Log.d("MainActivity, BusTO", "BACK STACK CHANGED");
- }
- });
+ busStopSearchByIDEditText = findViewById(R.id.busStopSearchByIDEditText);
+ busStopSearchByNameEditText = findViewById(R.id.busStopSearchByNameEditText);
+ progressBar = findViewById(R.id.progressBar);
+ howDoesItWorkTextView = findViewById(R.id.howDoesItWorkTextView);
+ hideHintButton = findViewById(R.id.hideHintButton);
+ swipeRefreshLayout = findViewById(R.id.listRefreshLayout);
+ floatingActionButton = findViewById(R.id.floatingActionButton);
+
+ framan.addOnBackStackChangedListener(() -> Log.d("MainActivity, BusTO", "BACK STACK CHANGED"));
busStopSearchByIDEditText.setSelectAllOnFocus(true);
busStopSearchByIDEditText
- .setOnEditorActionListener(new TextView.OnEditorActionListener() {
- @Override
- public boolean onEditorAction(TextView v, int actionId,
- KeyEvent event) {
- // IME_ACTION_SEARCH alphabetical option
- if (actionId == EditorInfo.IME_ACTION_SEARCH) {
- onSearchClick(v);
- return true;
- }
- return false;
+ .setOnEditorActionListener((v, actionId, event) -> {
+ // IME_ACTION_SEARCH alphabetical option
+ if (actionId == EditorInfo.IME_ACTION_SEARCH) {
+ onSearchClick(v);
+ return true;
}
+ return false;
});
busStopSearchByNameEditText
- .setOnEditorActionListener(new TextView.OnEditorActionListener() {
- @Override
- public boolean onEditorAction(TextView v, int actionId,
- KeyEvent event) {
- // IME_ACTION_SEARCH alphabetical option
- if (actionId == EditorInfo.IME_ACTION_SEARCH) {
- onSearchClick(v);
- return true;
- }
- return false;
+ .setOnEditorActionListener((v, actionId, event) -> {
+ // IME_ACTION_SEARCH alphabetical option
+ if (actionId == EditorInfo.IME_ACTION_SEARCH) {
+ onSearchClick(v);
+ return true;
}
+ return false;
});
// Called when the layout is pulled down
swipeRefreshLayout
- .setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
- @Override
- public void onRefresh() {
- handler.post(refreshing);
- }
- });
+ .setOnRefreshListener(() -> theHandler.post(refreshing));
/**
* @author Marco Gagino!!!
@@ -241,7 +233,6 @@
if (tryedFromIntent) {
// This shows a luser warning
- ArrivalFetchersRecursionHelper.reset();
Toast.makeText(getApplicationContext(),
R.string.insert_bus_stop_number_error, Toast.LENGTH_SHORT).show();
}
@@ -260,32 +251,54 @@
createFragmentForStop(busStopID);
}
//Try (hopefully) database update
- //TODO: Start the service in foreground, check last time it ran before
- DatabaseUpdateService.startDBUpdate(getApplicationContext());
+ //TODO: Check if service shows the notification
+ //Old code for the db update
+ //DatabaseUpdateService.startDBUpdate(getApplicationContext());
+
+
+ PeriodicWorkRequest wr = new PeriodicWorkRequest.Builder(DBUpdateWorker.class, 1, TimeUnit.DAYS)
+ .setBackoffCriteria(BackoffPolicy.LINEAR, 30, TimeUnit.MINUTES)
+ .setConstraints(new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED)
+ .build())
+ .build();
+ final WorkManager workManager = WorkManager.getInstance(this);
+
+ final int version = theShPr.getInt(DatabaseUpdate.DB_VERSION_KEY, -10);
+ if (version >= 0)
+ workManager.enqueueUniquePeriodicWork(DBUpdateWorker.DEBUG_TAG,
+ ExistingPeriodicWorkPolicy.KEEP, wr);
+ else workManager.enqueueUniquePeriodicWork(DBUpdateWorker.DEBUG_TAG,
+ ExistingPeriodicWorkPolicy.REPLACE, wr);
/*
Set database update
*/
- updatelistener = new DBStatusManager.OnDBUpdateStatusChangeListener() {
- @Override
- public boolean defaultStatusValue() {
- return true;
- }
+ workManager.getWorkInfosForUniqueWorkLiveData(DBUpdateWorker.DEBUG_TAG)
+ .observe(this, workInfoList -> {
+ // If there are no matching work info, do nothing
+ if (workInfoList == null || workInfoList.isEmpty()) {
+ return;
+ }
+ Log.d(DEBUG_TAG, "WorkerInfo: "+workInfoList);
- @Override
- public void onDBStatusChanged(boolean updating) {
+ boolean showProgress = false;
+ for (WorkInfo workInfo : workInfoList) {
+ if (workInfo.getState() == WorkInfo.State.RUNNING) {
+ showProgress = true;
+ }
+ }
- if (updating) {
- createDefaultSnackbar();
- } else if (snackbar != null) {
- snackbar.dismiss();
- snackbar = null;
- }
+ if (showProgress) {
+ createDefaultSnackbar();
+ } else {
+ if(snackbar!=null) {
+ snackbar.dismiss();
+ snackbar = null;
+ }
+ }
+
+ });
- }
- };
- prefsManager = new DBStatusManager(getApplicationContext(), updatelistener);
- prefsManager.registerListener();
//locationHandler = new GPSLocationAdapter(getApplicationContext());
//--------- NEARBY STOPS--------//
@@ -297,7 +310,7 @@
cr.setCostAllowed(true);
cr.setPowerRequirement(Criteria.NO_REQUIREMENT);
//We want the nearby bus stops!
- handler.post(new NearbyStopsRequester());
+ theHandler.post(new NearbyStopsRequester());
//If there are no providers available, then, wait for them
@@ -314,7 +327,6 @@
* Log.d("ActivityMain", "onPostResume fired. Last successfully bus stop ID: " + fh.getLastSuccessfullySearchedBusStop());
* if (searchMode == SEARCH_BY_ID && fh.getLastSuccessfullySearchedBusStop() != null) {
* setBusStopSearchByIDEditText(fh.getLastSuccessfullySearchedBusStop().ID);
- * //new asyncWgetBusStopFromBusStopID(lastSuccessfullySearchedBusStop.ID, ArrivalFetchersRecursionHelper, lastSuccessfullySearchedBusStop);
* new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS,fh).execute();
* } else {
* //we have new activity or we don't have a new searched stop.
@@ -336,7 +348,6 @@
super.onPause();
fh.stopLastRequestIfNeeded();
fh.setBlockAllActivities(true);
- if (updatelistener != null && prefsManager != null) prefsManager.unregisterListener();
locmgr.removeUpdates(locListener);
}
@@ -344,14 +355,9 @@
protected void onResume() {
super.onResume();
fh.setBlockAllActivities(false);
- if (updatelistener != null && prefsManager != null) {
- prefsManager.registerListener();
- if (prefsManager.isDBUpdating(true)) {
- createDefaultSnackbar();
- }
- }
+ //TODO: check if current LiveData-bound observer works
if (pendingNearbyStopsRequest)
- handler.post(new NearbyStopsRequester());
+ theHandler.post(new NearbyStopsRequester());
}
@Override
@@ -386,8 +392,25 @@
startActivity(new Intent(ActivityMain.this, ActivityFavorites.class));
return true;
case R.id.action_map:
- startActivity(new Intent(ActivityMain.this, ActivityMap.class));
+ //ensure storage permission is granted
+ final String permission = Manifest.permission.WRITE_EXTERNAL_STORAGE;
+ int result = askForPermissionIfNeeded(permission, STORAGE_PERMISSION_REQ);
+ switch (result) {
+ case PERMISSION_OK:
+ startActivity(new Intent(ActivityMain.this, ActivityMap.class));
+ break;
+ case PERMISSION_ASKING:
+ permissionDoneRunnables.put(permission,
+ () -> startActivity(new Intent(ActivityMain.this, ActivityMap.class)));
+ break;
+ case PERMISSION_NEG_CANNOT_ASK:
+ Resources res = getResources();
+ String storage_perm = res.getString(R.string.storage_permission);
+ String text = res.getString(R.string.too_many_permission_asks, storage_perm);
+ Toast.makeText(getApplicationContext(),text, Toast.LENGTH_LONG).show();
+ }
return true;
+
case R.id.action_about:
startActivity(new Intent(ActivityMain.this, ActivityAbout.class));
return true;
@@ -418,20 +441,11 @@
public void onSearchClick(View v) {
if (searchMode == SEARCH_BY_ID) {
String busStopID = busStopSearchByIDEditText.getText().toString();
- //OLD ASYNCTASK
- //new asyncWgetBusStopFromBusStopID(busStopID, ArrivalFetchersRecursionHelper, lastSuccessfullySearchedBusStop);
-
- if (busStopID == null || busStopID.length() <= 0) {
- showMessage(R.string.insert_bus_stop_number_error);
- toggleSpinner(false);
- } else {
- new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS, fh).execute(busStopID);
- Log.d("MainActiv", "Started search for arrivals of stop " + busStopID);
- }
+ createFragmentForStop(busStopID);
} else { // searchMode == SEARCH_BY_NAME
String query = busStopSearchByNameEditText.getText().toString();
//new asyncWgetBusStopSuggestions(query, stopsDB, StopsFindersByNameRecursionHelper);
- new AsyncDataDownload(AsyncDataDownload.RequestType.STOPS, fh).execute(query);
+ new AsyncDataDownload(fh, stopsFinderByNames).execute(query);
}
}
@@ -447,7 +461,7 @@
//if we sent a request for a new NearbyStopsFragment
if (pendingNearbyStopsRequest) {
pendingNearbyStopsRequest = false;
- handler.post(new NearbyStopsRequester());
+ theHandler.post(new NearbyStopsRequester());
}
} else {
@@ -455,6 +469,31 @@
setOption(LOCATION_PERMISSION_GIVEN, false);
}
//add other cases for permissions
+ break;
+ case STORAGE_PERMISSION_REQ:
+ final String storageKey = Manifest.permission.WRITE_EXTERNAL_STORAGE;
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ Log.d(DEBUG_TAG, "Permissions check: " + Arrays.toString(permissions));
+
+ if (permissionDoneRunnables.containsKey(storageKey)) {
+ Runnable toRun = permissionDoneRunnables.get(storageKey);
+ if (toRun != null)
+ toRun.run();
+ permissionDoneRunnables.remove(storageKey);
+ }
+ } else {
+ //permission denied
+ showToastMessage(R.string.permission_storage_maps_msg, false);
+ /*final int canGetPermission = askForPermissionIfNeeded(Manifest.permission.ACCESS_FINE_LOCATION, STORAGE_PERMISSION_REQ);
+ switch (canGetPermission) {
+ case PERMISSION_ASKING:
+
+ break;
+ case PERMISSION_NEG_CANNOT_ASK:
+ permissionDoneRunnables.remove(storageKey);
+ showToastMessage(R.string.closing_act_crash_msg, false);
+ }*/
+ }
}
}
@@ -462,13 +501,22 @@
@Override
public void createFragmentForStop(String ID) {
- //new asyncWgetBusStopFromBusStopID(ID, ArrivalFetchersRecursionHelper,lastSuccessfullySearchedBusStop);
if (ID == null || ID.length() <= 0) {
// we're still in UI thread, no need to mess with Progress
- showMessage(R.string.insert_bus_stop_number_error);
+ showToastMessage(R.string.insert_bus_stop_number_error, true);
toggleSpinner(false);
- } else {
- new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS, fh).execute(ID);
+ } else if (framan.findFragmentById(R.id.resultFrame) instanceof ArrivalsFragment) {
+ ArrivalsFragment fragment = (ArrivalsFragment) framan.findFragmentById(R.id.resultFrame);
+ if (fragment.getStopID() != null && fragment.getStopID().equals(ID)){
+ // Run with previous fetchers
+ //fragment.getCurrentFetchers().toArray()
+ new AsyncDataDownload(fh,fragment.getCurrentFetchersAsArray()).execute(ID);
+ } else{
+ new AsyncDataDownload(fh, arrivalsFetchers).execute(ID);
+ }
+ }
+ else {
+ new AsyncDataDownload(fh,arrivalsFetchers).execute(ID);
Log.d("MainActiv", "Started search for arrivals of stop " + ID);
}
}
@@ -488,6 +536,7 @@
* Receive the Barcode Scanner Intent
*/
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+ super.onActivityResult(requestCode, resultCode, intent);
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
Uri uri;
@@ -535,7 +584,7 @@
Log.d(DEBUG_TAG, "Provider " + provider + " got enabled");
if (locmgr != null && pendingNearbyStopsRequest && locmgr.getProvider(provider).meetsCriteria(cr)) {
pendingNearbyStopsRequest = false;
- handler.post(new NearbyStopsRequester());
+ theHandler.post(new NearbyStopsRequester());
}
}
@@ -564,16 +613,27 @@
}
};
+ /**
+ * Run location requests separately and asynchronously
+ */
class NearbyStopsRequester implements Runnable {
- @SuppressLint("MissingPermission")
@Override
public void run() {
final boolean canRunPosition = Build.VERSION.SDK_INT < Build.VERSION_CODES.M || getOption(LOCATION_PERMISSION_GIVEN, false);
-
- if (!canRunPosition) {
- pendingNearbyStopsRequest = true;
- assertLocationPermissions();
- return;
+ final boolean noPermission = ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
+ ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED;
+
+ //if we don't have the permission, we have to ask for it, if we haven't
+ // asked too many times before
+ if (noPermission) {
+ if (!canRunPosition) {
+ pendingNearbyStopsRequest = true;
+ assertLocationPermissions();
+ Log.w(DEBUG_TAG, "Cannot get position: Asking permission, noPositionFromSys: " + noPermission);
+ return;
+ } else {
+ Toast.makeText(getApplicationContext(), "Asked for permission position too many times", Toast.LENGTH_LONG).show();
+ }
} else setOption(LOCATION_PERMISSION_GIVEN, true);
LocationManager locManager = (LocationManager) getSystemService(LOCATION_SERVICE);
@@ -581,7 +641,9 @@
Log.e(DEBUG_TAG, "location manager is nihil, cannot create NearbyStopsFragment");
return;
}
- if (anyLocationProviderMatchesCriteria(locManager, cr, true) && fh.getLastSuccessfullySearchedBusStop() == null) {
+ if (anyLocationProviderMatchesCriteria(locManager, cr, true)
+ && fh.getLastSuccessfullySearchedBusStop() == null
+ && !framan.isDestroyed()) {
//Go ahead with the request
Log.d("mainActivity", "Recreating stop fragment");
swipeRefreshLayout.setVisibility(View.VISIBLE);
@@ -598,6 +660,7 @@
//Wait for the providers
Log.d(DEBUG_TAG, "Queuing position request");
pendingNearbyStopsRequest = true;
+
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10, 0.1f, locListener);
}
@@ -726,18 +789,12 @@
}
////////////////////////////////////// GUI HELPERS /////////////////////////////////////////////
- @Override
public void showKeyboard() {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
View view = searchMode == SEARCH_BY_ID ? busStopSearchByIDEditText : busStopSearchByNameEditText;
imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
}
- @Override
- public void showMessage(int messageID) {
- Toast.makeText(getApplicationContext(), messageID, Toast.LENGTH_SHORT).show();
- }
-
private void setSearchModeBusStopID() {
searchMode = SEARCH_BY_ID;
busStopSearchByNameEditText.setVisibility(View.GONE);
diff --git a/src/it/reyboz/bustorino/ActivityMap.java b/src/it/reyboz/bustorino/ActivityMap.java
--- a/src/it/reyboz/bustorino/ActivityMap.java
+++ b/src/it/reyboz/bustorino/ActivityMap.java
@@ -19,8 +19,10 @@
package it.reyboz.bustorino;
+import android.Manifest;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Build;
@@ -28,12 +30,16 @@
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
-import android.support.annotation.RequiresApi;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.preference.PreferenceManager;
-import android.widget.Toast;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+import androidx.preference.PreferenceManager;
+
+import it.reyboz.bustorino.middleware.GeneralActivity;
import it.reyboz.bustorino.middleware.NextGenDB;
+
import org.osmdroid.api.IMapController;
import org.osmdroid.config.Configuration;
import org.osmdroid.events.DelayedMapListener;
@@ -55,9 +61,8 @@
import it.reyboz.bustorino.backend.Stop;
import it.reyboz.bustorino.map.CustomInfoWindow;
-import it.reyboz.bustorino.middleware.StopsDB;
-public class ActivityMap extends AppCompatActivity {
+public class ActivityMap extends GeneralActivity {
private static final String TAG = "Busto-MapActivity";
private static final String MAP_CURRENT_ZOOM_KEY = "map-current-zoom";
@@ -84,12 +89,15 @@
protected ImageButton btFollowMe;
@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
- @Override public void onCreate(Bundle savedInstanceState) {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//handle permissions first, before map is created. not depicted here
- //load/initialize the osmdroid configuration, this can be done
+ //load/initialize the osmdroid configuration
+
+
ctx = getApplicationContext();
Configuration.getInstance().load(ctx, PreferenceManager.getDefaultSharedPreferences(ctx));
//setting this before the layout is inflated is a good idea
@@ -138,7 +146,6 @@
}));
-
btCenterMap.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -165,12 +172,13 @@
}
+
public void startMap(Bundle incoming, Bundle savedInstanceState) {
//parse incoming bundle
GeoPoint marker = null;
String name = null;
String ID = null;
- if(incoming != null) {
+ if (incoming != null) {
double lat = incoming.getDouble(BUNDLE_LATIT);
double lon = incoming.getDouble(BUNDLE_LONGIT);
marker = new GeoPoint(lat, lon);
@@ -184,11 +192,17 @@
IMapController mapController = map.getController();
GeoPoint startPoint = null;
+ boolean havePositionPermission = true;
+
+ if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
+ askForPermissionIfNeeded(Manifest.permission.ACCESS_FINE_LOCATION, PERMISSION_REQUEST_POSITION);
+ havePositionPermission = false;
+ }
+
if (marker != null) {
startPoint = marker;
mapController.setZoom(POSITION_FOUND_ZOOM);
- }
- else if (savedInstanceState != null) {
+ } else if (savedInstanceState != null || !havePositionPermission) {
mapController.setZoom(savedInstanceState.getDouble(MAP_CURRENT_ZOOM_KEY));
mapController.setCenter(new GeoPoint(savedInstanceState.getDouble(MAP_CENTER_LAT_KEY),
savedInstanceState.getDouble(MAP_CENTER_LON_KEY)));
@@ -196,7 +210,8 @@
boolean found = false;
LocationManager locationManager =
(LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
- if(locationManager!=null) {
+ if (locationManager != null) {
+
Location userLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (userLocation != null) {
mapController.setZoom(POSITION_FOUND_ZOOM);
@@ -390,4 +405,25 @@
outState.putDouble(MAP_CENTER_LON_KEY, map.getMapCenter().getLongitude());
}
+ /**
+ * PERMISSION STUFF
+ **/
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ switch (requestCode) {
+ case PERMISSION_REQUEST_POSITION:
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ setOption(LOCATION_PERMISSION_GIVEN, true);
+ //if we sent a request for a new NearbyStopsFragment
+
+
+ } else {
+ //permission denied
+ setOption(LOCATION_PERMISSION_GIVEN, false);
+ }
+ break;
+ //add other cases for permissions
+ }
+
+ }
}
\ No newline at end of file
diff --git a/src/it/reyboz/bustorino/ActivitySettings.java b/src/it/reyboz/bustorino/ActivitySettings.java
--- a/src/it/reyboz/bustorino/ActivitySettings.java
+++ b/src/it/reyboz/bustorino/ActivitySettings.java
@@ -1,10 +1,10 @@
package it.reyboz.bustorino;
import android.os.Bundle;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentTransaction;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import it.reyboz.bustorino.fragments.SettingsFragment;
diff --git a/src/it/reyboz/bustorino/BustoApp.java b/src/it/reyboz/bustorino/BustoApp.java
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/BustoApp.java
@@ -0,0 +1,36 @@
+package it.reyboz.bustorino;
+
+import android.app.Application;
+import android.content.Context;
+
+import org.acra.ACRA;
+import org.acra.BuildConfig;
+import org.acra.annotation.AcraCore;
+import org.acra.annotation.AcraDialog;
+import org.acra.annotation.AcraMailSender;
+import org.acra.config.CoreConfigurationBuilder;
+import org.acra.config.DialogConfigurationBuilder;
+import org.acra.config.MailSenderConfigurationBuilder;
+import org.acra.data.StringFormat;
+
+
+public class BustoApp extends Application {
+
+ @Override
+ protected void attachBaseContext(Context base) {
+ super.attachBaseContext(base);
+
+ CoreConfigurationBuilder builder = new CoreConfigurationBuilder(this);
+ builder.setBuildConfigClass(BuildConfig.class).setReportFormat(StringFormat.JSON)
+ .setDeleteUnapprovedReportsOnApplicationStart(true);
+ builder.getPluginConfigurationBuilder(MailSenderConfigurationBuilder.class).setMailTo("gtt@succhia.cz")
+ .setReportFileName(it.reyboz.bustorino.BuildConfig.VERSION_NAME +"_report.json")
+ .setResBody(R.string.acra_email_message)
+ .setEnabled(true);
+ builder.getPluginConfigurationBuilder(DialogConfigurationBuilder.class).setResText(R.string.message_crash)
+ .setResTheme(R.style.AppTheme)
+ .setEnabled(true);
+
+ ACRA.init(this, builder);
+ }
+}
diff --git a/src/it/reyboz/bustorino/adapters/ArrivalsStopAdapter.java b/src/it/reyboz/bustorino/adapters/ArrivalsStopAdapter.java
--- a/src/it/reyboz/bustorino/adapters/ArrivalsStopAdapter.java
+++ b/src/it/reyboz/bustorino/adapters/ArrivalsStopAdapter.java
@@ -19,9 +19,9 @@
import android.content.Context;
import android.location.Location;
-import android.support.annotation.Nullable;
-import android.support.v4.util.Pair;
-import android.support.v7.widget.RecyclerView;
+import androidx.annotation.Nullable;
+import androidx.core.util.Pair;
+import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
diff --git a/src/it/reyboz/bustorino/adapters/PalinaAdapter.java b/src/it/reyboz/bustorino/adapters/PalinaAdapter.java
--- a/src/it/reyboz/bustorino/adapters/PalinaAdapter.java
+++ b/src/it/reyboz/bustorino/adapters/PalinaAdapter.java
@@ -18,7 +18,7 @@
package it.reyboz.bustorino.adapters;
import android.content.Context;
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
diff --git a/src/it/reyboz/bustorino/adapters/SquareStopAdapter.java b/src/it/reyboz/bustorino/adapters/SquareStopAdapter.java
--- a/src/it/reyboz/bustorino/adapters/SquareStopAdapter.java
+++ b/src/it/reyboz/bustorino/adapters/SquareStopAdapter.java
@@ -17,10 +17,9 @@
*/
package it.reyboz.bustorino.adapters;
-import android.content.Context;
import android.location.Location;
-import android.support.annotation.Nullable;
-import android.support.v7.widget.RecyclerView;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
diff --git a/src/it/reyboz/bustorino/adapters/StopAdapter.java b/src/it/reyboz/bustorino/adapters/StopAdapter.java
--- a/src/it/reyboz/bustorino/adapters/StopAdapter.java
+++ b/src/it/reyboz/bustorino/adapters/StopAdapter.java
@@ -18,7 +18,7 @@
package it.reyboz.bustorino.adapters;
import android.content.Context;
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
diff --git a/src/it/reyboz/bustorino/backend/ArrivalsFetcher.java b/src/it/reyboz/bustorino/backend/ArrivalsFetcher.java
--- a/src/it/reyboz/bustorino/backend/ArrivalsFetcher.java
+++ b/src/it/reyboz/bustorino/backend/ArrivalsFetcher.java
@@ -49,4 +49,10 @@
* @see FiveTNormalizer
*/
Palina ReadArrivalTimesAll(String stopID, AtomicReference<result> res);
+
+ /**
+ * Get the determined source for the Fetcher
+ * @return the source of the arrival times
+ */
+ Passaggio.Source getSourceForFetcher();
}
diff --git a/src/it/reyboz/bustorino/backend/DBStatusManager.java b/src/it/reyboz/bustorino/backend/DBStatusManager.java
--- a/src/it/reyboz/bustorino/backend/DBStatusManager.java
+++ b/src/it/reyboz/bustorino/backend/DBStatusManager.java
@@ -46,7 +46,7 @@
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Log.d("BUSTO-PrefListener", "Changed key " + key + " in the sharedPref");
- if (key.equals(DB_UPDATING)) {
+ if (dbUpdateListener!=null && key.equals(DB_UPDATING)) {
dbUpdateListener.onDBStatusChanged(sharedPreferences.getBoolean(DB_UPDATING, dbUpdateListener.defaultStatusValue()));
}
diff --git a/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java b/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java
--- a/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java
+++ b/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java
@@ -17,7 +17,7 @@
*/
package it.reyboz.bustorino.backend;
-import android.support.annotation.Nullable;
+import androidx.annotation.Nullable;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
@@ -27,8 +27,6 @@
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
@@ -68,6 +66,11 @@
return p;
}
+ @Override
+ public Passaggio.Source getSourceForFetcher() {
+ return Passaggio.Source.FiveTAPI;
+ }
+
List<Route> parseArrivalsServerResponse(String JSONresponse, AtomicReference<result> res) throws JSONException{
ArrayList<Route> routes = new ArrayList<>(3);
/*
diff --git a/src/it/reyboz/bustorino/backend/FiveTAPIVolleyRequest.java b/src/it/reyboz/bustorino/backend/FiveTAPIVolleyRequest.java
--- a/src/it/reyboz/bustorino/backend/FiveTAPIVolleyRequest.java
+++ b/src/it/reyboz/bustorino/backend/FiveTAPIVolleyRequest.java
@@ -18,14 +18,13 @@
package it.reyboz.bustorino.backend;
-import android.support.annotation.Nullable;
+import androidx.annotation.Nullable;
import android.util.Log;
import com.android.volley.*;
import com.android.volley.toolbox.HttpHeaderParser;
import org.json.JSONException;
import java.io.UnsupportedEncodingException;
-import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
diff --git a/src/it/reyboz/bustorino/backend/FiveTScraperFetcher.java b/src/it/reyboz/bustorino/backend/FiveTScraperFetcher.java
--- a/src/it/reyboz/bustorino/backend/FiveTScraperFetcher.java
+++ b/src/it/reyboz/bustorino/backend/FiveTScraperFetcher.java
@@ -159,7 +159,7 @@
// Yes... Sometimes there is an EMPTY td ._.
continue;
}
- p.addPassaggio(time, Passaggio.Source.FiveTScraper,routeIndex);
+ p.addPassaggio(time, Passaggio.Source.FiveTScraper, routeIndex);
}
}
@@ -168,6 +168,11 @@
return p;
}
+ @Override
+ public Passaggio.Source getSourceForFetcher() {
+ return Passaggio.Source.FiveTScraper;
+ }
+
// preserved for future generations:
// /*
// * I've sent many emails to the public email info@5t.torino.it to write down something like:
diff --git a/src/it/reyboz/bustorino/backend/GTTJSONFetcher.java b/src/it/reyboz/bustorino/backend/GTTJSONFetcher.java
--- a/src/it/reyboz/bustorino/backend/GTTJSONFetcher.java
+++ b/src/it/reyboz/bustorino/backend/GTTJSONFetcher.java
@@ -18,7 +18,7 @@
package it.reyboz.bustorino.backend;
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
import org.json.JSONArray;
import org.json.JSONException;
@@ -89,7 +89,11 @@
passaggi = thisroute.getJSONArray("PassaggiRT");
howManyPassaggi = passaggi.length();
for(j = 0; j < howManyPassaggi; j++) {
- p.addPassaggio(passaggi.getString(j).concat("*"), Passaggio.Source.GTTJSON, pos);
+ String mPassaggio = passaggi.getString(j);
+ if (mPassaggio.contains("__")){
+ mPassaggio = mPassaggio.replace("_", "");
+ }
+ p.addPassaggio(mPassaggio.concat("*"), Passaggio.Source.GTTJSON, pos);
}
passaggi = thisroute.getJSONArray("PassaggiPR"); // now the non-real-time ones
@@ -108,4 +112,9 @@
return p;
}
+ @Override
+ public Passaggio.Source getSourceForFetcher() {
+ return Passaggio.Source.GTTJSON;
+ }
+
}
diff --git a/src/it/reyboz/bustorino/backend/GTTStopsFetcher.java b/src/it/reyboz/bustorino/backend/GTTStopsFetcher.java
--- a/src/it/reyboz/bustorino/backend/GTTStopsFetcher.java
+++ b/src/it/reyboz/bustorino/backend/GTTStopsFetcher.java
@@ -18,7 +18,7 @@
package it.reyboz.bustorino.backend;
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
import org.json.JSONArray;
import org.json.JSONException;
diff --git a/src/it/reyboz/bustorino/backend/Notifications.java b/src/it/reyboz/bustorino/backend/Notifications.java
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/backend/Notifications.java
@@ -0,0 +1,46 @@
+package it.reyboz.bustorino.backend;
+
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.os.Build;
+import it.reyboz.bustorino.R;
+
+public class Notifications {
+ public static final String DEFAULT_CHANNEL_ID ="Default";
+
+ public static void createDefaultNotificationChannel(Context context) {
+ // Create the NotificationChannel, but only on API 26+ because
+ // the NotificationChannel class is new and not in the support library
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ CharSequence name = context.getString(R.string.default_notification_channel);
+ String description = context.getString(R.string.default_notification_channel_description);
+ int importance = NotificationManager.IMPORTANCE_DEFAULT;
+ NotificationChannel channel = new NotificationChannel(DEFAULT_CHANNEL_ID, name, importance);
+ channel.setDescription(description);
+ // Register the channel with the system; you can't change the importance
+ // or other notification behaviors after this
+ NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
+ notificationManager.createNotificationChannel(channel);
+ }
+ }
+
+ /**
+ * Register a notification channel on Android Oreo and above
+ * @param con a Context
+ * @param name channel name
+ * @param description channel description
+ * @param importance channel importance (from NotificationManager)
+ * @param ID channel ID
+ */
+ public static void createNotificationChannel(Context con, String name, String description, int importance, String ID){
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ NotificationChannel channel = new NotificationChannel(ID, name, importance);
+ channel.setDescription(description);
+ // Register the channel with the system; you can't change the importance
+ // or other notification behaviors after this
+ NotificationManager notificationManager = con.getSystemService(NotificationManager.class);
+ notificationManager.createNotificationChannel(channel);
+ }
+ }
+}
diff --git a/src/it/reyboz/bustorino/backend/Palina.java b/src/it/reyboz/bustorino/backend/Palina.java
--- a/src/it/reyboz/bustorino/backend/Palina.java
+++ b/src/it/reyboz/bustorino/backend/Palina.java
@@ -33,6 +33,8 @@
*/
public class Palina extends Stop {
private ArrayList<Route> routes = new ArrayList<>();
+ private boolean routesModified = false;
+ private Passaggio.Source allSource = null;
public Palina(String stopID) {
super(stopID);
@@ -52,6 +54,7 @@
*/
public void addPassaggio(String TimeGTT, Passaggio.Source src,int arrayIndex) {
this.routes.get(arrayIndex).addPassaggio(TimeGTT,src);
+ routesModified = true;
}
/**
@@ -76,11 +79,13 @@
* @return array index for this route
*/
public int addRoute(String routeID, String destinazione, Route.Type type) {
- this.routes.add(new Route(routeID, destinazione, type, new ArrayList<Passaggio>(6)));
+ this.routes.add(new Route(routeID, destinazione, type, new ArrayList<>(6)));
+ routesModified = true;
return this.routes.size() - 1; // last inserted element and pray that direct access to ArrayList elements really is direct
}
public int addRoute(Route r){
this.routes.add(r);
+ routesModified = true;
return this.routes.size()-1;
}
public void setRoutes(List<Route> routeList){
@@ -151,6 +156,35 @@
// public List<Passaggio> queryRouteByIndex(int index) {
// return this.routes.get(index).getPassaggi();
// }
+ protected void checkPassaggi(){
+ Passaggio.Source mSource = null;
+ for (Route r: routes){
+ for(Passaggio pass: r.passaggi){
+ if (mSource == null) {
+ mSource = pass.source;
+ } else if (mSource != pass.source){
+ Log.w("BusTO-CheckPassaggi",
+ "Cannot determine the source, have got "+mSource +" so far, the next one is "+pass.source );
+ mSource = Passaggio.Source.UNDETERMINED;
+
+ break;
+ }
+ }
+ if(mSource == Passaggio.Source.UNDETERMINED)
+ break;
+ }
+ //finished with the check, setting flags
+ routesModified = false;
+ allSource = mSource;
+ }
+
+ public Passaggio.Source getPassaggiSourceIfAny(){
+ if(allSource==null || routesModified){
+ checkPassaggi();
+ }
+ assert allSource != null;
+ return allSource;
+ }
/**
* Gets every route and its timetable.
@@ -234,8 +268,6 @@
return count;
}
-
-
// /**
// * Route with terminus (destinazione) and timetables (passaggi), internal implementation.
// *
diff --git a/src/it/reyboz/bustorino/backend/Passaggio.java b/src/it/reyboz/bustorino/backend/Passaggio.java
--- a/src/it/reyboz/bustorino/backend/Passaggio.java
+++ b/src/it/reyboz/bustorino/backend/Passaggio.java
@@ -18,7 +18,7 @@
package it.reyboz.bustorino.backend;
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
import android.util.Log;
public final class Passaggio implements Comparable<Passaggio> {
@@ -29,7 +29,7 @@
private final String passaggioGTT;
public final int hh,mm;
public final boolean isInRealTime;
- public final Source passageSource;
+ public final Source source;
/**
@@ -55,7 +55,7 @@
*/
public Passaggio(@NonNull String TimeGTT, @NonNull Source sorgente) {
passaggioGTT = TimeGTT;
- passageSource = sorgente;
+ source = sorgente;
String[] parts = TimeGTT.split(":");
String hh,mm;
boolean realtime;
@@ -95,7 +95,7 @@
this.hh = hour;
this.mm = minutes;
this.isInRealTime = realtime;
- this.passageSource = sorgente;
+ this.source = sorgente;
//Build the passaggio string
StringBuilder sb = new StringBuilder();
sb.append(hour).append(":").append(minutes);
@@ -154,6 +154,6 @@
// }
// }
public enum Source{
- FiveTAPI,GTTJSON,FiveTScraper
+ FiveTAPI,GTTJSON,FiveTScraper, UNDETERMINED
}
}
\ No newline at end of file
diff --git a/src/it/reyboz/bustorino/backend/Route.java b/src/it/reyboz/bustorino/backend/Route.java
--- a/src/it/reyboz/bustorino/backend/Route.java
+++ b/src/it/reyboz/bustorino/backend/Route.java
@@ -18,8 +18,8 @@
package it.reyboz.bustorino.backend;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.Calendar;
diff --git a/src/it/reyboz/bustorino/backend/Stop.java b/src/it/reyboz/bustorino/backend/Stop.java
--- a/src/it/reyboz/bustorino/backend/Stop.java
+++ b/src/it/reyboz/bustorino/backend/Stop.java
@@ -19,9 +19,9 @@
package it.reyboz.bustorino.backend;
import android.location.Location;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.util.Log;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import it.reyboz.bustorino.util.LinesNameSorter;
import java.net.URLEncoder;
diff --git a/src/it/reyboz/bustorino/backend/StopsDBInterface.java b/src/it/reyboz/bustorino/backend/StopsDBInterface.java
--- a/src/it/reyboz/bustorino/backend/StopsDBInterface.java
+++ b/src/it/reyboz/bustorino/backend/StopsDBInterface.java
@@ -18,8 +18,8 @@
package it.reyboz.bustorino.backend;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import java.util.List;
diff --git a/src/it/reyboz/bustorino/backend/networkTools.java b/src/it/reyboz/bustorino/backend/networkTools.java
--- a/src/it/reyboz/bustorino/backend/networkTools.java
+++ b/src/it/reyboz/bustorino/backend/networkTools.java
@@ -18,7 +18,7 @@
package it.reyboz.bustorino.backend;
-import android.support.annotation.Nullable;
+import androidx.annotation.Nullable;
import android.util.Log;
import java.io.BufferedInputStream;
diff --git a/src/it/reyboz/bustorino/backend/utils.java b/src/it/reyboz/bustorino/backend/utils.java
--- a/src/it/reyboz/bustorino/backend/utils.java
+++ b/src/it/reyboz/bustorino/backend/utils.java
@@ -1,7 +1,6 @@
package it.reyboz.bustorino.backend;
import android.content.Context;
-import android.support.v7.widget.RecyclerView;
import android.view.View;
public abstract class utils {
diff --git a/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java b/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java
--- a/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java
+++ b/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java
@@ -21,16 +21,40 @@
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v4.app.LoaderManager;
-import android.support.v4.content.CursorLoader;
-import android.support.v4.content.Loader;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.NonNull;
+import androidx.loader.app.LoaderManager;
+import androidx.loader.content.CursorLoader;
+import androidx.loader.content.Loader;
+
import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
import android.widget.ImageButton;
+import android.widget.ListAdapter;
+import android.widget.ListView;
import android.widget.TextView;
+import android.widget.Toast;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
import it.reyboz.bustorino.R;
+import it.reyboz.bustorino.adapters.PalinaAdapter;
+import it.reyboz.bustorino.backend.ArrivalsFetcher;
import it.reyboz.bustorino.backend.DBStatusManager;
+import it.reyboz.bustorino.backend.Fetcher;
+import it.reyboz.bustorino.backend.FiveTAPIFetcher;
+import it.reyboz.bustorino.backend.FiveTNormalizer;
+import it.reyboz.bustorino.backend.FiveTScraperFetcher;
+import it.reyboz.bustorino.backend.GTTJSONFetcher;
+import it.reyboz.bustorino.backend.Palina;
+import it.reyboz.bustorino.backend.Passaggio;
+import it.reyboz.bustorino.backend.Route;
import it.reyboz.bustorino.middleware.AppDataProvider;
import it.reyboz.bustorino.middleware.NextGenDB;
import it.reyboz.bustorino.middleware.UserDB;
@@ -42,27 +66,37 @@
private final static String DEBUG_TAG = "BUSTOArrivalsFragment";
private final static int loaderFavId = 2;
private final static int loaderStopId = 1;
+ private final static ArrivalsFetcher[] defaultFetchers = new ArrivalsFetcher[]{new FiveTAPIFetcher(), new GTTJSONFetcher(), new FiveTScraperFetcher()};
+ static final String STOP_TITLE = "messageExtra";
+
private @Nullable String stopID,stopName;
- private TextView messageTextView;
private DBStatusManager prefs;
private DBStatusManager.OnDBUpdateStatusChangeListener listener;
private boolean justCreated = false;
- private ImageButton addToFavorites;
+ private Palina lastUpdatedPalina = null;
+ private boolean needUpdateOnAttach = false;
+ private boolean requestedNewArrivalTimes = false;
+
+ //Views
+ protected ImageButton addToFavorites;
+ protected TextView timesSourceTextView;
+
+ private List<ArrivalsFetcher> fetchers = new ArrayList<>(Arrays.asList(defaultFetchers));
public static ArrivalsFragment newInstance(String stopID){
+ return newInstance(stopID, null);
+ }
+
+ public static ArrivalsFragment newInstance(@NonNull String stopID, @Nullable String stopName){
+ ArrivalsFragment fragment = new ArrivalsFragment();
Bundle args = new Bundle();
args.putString(KEY_STOP_ID,stopID);
- ArrivalsFragment fragment = new ArrivalsFragment();
//parameter for ResultListFragment
args.putSerializable(LIST_TYPE,FragmentKind.ARRIVALS);
- fragment.setArguments(args);
- return fragment;
- }
- public static ArrivalsFragment newInstance(String stopID,String stopName){
- ArrivalsFragment fragment = newInstance(stopID);
- Bundle args = fragment.getArguments();
- args.putString(KEY_STOP_NAME,stopName);
+ if (stopName != null){
+ args.putString(KEY_STOP_NAME,stopName);
+ }
fragment.setArguments(args);
return fragment;
}
@@ -73,12 +107,12 @@
stopID = getArguments().getString(KEY_STOP_ID);
//this might really be null
stopName = getArguments().getString(KEY_STOP_NAME);
- final ArrivalsFragment f = this;
+ final ArrivalsFragment arrivalsFragment = this;
listener = new DBStatusManager.OnDBUpdateStatusChangeListener() {
@Override
public void onDBStatusChanged(boolean updating) {
if(!updating){
- getLoaderManager().restartLoader(loaderFavId,getArguments(),f);
+ getLoaderManager().restartLoader(loaderFavId,getArguments(),arrivalsFragment);
} else {
final LoaderManager lm = getLoaderManager();
lm.destroyLoader(loaderFavId);
@@ -96,6 +130,65 @@
}
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View root = inflater.inflate(R.layout.fragment_arrivals, container, false);
+ messageTextView = (TextView) root.findViewById(R.id.messageTextView);
+ addToFavorites = (ImageButton) root.findViewById(R.id.addToFavorites);
+ resultsListView = (ListView) root.findViewById(R.id.resultsListView);
+ timesSourceTextView = (TextView) root.findViewById(R.id.timesSourceTextView);
+ timesSourceTextView.setOnLongClickListener(view -> {
+ if(!requestedNewArrivalTimes){
+ rotateFetchers();
+ timesSourceTextView.setText(R.string.arrival_source_changing);
+ mListener.createFragmentForStop(stopID);
+ requestedNewArrivalTimes = true;
+ return true;
+ }
+ return false;
+ });
+ timesSourceTextView.setOnClickListener(view -> {
+ Toast.makeText(getContext(), R.string.change_arrivals_source_message, Toast.LENGTH_SHORT)
+ .show();
+ });
+ //Button
+ addToFavorites.setClickable(true);
+ addToFavorites.setOnClickListener(v -> {
+ // add/remove the stop in the favorites
+ mListener.toggleLastStopToFavorites();
+ });
+
+ resultsListView.setOnItemClickListener((parent, view, position, id) -> {
+ String routeName;
+
+ Route r = (Route) parent.getItemAtPosition(position);
+ routeName = FiveTNormalizer.routeInternalToDisplay(r.getNameForDisplay());
+ if (routeName == null) {
+ routeName = r.getNameForDisplay();
+ }
+ if (r.destinazione == null || r.destinazione.length() == 0) {
+ Toast.makeText(getContext(),
+ getString(R.string.route_towards_unknown, routeName), Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(getContext(),
+ getString(R.string.route_towards_destination, routeName, r.destinazione), Toast.LENGTH_SHORT).show();
+ }
+ });
+ String displayName = getArguments().getString(STOP_TITLE);
+ setTextViewMessage(String.format(
+ getString(R.string.passages), displayName));
+
+
+ String probablemessage = getArguments().getString(MESSAGE_TEXT_VIEW);
+ if (probablemessage != null) {
+ //Log.d("BusTO fragment " + this.getTag(), "We have a possible message here in the savedInstaceState: " + probablemessage);
+ messageTextView.setText(probablemessage);
+ messageTextView.setVisibility(View.VISIBLE);
+ }
+ return root;
+ }
+
@Override
public void onResume() {
super.onResume();
@@ -116,11 +209,98 @@
}
}
+ @Override
+ public void onStart() {
+ super.onStart();
+ if (needUpdateOnAttach){
+ updateFragmentData(null);
+ }
+ }
+
@Nullable
public String getStopID() {
return stopID;
}
+ /**
+ * Give the fetchers
+ * @return the list of the fetchers
+ */
+ public ArrayList<Fetcher> getCurrentFetchers(){
+ ArrayList<Fetcher> v = new ArrayList<Fetcher>();
+ for (ArrivalsFetcher fetcher: fetchers){
+ v.add(fetcher);
+ }
+ return v;
+ }
+ public Fetcher[] getCurrentFetchersAsArray(){
+ Fetcher[] arr = new Fetcher[fetchers.size()];
+ fetchers.toArray(arr);
+ return arr;
+ }
+
+ private void rotateFetchers(){
+ Collections.rotate(fetchers, -1);
+ }
+
+
+ /**
+ * Update the UI with the new data
+ * @param p the full Palina
+ */
+ public void updateFragmentData(@Nullable Palina p){
+ if (p!=null)
+ lastUpdatedPalina = p;
+
+ if (!isAdded()){
+ //defer update at next show
+ if (p==null)
+ Log.w(DEBUG_TAG, "Asked to update the data, but we're not attached and the data is null");
+ else needUpdateOnAttach = true;
+ } else {
+
+ final PalinaAdapter adapter = new PalinaAdapter(getContext(), lastUpdatedPalina);
+ showArrivalsSources(lastUpdatedPalina);
+ super.resetListAdapter(adapter);
+ }
+ }
+
+ /**
+ * Set the message of the arrival times source
+ * @param p Palina with the arrival times
+ */
+ protected void showArrivalsSources(Palina p){
+ final Passaggio.Source source = p.getPassaggiSourceIfAny();
+
+ String source_txt;
+ switch (source){
+ case GTTJSON:
+ source_txt = getString(R.string.gttjsonfetcher);
+ break;
+ case FiveTAPI:
+ source_txt = getString(R.string.fivetapifetcher);
+ break;
+ case FiveTScraper:
+ source_txt = getString(R.string.fivetscraper);
+ break;
+ case UNDETERMINED:
+ //Don't show the view
+ timesSourceTextView.setVisibility(View.GONE);
+ return;
+ default:
+ throw new IllegalStateException("Unexpected value: " + source);
+ }
+ final String base_message = getString(R.string.times_source_fmt, source_txt);
+ timesSourceTextView.setVisibility(View.VISIBLE);
+ timesSourceTextView.setText(base_message);
+ requestedNewArrivalTimes = false;
+ }
+
+ @Override
+ public void setNewListAdapter(ListAdapter adapter) {
+ throw new UnsupportedOperationException();
+ }
+
/**
* Update the message in the fragment
*
diff --git a/src/it/reyboz/bustorino/fragments/CommonScrollListener.java b/src/it/reyboz/bustorino/fragments/CommonScrollListener.java
--- a/src/it/reyboz/bustorino/fragments/CommonScrollListener.java
+++ b/src/it/reyboz/bustorino/fragments/CommonScrollListener.java
@@ -17,7 +17,7 @@
*/
package it.reyboz.bustorino.fragments;
-import android.support.v7.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.widget.AbsListView;
diff --git a/src/it/reyboz/bustorino/fragments/FragmentHelper.java b/src/it/reyboz/bustorino/fragments/FragmentHelper.java
--- a/src/it/reyboz/bustorino/fragments/FragmentHelper.java
+++ b/src/it/reyboz/bustorino/fragments/FragmentHelper.java
@@ -21,10 +21,10 @@
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.sqlite.SQLiteException;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentTransaction;
-import android.support.v4.widget.SwipeRefreshLayout;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import android.util.Log;
import it.reyboz.bustorino.R;
import it.reyboz.bustorino.adapters.PalinaAdapter;
@@ -65,7 +65,7 @@
/**
* Get the last successfully searched bus stop or NULL
*
- * @return
+ * @return the stop
*/
public Stop getLastSuccessfullySearchedBusStop() {
return lastSuccessfullySearchedBusStop;
@@ -92,7 +92,6 @@
return;
}
- SwipeRefreshLayout srl = (SwipeRefreshLayout) act.findViewById(swipeRefID);
FragmentManager fm = act.getSupportFragmentManager();
if(fm.findFragmentById(R.id.resultFrame) instanceof ArrivalsFragment) {
@@ -118,8 +117,9 @@
Log.d("BusTO", "Same bus stop, accessing existing fragment");
arrivalsFragment = (ArrivalsFragment) fm.findFragmentById(R.id.resultFrame);
}
+ // DO NOT CALL `setListAdapter` ever on arrivals fragment
+ arrivalsFragment.updateFragmentData(p);
- arrivalsFragment.setListAdapter(new PalinaAdapter(act.getApplicationContext(),p));
act.hideKeyboard();
toggleSpinner(false);
}
@@ -206,25 +206,30 @@
case OK:
break;
case CLIENT_OFFLINE:
- act.showMessage(R.string.network_error);
+ act.showToastMessage(R.string.network_error, true);
break;
case SERVER_ERROR:
if (act.isConnected()) {
- act.showMessage(R.string.parsing_error);
+ act.showToastMessage(R.string.parsing_error, true);
} else {
- act.showMessage(R.string.network_error);
+ act.showToastMessage(R.string.network_error, true);
}
case PARSER_ERROR:
default:
- act.showMessage(R.string.internal_error);
+ showShortToast(R.string.internal_error);
break;
case QUERY_TOO_SHORT:
- act.showMessage(R.string.query_too_short);
+ showShortToast(R.string.query_too_short);
break;
case EMPTY_RESULT_SET:
- act.showMessage(R.string.no_bus_stop_have_this_name);
+ showShortToast(R.string.no_bus_stop_have_this_name);
break;
}
}
+ public void showShortToast(int message){
+ if (act!=null)
+ act.showToastMessage(message,true);
+ }
+
}
diff --git a/src/it/reyboz/bustorino/fragments/NearbyStopsFragment.java b/src/it/reyboz/bustorino/fragments/NearbyStopsFragment.java
--- a/src/it/reyboz/bustorino/fragments/NearbyStopsFragment.java
+++ b/src/it/reyboz/bustorino/fragments/NearbyStopsFragment.java
@@ -24,16 +24,16 @@
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.LoaderManager;
-import android.support.v4.content.CursorLoader;
-import android.support.v4.content.Loader;
-import android.support.v4.util.Pair;
-import android.support.v7.preference.PreferenceManager;
-import android.support.v7.widget.AppCompatButton;
-import android.support.v7.widget.GridLayoutManager;
-import android.support.v7.widget.RecyclerView;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.loader.app.LoaderManager;
+import androidx.loader.content.CursorLoader;
+import androidx.loader.content.Loader;
+import androidx.core.util.Pair;
+import androidx.preference.PreferenceManager;
+import androidx.appcompat.widget.AppCompatButton;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -574,7 +574,7 @@
getLoaderManager().restartLoader(LOADER_ID,msgBundle,callbacks);
}
lastUpdateTime = System.currentTimeMillis();
- Log.d("BusTO: NearbyLocationListener","can start loader "+ canStartDBQuery);
+ Log.d("BusTO:NearPositListen","can start loader "+ canStartDBQuery);
}
@Override
diff --git a/src/it/reyboz/bustorino/fragments/ResultListFragment.java b/src/it/reyboz/bustorino/fragments/ResultListFragment.java
--- a/src/it/reyboz/bustorino/fragments/ResultListFragment.java
+++ b/src/it/reyboz/bustorino/fragments/ResultListFragment.java
@@ -23,16 +23,16 @@
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.os.Parcelable;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
-import android.support.v4.widget.SwipeRefreshLayout;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
-import android.support.design.widget.FloatingActionButton;
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
import it.reyboz.bustorino.R;
import it.reyboz.bustorino.backend.FiveTNormalizer;
@@ -49,20 +49,19 @@
public class ResultListFragment extends Fragment{
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
static final String LIST_TYPE = "list-type";
- private static final String STOP_TITLE = "messageExtra";
protected static final String LIST_STATE = "list_state";
- private static final String MESSAGE_TEXT_VIEW = "message_text_view";
+ protected static final String MESSAGE_TEXT_VIEW = "message_text_view";
private FragmentKind adapterKind;
private boolean adapterSet = false;
protected FragmentListener mListener;
- private TextView messageTextView;
- private ImageButton addToFavorites;
+ protected TextView messageTextView;
+ protected ListView resultsListView;
+
private FloatingActionButton fabutton;
- private ListView resultsListView;
private ListAdapter mListAdapter = null;
boolean listShown;
private Parcelable mListInstanceState = null;
@@ -87,7 +86,7 @@
Bundle args = new Bundle();
args.putSerializable(LIST_TYPE, listType);
if (eventualStopTitle != null) {
- args.putString(STOP_TITLE, eventualStopTitle);
+ args.putString(ArrivalsFragment.STOP_TITLE, eventualStopTitle);
}
fragment.setArguments(args);
return fragment;
@@ -107,7 +106,7 @@
/**
* Check if the last Bus Stop is in the favorites
- * @return
+ * @return true if it iss
*/
public boolean isStopInFavorites(String busStopId) {
boolean found = false;
@@ -126,7 +125,6 @@
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_list_view, container, false);
messageTextView = (TextView) root.findViewById(R.id.messageTextView);
- addToFavorites = (ImageButton) root.findViewById(R.id.addToFavorites);
if (adapterKind != null) {
resultsListView = (ListView) root.findViewById(R.id.resultsListView);
switch (adapterKind) {
@@ -167,7 +165,7 @@
}
}
});
- String displayName = getArguments().getString(STOP_TITLE);
+ String displayName = getArguments().getString(ArrivalsFragment.STOP_TITLE);
setTextViewMessage(String.format(
getString(R.string.passages), displayName));
break;
@@ -204,7 +202,7 @@
ListAdapter adapter = mListAdapter;
mListAdapter = null;
- setListAdapter(adapter);
+ resetListAdapter(adapter);
}
if (mListInstanceState != null) {
Log.d("resultsListView", "trying to restore instance state");
@@ -277,7 +275,7 @@
}
}
- public void setListAdapter(ListAdapter adapter) {
+ protected void resetListAdapter(ListAdapter adapter) {
boolean hadAdapter = mListAdapter != null;
mListAdapter = adapter;
if (resultsListView != null) {
@@ -285,6 +283,9 @@
resultsListView.setVisibility(View.VISIBLE);
}
}
+ public void setNewListAdapter(ListAdapter adapter){
+ resetListAdapter(adapter);
+ }
/**
* Set the message textView
@@ -292,23 +293,6 @@
*/
public void setTextViewMessage(String message) {
messageTextView.setText(message);
- switch (adapterKind) {
- case ARRIVALS:
- addToFavorites.setClickable(true);
- addToFavorites.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // add/remove the stop in the favorites
- mListener.toggleLastStopToFavorites();
- }
- });
- break;
- case STOPS:
- addToFavorites.setClickable(false);
- addToFavorites.setVisibility(View.INVISIBLE);
- break;
- }
-
messageTextView.setVisibility(View.VISIBLE);
}
}
\ No newline at end of file
diff --git a/src/it/reyboz/bustorino/fragments/SettingsFragment.java b/src/it/reyboz/bustorino/fragments/SettingsFragment.java
--- a/src/it/reyboz/bustorino/fragments/SettingsFragment.java
+++ b/src/it/reyboz/bustorino/fragments/SettingsFragment.java
@@ -3,8 +3,8 @@
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceFragmentCompat;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragmentCompat;
import it.reyboz.bustorino.R;
public class SettingsFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener {
diff --git a/src/it/reyboz/bustorino/fragments/StopListFragment.java b/src/it/reyboz/bustorino/fragments/StopListFragment.java
--- a/src/it/reyboz/bustorino/fragments/StopListFragment.java
+++ b/src/it/reyboz/bustorino/fragments/StopListFragment.java
@@ -20,9 +20,9 @@
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
-import android.support.v4.app.LoaderManager;
-import android.support.v4.content.CursorLoader;
-import android.support.v4.content.Loader;
+import androidx.loader.app.LoaderManager;
+import androidx.loader.content.CursorLoader;
+import androidx.loader.content.Loader;
import android.util.Log;
import it.reyboz.bustorino.backend.Route;
import it.reyboz.bustorino.backend.Stop;
@@ -70,7 +70,7 @@
LoaderManager loaderManager = getLoaderManager();
if(stopList!=null) {
mListAdapter = new StopAdapter(getContext(),stopList);
- setListAdapter(mListAdapter);
+ resetListAdapter(mListAdapter);
for (int i = 0; i < stopList.size(); i++) {
final Bundle b = new Bundle();
b.putString(KEY_STOP_ID, stopList.get(i).ID);
diff --git a/src/it/reyboz/bustorino/middleware/AsyncDataDownload.java b/src/it/reyboz/bustorino/middleware/AsyncDataDownload.java
--- a/src/it/reyboz/bustorino/middleware/AsyncDataDownload.java
+++ b/src/it/reyboz/bustorino/middleware/AsyncDataDownload.java
@@ -20,12 +20,12 @@
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.SQLException;
-import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.AsyncTask;
-import android.support.v7.app.AppCompatActivity;
+
+import androidx.annotation.NonNull;
import android.util.Log;
-import it.reyboz.bustorino.R;
+
import it.reyboz.bustorino.backend.*;
import it.reyboz.bustorino.fragments.FragmentHelper;
import it.reyboz.bustorino.middleware.NextGenDB.Contract.*;
@@ -44,36 +44,40 @@
private static final String TAG = "BusTO-DataDownload";
private boolean failedAll = false;
- private AtomicReference<Fetcher.result> res;
- private RequestType t;
+ private final AtomicReference<Fetcher.result> res;
+ private final RequestType t;
private String query;
WeakReference<FragmentHelper> helperRef;
- private ArrayList<Thread> otherActivities = new ArrayList<>();
+ private final ArrayList<Thread> otherActivities = new ArrayList<>();
+ private final Fetcher[] theFetchers;
- public AsyncDataDownload(RequestType type,FragmentHelper fh) {
- t = type;
+ public AsyncDataDownload(FragmentHelper fh, @NonNull Fetcher[] fetchers) {
+ RequestType type;
helperRef = new WeakReference<>(fh);
- fh.setLastTaskRef(new WeakReference<AsyncDataDownload>(this));
+ fh.setLastTaskRef(new WeakReference<>(this));
res = new AtomicReference<>();
+
+ theFetchers = fetchers;
+ if (theFetchers.length < 1){
+ throw new IllegalArgumentException("You have to put at least one Fetcher, idiot!");
+ }
+ if (theFetchers[0] instanceof ArrivalsFetcher){
+ type = RequestType.ARRIVALS;
+ } else if (theFetchers[0] instanceof StopsFinderByName){
+ type = RequestType.STOPS;
+ } else{
+ type = null;
+ }
+ t = type;
+
}
@Override
protected Object doInBackground(String... params) {
- RecursionHelper r;
+ RecursionHelper<Fetcher> r = new RecursionHelper<>(theFetchers);
boolean success=false;
Object result;
- switch (t){
- case ARRIVALS:
- r = new RecursionHelper<>(new ArrivalsFetcher[] {new FiveTAPIFetcher(),new GTTJSONFetcher(), new FiveTScraperFetcher()});
- break;
- case STOPS:
- r = new RecursionHelper<>(new StopsFinderByName[] {new GTTStopsFetcher(), new FiveTStopsFetcher()});
- break;
- default:
- //TODO put error message
- return null;
- }
FragmentHelper fh = helperRef.get();
//If the FragmentHelper is null, that means the activity doesn't exist anymore
if (fh == null){
@@ -229,10 +233,10 @@
}
public class BranchInserter implements Runnable{
- private List<Route> routesToInsert;
+ private final List<Route> routesToInsert;
private String stopID;
- private FragmentHelper fragmentHelper;
+ private final FragmentHelper fragmentHelper;
public BranchInserter(List<Route> routesToInsert,FragmentHelper fh,String stopID) {
this.routesToInsert = routesToInsert;
diff --git a/src/it/reyboz/bustorino/middleware/DBUpdateWorker.java b/src/it/reyboz/bustorino/middleware/DBUpdateWorker.java
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/middleware/DBUpdateWorker.java
@@ -0,0 +1,139 @@
+package it.reyboz.bustorino.middleware;
+
+import android.annotation.SuppressLint;
+import android.app.Notification;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.util.Log;
+import androidx.annotation.NonNull;
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.NotificationManagerCompat;
+import androidx.work.*;
+import it.reyboz.bustorino.R;
+import it.reyboz.bustorino.backend.Fetcher;
+import it.reyboz.bustorino.backend.Notifications;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static android.content.Context.MODE_PRIVATE;
+
+public class DBUpdateWorker extends Worker{
+
+
+ public static final String ERROR_CODE_KEY ="Error_Code";
+ public static final String ERROR_REASON_KEY = "ERROR_REASON";
+ public static final int ERROR_FETCHING_VERSION = 4;
+ public static final int ERROR_DOWNLOADING_STOPS = 5;
+ public static final int ERROR_DOWNLOADING_LINES = 6;
+
+ public static final String SUCCESS_REASON_KEY = "SUCCESS_REASON";
+ public static final int SUCCESS_NO_ACTION_NEEDED = 9;
+ public static final int SUCCESS_UPDATE_DONE = 1;
+
+ private final int notifi_ID=62341;
+
+ public static final String FORCED_UPDATE = "FORCED-UPDATE";
+
+ public static final String DEBUG_TAG = "Busto-UpdateWorker";
+
+
+ public DBUpdateWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
+ super(context, workerParams);
+ }
+
+ @SuppressLint("RestrictedApi")
+ @NonNull
+ @Override
+ public Result doWork() {
+ //register Notification channel
+ final Context con = getApplicationContext();
+ Notifications.createDefaultNotificationChannel(con);
+ final SharedPreferences shPr = con.getSharedPreferences(con.getString(R.string.mainSharedPreferences),MODE_PRIVATE);
+ final int current_DB_version = shPr.getInt(DatabaseUpdate.DB_VERSION_KEY,-10);
+
+ final int new_DB_version = DatabaseUpdate.getNewVersion();
+
+ final boolean isUpdateCompulsory = getInputData().getBoolean(FORCED_UPDATE,false);
+
+ final int notificationID = showNotification();
+ Log.d(DEBUG_TAG, "Have previous version: "+current_DB_version +" and new version "+new_DB_version);
+ Log.d(DEBUG_TAG, "Update compulsory: "+isUpdateCompulsory);
+ if (new_DB_version < 0){
+ //there has been an error
+ final Data out = new Data.Builder().putInt(ERROR_REASON_KEY, ERROR_FETCHING_VERSION)
+ .putInt(ERROR_CODE_KEY,new_DB_version).build();
+ cancelNotification(notificationID);
+ return Result.failure(out);
+ }
+
+ //we got a good version
+ if (current_DB_version >= new_DB_version && !isUpdateCompulsory) {
+ //don't need to update
+ cancelNotification(notificationID);
+ return Result.success(new Data.Builder().
+ putInt(SUCCESS_REASON_KEY, SUCCESS_NO_ACTION_NEEDED).build());
+ }
+ //start the real update
+ AtomicReference<Fetcher.result> resultAtomicReference = new AtomicReference<>();
+ DatabaseUpdate.setDBUpdatingFlag(con, shPr,true);
+ final DatabaseUpdate.Result resultUpdate = DatabaseUpdate.performDBUpdate(con,resultAtomicReference);
+ DatabaseUpdate.setDBUpdatingFlag(con, shPr,false);
+
+ if (resultUpdate != DatabaseUpdate.Result.DONE){
+ Fetcher.result result = resultAtomicReference.get();
+
+ final Data.Builder dataBuilder = new Data.Builder();
+ switch (resultUpdate){
+ case ERROR_STOPS_DOWNLOAD:
+ dataBuilder.put(ERROR_REASON_KEY, ERROR_DOWNLOADING_STOPS);
+ break;
+ case ERROR_LINES_DOWNLOAD:
+ dataBuilder.put(ERROR_REASON_KEY, ERROR_DOWNLOADING_LINES);
+ break;
+ }
+ cancelNotification(notificationID);
+ return Result.failure(dataBuilder.build());
+ }
+ Log.d(DEBUG_TAG, "Update finished successfully!");
+ //update the version in the shared preference
+ final SharedPreferences.Editor editor = shPr.edit();
+ editor.putInt(DatabaseUpdate.DB_VERSION_KEY, new_DB_version);
+ editor.apply();
+ cancelNotification(notificationID);
+
+ return Result.success(new Data.Builder().putInt(SUCCESS_REASON_KEY, SUCCESS_UPDATE_DONE).build());
+ }
+
+ public static Constraints getWorkConstraints(){
+ return new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED)
+ .setRequiresCharging(false).build();
+ }
+
+ public static WorkRequest newFirstTimeWorkRequest(){
+ return new OneTimeWorkRequest.Builder(DBUpdateWorker.class)
+ .setBackoffCriteria(BackoffPolicy.LINEAR, 15, TimeUnit.SECONDS)
+ //.setInputData(new Data.Builder().putBoolean())
+ .build();
+ }
+
+
+ private int showNotification(){
+ final NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), Notifications.DEFAULT_CHANNEL_ID)
+ .setContentTitle("Libre BusTO - Updating Database")
+ .setProgress(0,0,true)
+ .setPriority(NotificationCompat.PRIORITY_LOW);
+ builder.setSmallIcon(R.drawable.ic_bus_orange);
+ final NotificationManagerCompat notifcManager = NotificationManagerCompat.from(getApplicationContext());
+ final int notification_ID = 32198;
+ notifcManager.notify(notification_ID,builder.build());
+
+ return notification_ID;
+ }
+
+ private void cancelNotification(int notificationID){
+ final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getApplicationContext());
+
+ notificationManager.cancel(notificationID);
+ }
+}
diff --git a/src/it/reyboz/bustorino/middleware/DatabaseUpdate.java b/src/it/reyboz/bustorino/middleware/DatabaseUpdate.java
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/middleware/DatabaseUpdate.java
@@ -0,0 +1,158 @@
+package it.reyboz.bustorino.middleware;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.database.sqlite.SQLiteDatabase;
+import android.util.Log;
+import it.reyboz.bustorino.R;
+import it.reyboz.bustorino.backend.Fetcher;
+import it.reyboz.bustorino.backend.FiveTAPIFetcher;
+import it.reyboz.bustorino.backend.Route;
+import it.reyboz.bustorino.backend.Stop;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static android.content.Context.MODE_PRIVATE;
+
+
+public class DatabaseUpdate {
+
+ public static final String DEBUG_TAG = "BusTO-DBUpdate";
+ public static final int VERSION_UNAVAILABLE = -2;
+ public static final int JSON_PARSING_ERROR = -4;
+
+ public static final String DB_VERSION_KEY = "NextGenDB.GTTVersion";
+
+ enum Result {
+ DONE, ERROR_STOPS_DOWNLOAD, ERROR_LINES_DOWNLOAD
+ }
+
+ /**
+ * Request the server the version of the database
+ * @return the version of the DB, or an error code
+ */
+ public static int getNewVersion(){
+ AtomicReference<Fetcher.result> gres = new AtomicReference<>();
+ String networkRequest = FiveTAPIFetcher.performAPIRequest(FiveTAPIFetcher.QueryType.STOPS_VERSION,null,gres);
+ if(networkRequest == null){
+ return VERSION_UNAVAILABLE;
+ }
+
+ try {
+ JSONObject resp = new JSONObject(networkRequest);
+ return resp.getInt("id");
+ } catch (JSONException e) {
+ e.printStackTrace();
+ Log.e(DEBUG_TAG,"Error: wrong JSON response\nResponse:\t"+networkRequest);
+ return JSON_PARSING_ERROR;
+ }
+ }
+ /**
+ * Run the DB Update
+ * @param con a context
+ * @param gres a result reference
+ * @return result of the update
+ */
+ public static Result performDBUpdate(Context con, AtomicReference<Fetcher.result> gres) {
+
+ final FiveTAPIFetcher f = new FiveTAPIFetcher();
+ final ArrayList<Stop> stops = f.getAllStopsFromGTT(gres);
+ //final ArrayList<ContentProviderOperation> cpOp = new ArrayList<>();
+
+ if (gres.get() != Fetcher.result.OK) {
+ Log.w(DEBUG_TAG, "Something went wrong downloading");
+ return Result.ERROR_STOPS_DOWNLOAD;
+
+ }
+ // return false; //If the commit to the SharedPreferences didn't succeed, simply stop updating the database
+ final NextGenDB dbHelp = new NextGenDB(con.getApplicationContext());
+ final SQLiteDatabase db = dbHelp.getWritableDatabase();
+ //Empty the needed tables
+ db.beginTransaction();
+ //db.execSQL("DELETE FROM "+StopsTable.TABLE_NAME);
+ //db.delete(LinesTable.TABLE_NAME,null,null);
+
+ //put new data
+ long startTime = System.currentTimeMillis();
+
+ Log.d(DEBUG_TAG, "Inserting " + stops.size() + " stops");
+ for (final Stop s : stops) {
+ final ContentValues cv = new ContentValues();
+
+ cv.put(NextGenDB.Contract.StopsTable.COL_ID, s.ID);
+ cv.put(NextGenDB.Contract.StopsTable.COL_NAME, s.getStopDefaultName());
+ if (s.location != null)
+ cv.put(NextGenDB.Contract.StopsTable.COL_LOCATION, s.location);
+ cv.put(NextGenDB.Contract.StopsTable.COL_LAT, s.getLatitude());
+ cv.put(NextGenDB.Contract.StopsTable.COL_LONG, s.getLongitude());
+ if (s.getAbsurdGTTPlaceName() != null) cv.put(NextGenDB.Contract.StopsTable.COL_PLACE, s.getAbsurdGTTPlaceName());
+ cv.put(NextGenDB.Contract.StopsTable.COL_LINES_STOPPING, s.routesThatStopHereToString());
+ if (s.type != null) cv.put(NextGenDB.Contract.StopsTable.COL_TYPE, s.type.getCode());
+
+ //Log.d(DEBUG_TAG,cv.toString());
+ //cpOp.add(ContentProviderOperation.newInsert(uritobeused).withValues(cv).build());
+ //valuesArr[i] = cv;
+ db.replace(NextGenDB.Contract.StopsTable.TABLE_NAME, null, cv);
+
+ }
+ db.setTransactionSuccessful();
+ db.endTransaction();
+ long endTime = System.currentTimeMillis();
+ Log.d(DEBUG_TAG, "Inserting stops took: " + ((double) (endTime - startTime) / 1000) + " s");
+
+ final ArrayList<Route> routes = f.getAllLinesFromGTT(gres);
+
+ if (routes == null) {
+ Log.w(DEBUG_TAG, "Something went wrong downloading the lines");
+ dbHelp.close();
+ return Result.ERROR_LINES_DOWNLOAD;
+
+ }
+
+ db.beginTransaction();
+ startTime = System.currentTimeMillis();
+ for (Route r : routes) {
+ final ContentValues cv = new ContentValues();
+ cv.put(NextGenDB.Contract.LinesTable.COLUMN_NAME, r.getName());
+ switch (r.type) {
+ case BUS:
+ cv.put(NextGenDB.Contract.LinesTable.COLUMN_TYPE, "URBANO");
+ break;
+ case RAILWAY:
+ cv.put(NextGenDB.Contract.LinesTable.COLUMN_TYPE, "FERROVIA");
+ break;
+ case LONG_DISTANCE_BUS:
+ cv.put(NextGenDB.Contract.LinesTable.COLUMN_TYPE, "EXTRA");
+ break;
+ }
+ cv.put(NextGenDB.Contract.LinesTable.COLUMN_DESCRIPTION, r.description);
+
+ //db.insert(LinesTable.TABLE_NAME,null,cv);
+ int rows = db.update(NextGenDB.Contract.LinesTable.TABLE_NAME, cv, NextGenDB.Contract.LinesTable.COLUMN_NAME + " = ?", new String[]{r.getName()});
+ if (rows < 1) { //we haven't changed anything
+ db.insert(NextGenDB.Contract.LinesTable.TABLE_NAME, null, cv);
+ }
+ }
+ db.setTransactionSuccessful();
+ db.endTransaction();
+ endTime = System.currentTimeMillis();
+ Log.d(DEBUG_TAG, "Inserting lines took: " + ((double) (endTime - startTime) / 1000) + " s");
+ dbHelp.close();
+
+ return Result.DONE;
+ }
+
+ public static boolean setDBUpdatingFlag(Context con, boolean value){
+ final SharedPreferences shPr = con.getSharedPreferences(con.getString(R.string.mainSharedPreferences),MODE_PRIVATE);
+ return setDBUpdatingFlag(con, shPr, value);
+ }
+ static boolean setDBUpdatingFlag(Context con, SharedPreferences shPr,boolean value){
+ final SharedPreferences.Editor editor = shPr.edit();
+ editor.putBoolean(con.getString(R.string.databaseUpdatingPref),value);
+ return editor.commit();
+ }
+}
diff --git a/src/it/reyboz/bustorino/middleware/DatabaseUpdateService.java b/src/it/reyboz/bustorino/middleware/DatabaseUpdateService.java
--- a/src/it/reyboz/bustorino/middleware/DatabaseUpdateService.java
+++ b/src/it/reyboz/bustorino/middleware/DatabaseUpdateService.java
@@ -19,24 +19,17 @@
import android.app.IntentService;
import android.content.*;
-import android.database.sqlite.SQLiteDatabase;
-import android.support.annotation.Nullable;
+import androidx.annotation.Nullable;
import android.util.Log;
-import it.reyboz.bustorino.ActivityMain;
+
import it.reyboz.bustorino.R;
import it.reyboz.bustorino.backend.Fetcher;
import it.reyboz.bustorino.backend.FiveTAPIFetcher;
-import it.reyboz.bustorino.backend.Route;
-import it.reyboz.bustorino.backend.Stop;
import org.json.JSONException;
import org.json.JSONObject;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicReference;
-import static it.reyboz.bustorino.middleware.NextGenDB.Contract.*;
-
/**
* An {@link IntentService} subclass for handling asynchronous task requests in
* a service on a separate handler thread.
@@ -126,6 +119,10 @@
}
private boolean performDBUpdate(AtomicReference<Fetcher.result> gres){
+ if(!setDBUpdatingFlag(true))
+ return false;
+
+ /*
final FiveTAPIFetcher f = new FiveTAPIFetcher();
final ArrayList<Stop> stops = f.getAllStopsFromGTT(gres);
//final ArrayList<ContentProviderOperation> cpOp = new ArrayList<>();
@@ -212,6 +209,9 @@
Log.d(DEBUG_TAG,"Inserting lines took: "+((double) (endTime-startTime)/1000)+" s");
dbHelp.close();
return true;
+
+ */
+ return DatabaseUpdate.performDBUpdate(getApplication(),gres) == DatabaseUpdate.Result.DONE;
}
private int getNewVersion(UpdateRequestParams params){
AtomicReference<Fetcher.result> gres = new AtomicReference<>();
@@ -252,7 +252,7 @@
}
}
- /**
+ /*
* Probably useless
*
* Spoiler: IT IS
diff --git a/src/it/reyboz/bustorino/middleware/GeneralActivity.java b/src/it/reyboz/bustorino/middleware/GeneralActivity.java
--- a/src/it/reyboz/bustorino/middleware/GeneralActivity.java
+++ b/src/it/reyboz/bustorino/middleware/GeneralActivity.java
@@ -4,21 +4,42 @@
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
-import android.support.design.widget.Snackbar;
-import android.support.v4.app.ActivityCompat;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.app.AppCompatActivity;
+import com.google.android.material.snackbar.Snackbar;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
+import android.widget.Toast;
+
+import java.util.HashMap;
+
import it.reyboz.bustorino.R;
/**
* Activity class that contains all the generally useful methods
*/
public abstract class GeneralActivity extends AppCompatActivity {
- final protected int PERMISSION_REQUEST_POSITION = 33;
+ final static protected int PERMISSION_REQUEST_POSITION = 33;
+ final static protected String LOCATION_PERMISSION_GIVEN = "loc_permission";
+ final static protected int STORAGE_PERMISSION_REQ = 291;
+
+ final static protected int PERMISSION_OK = 0;
+ final static protected int PERMISSION_ASKING = 11;
+ final static protected int PERMISSION_NEG_CANNOT_ASK = -3;
+
+ final static private String DEBUG_TAG = "BusTO-GeneralAct";
+
+ /*
+ * Permission stuff
+ */
+ protected HashMap<String,Runnable> permissionDoneRunnables = new HashMap<>();
+ protected HashMap<String,Integer> permissionAsked = new HashMap<>();
protected void setOption(String optionName, boolean value) {
SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();
@@ -30,6 +51,10 @@
SharedPreferences preferences = getPreferences(MODE_PRIVATE);
return preferences.getBoolean(optionName, optDefault);
}
+
+ protected SharedPreferences getMainSharedPreferences(){
+ return getSharedPreferences(getString(R.string.mainSharedPreferences),MODE_PRIVATE);
+ }
public void hideKeyboard() {
View view = getCurrentFocus();
if (view != null) {
@@ -43,17 +68,56 @@
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return networkInfo != null && networkInfo.isConnected();
}
- public abstract void showMessage(int messageID);
- public abstract void showKeyboard();
+
+ public void showToastMessage(int messageID, boolean short_lenght) {
+ final int length = short_lenght ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG;
+ Toast.makeText(getApplicationContext(), messageID, length).show();
+ }
public void assertLocationPermissions() {
if(ContextCompat.checkSelfPermission(getApplicationContext(),Manifest.permission.ACCESS_FINE_LOCATION)!=PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_REQUEST_POSITION);
}
}
+
+ public int askForPermissionIfNeeded(String permission, int requestID){
+
+ if(ContextCompat.checkSelfPermission(getApplicationContext(),permission)==PackageManager.PERMISSION_GRANTED){
+ return PERMISSION_OK;
+ }
+ //need to ask for the permission
+ //consider scenario when we have already asked for permission
+ boolean alreadyAsked = false;
+ Integer num_trials = 0;
+ synchronized (this){
+ if (permissionAsked.containsKey(permission)){
+ num_trials = permissionAsked.get(permission);
+ if (num_trials != null && num_trials > 3)
+ alreadyAsked = true;
+
+ }
+ }
+ Log.d(DEBUG_TAG,"Already asked for permission: "+permission+" -> "+num_trials);
+
+ if(!alreadyAsked){
+ ActivityCompat.requestPermissions(this,new String[]{permission}, requestID);
+ synchronized (this){
+ if (num_trials!=null){
+ permissionAsked.put(permission, num_trials+1);
+ }
+ }
+ return PERMISSION_ASKING;
+ } else {
+
+ return PERMISSION_NEG_CANNOT_ASK;
+ }
+
+ }
+
public void createSnackbar(int ViewID, String message,int duration){
Snackbar.make(findViewById(ViewID),message,duration);
}
+
/*
METHOD THAT MIGHT BE USEFUL LATER
public void assertPermissions(String[] permissions){
diff --git a/src/it/reyboz/bustorino/middleware/NextGenDB.java b/src/it/reyboz/bustorino/middleware/NextGenDB.java
--- a/src/it/reyboz/bustorino/middleware/NextGenDB.java
+++ b/src/it/reyboz/bustorino/middleware/NextGenDB.java
@@ -19,21 +19,24 @@
import android.content.ContentValues;
import android.content.Context;
-import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteConstraintException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;
-import android.support.annotation.Nullable;
+import androidx.annotation.Nullable;
import android.util.Log;
-import it.reyboz.bustorino.R;
+
+import it.reyboz.bustorino.backend.Fetcher;
+import it.reyboz.bustorino.backend.FiveTAPIFetcher;
import it.reyboz.bustorino.backend.Route;
import it.reyboz.bustorino.backend.Stop;
+import org.json.JSONException;
+import org.json.JSONObject;
import java.util.*;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
import static it.reyboz.bustorino.middleware.NextGenDB.Contract.*;
@@ -95,22 +98,6 @@
appContext = context.getApplicationContext();
}
- /**
- * Lazy initialization singleton getter, thread-safe with double checked locking
- * from https://en.wikipedia.org/wiki/Singleton_pattern
- * @return the instance
- */
- /*
- public static NextGenDB getInstance(Context context){
- if(instance==null){
- synchronized (NextGenDB.class){
- if(instance==null){
- instance = new NextGenDB(context);
- }
- }
- }
- return instance;
- }*/
@Override
public void onCreate(SQLiteDatabase db) {
@@ -364,5 +351,4 @@
super(message);
}
}
-
}
diff --git a/src/it/reyboz/bustorino/middleware/StopsDB.java b/src/it/reyboz/bustorino/middleware/StopsDB.java
--- a/src/it/reyboz/bustorino/middleware/StopsDB.java
+++ b/src/it/reyboz/bustorino/middleware/StopsDB.java
@@ -22,8 +22,8 @@
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.readystatesoftware.sqliteasset.SQLiteAssetHelper;
diff --git a/src/it/reyboz/bustorino/util/RoutePositionSorter.java b/src/it/reyboz/bustorino/util/RoutePositionSorter.java
--- a/src/it/reyboz/bustorino/util/RoutePositionSorter.java
+++ b/src/it/reyboz/bustorino/util/RoutePositionSorter.java
@@ -18,9 +18,9 @@
package it.reyboz.bustorino.util;
import android.location.Location;
-import android.support.v4.util.Pair;
+import androidx.core.util.Pair;
import android.util.Log;
-import it.reyboz.bustorino.adapters.ArrivalsStopAdapter;
+
import it.reyboz.bustorino.backend.Passaggio;
import it.reyboz.bustorino.backend.Route;
import it.reyboz.bustorino.backend.Stop;

File Metadata

Mime Type
text/plain
Expires
Fri, Oct 18, 07:10 (38 m, 7 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
634452
Default Alt Text
D45.1729228210.diff (126 KB)

Event Timeline