From 796a9e81a3fdab5d8cfa2c99a5c0d55b51ad9077 Mon Sep 17 00:00:00 2001 From: Bertware Date: Sat, 24 Jun 2017 22:52:10 +0200 Subject: [PATCH 1/7] Keep proguard line numbers for unambiguous stacktraces --- Hyperrail/build.gradle | 9 ++++++--- Hyperrail/proguard-rules.pro | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Hyperrail/build.gradle b/Hyperrail/build.gradle index 2d2cb61d..109dea4d 100644 --- a/Hyperrail/build.gradle +++ b/Hyperrail/build.gradle @@ -6,6 +6,10 @@ apply plugin: 'com.android.application' apply plugin: 'com.google.firebase.firebase-perf' +apply plugin: 'com.google.firebase.firebase-crash' + +def VERSION_CODE = 4 +def VERSION_NAME = '0.9.2' android { signingConfigs { @@ -24,8 +28,8 @@ android { applicationId "be.hyperrail.android" minSdkVersion 19 targetSdkVersion 25 - versionCode 3 - versionName '0.9.2' + versionCode VERSION_CODE + versionName VERSION_NAME testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" multiDexEnabled true } @@ -63,5 +67,4 @@ dependencies { testCompile 'junit:junit:4.12' } - apply plugin: 'com.google.gms.google-services' \ No newline at end of file diff --git a/Hyperrail/proguard-rules.pro b/Hyperrail/proguard-rules.pro index 0081dc19..3583512f 100644 --- a/Hyperrail/proguard-rules.pro +++ b/Hyperrail/proguard-rules.pro @@ -15,3 +15,4 @@ #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} +-keepattributes SourceFile,LineNumberTable \ No newline at end of file From 1a81d60f5eb605bbd0598940e035c13ce9cc4dc6 Mon Sep 17 00:00:00 2001 From: Bertware Date: Sat, 24 Jun 2017 23:18:48 +0200 Subject: [PATCH 2/7] Improve stability of station search, improve logging --- .../android/irail/db/StationsDb.java | 12 +++++++ .../persistence/PersistentQueryProvider.java | 33 ++++++++++++++----- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/Hyperrail/src/main/java/be/hyperrail/android/irail/db/StationsDb.java b/Hyperrail/src/main/java/be/hyperrail/android/irail/db/StationsDb.java index 4a1abd94..b3625875 100644 --- a/Hyperrail/src/main/java/be/hyperrail/android/irail/db/StationsDb.java +++ b/Hyperrail/src/main/java/be/hyperrail/android/irail/db/StationsDb.java @@ -333,6 +333,12 @@ public int compare(Station o1, Station o2) { */ @Override public String[] getStationNames(Station[] Stations) { + + if (Stations == null ||Stations.length == 0){ + FirebaseCrash.logcat(WARNING.intValue(),LOGTAG,"Tried to load station names on empty station list!"); + return new String[0]; + } + String[] results = new String[Stations.length]; for (int i = 0; i < Stations.length; i++) { results[i] = Stations[i].getLocalizedName(); @@ -450,6 +456,12 @@ public Station getStationByName(String name) { */ private Station[] loadStationCursor(Cursor c) { if (c.isClosed()) { + FirebaseCrash.logcat(SEVERE.intValue(),LOGTAG,"Tried to load closed cursor"); + return null; + } + + if (c.getCount() == 0){ + FirebaseCrash.logcat(SEVERE.intValue(),LOGTAG,"Tried to load cursor with 0 results!"); return null; } diff --git a/Hyperrail/src/main/java/be/hyperrail/android/persistence/PersistentQueryProvider.java b/Hyperrail/src/main/java/be/hyperrail/android/persistence/PersistentQueryProvider.java index b51b5a35..f247adfc 100644 --- a/Hyperrail/src/main/java/be/hyperrail/android/persistence/PersistentQueryProvider.java +++ b/Hyperrail/src/main/java/be/hyperrail/android/persistence/PersistentQueryProvider.java @@ -17,6 +17,8 @@ import android.preference.PreferenceManager; import android.util.Log; +import com.google.firebase.crash.FirebaseCrash; + import org.json.JSONException; import org.json.JSONObject; @@ -30,6 +32,7 @@ import java.util.List; import java.util.Objects; import java.util.Set; +import java.util.logging.Level; import be.hyperrail.android.irail.contracts.IrailStationProvider; import be.hyperrail.android.irail.db.Station; @@ -91,7 +94,7 @@ public PersistentQueryProvider(Context context) { if (sharedPreferences.getBoolean("migrated1.9.1", false)) { for (String tag : new String[]{TAG_FAV_ROUTES, TAG_FAV_STATIONS, TAG_RECENT_ROUTES, TAG_RECENT_STATIONS}) { - Log.d("PersistentMigration","Tag " + tag ); + Log.d("PersistentMigration", "Tag " + tag); Set oldValue = context.getSharedPreferences(PREFERENCES_NAME, 0).getStringSet(tag, new HashSet()); ArrayList newValue = new ArrayList<>(); @@ -101,16 +104,16 @@ public PersistentQueryProvider(Context context) { JSONObject object = new JSONObject(entry); Station from = stationProvider.getStationByName(object.getString("from")); Station to; - if (! object.getString("to").equals("")) { + if (!object.getString("to").equals("")) { to = stationProvider.getStationByName(object.getString("to")); } else { to = null; } - Log.d("PersistentMigration","FROM " + object.getString("from") + " - " + from.getId()); + Log.d("PersistentMigration", "FROM " + object.getString("from") + " - " + from.getId()); if (to != null) { Log.d("PersistentMigration", "TO " + object.getString("to") + " - " + to.getId()); } else { - Log.d("PersistentMigration","TO " + object.getString("to") + " - NULL"); + Log.d("PersistentMigration", "TO " + object.getString("to") + " - NULL"); } RouteQuery query = new RouteQuery(from, to); newValue.add(query); @@ -121,8 +124,8 @@ public PersistentQueryProvider(Context context) { clear(tag); - for (RouteQuery q: newValue){ - store(tag,q); + for (RouteQuery q : newValue) { + store(tag, q); } } sharedPreferences.edit().putBoolean("migrated1.9.1", true).apply(); @@ -489,6 +492,11 @@ private ArrayList load(String tag, int limit, RouteQuery.RouteQueryT * @return List or routeQueries */ private ArrayList load(String tag, int limit, boolean timeSensitive, RouteQuery.RouteQueryType type) { + + if (limit <= 0) { + return new ArrayList<>(0); + } + SharedPreferences settings = context.getSharedPreferences(PREFERENCES_NAME, 0); Set items = settings.getStringSet(tag, null); @@ -591,16 +599,25 @@ private ArrayList setToList(Set set, RouteQuery.RouteQueryTy for (String entry : set) { try { JSONObject object = new JSONObject(entry); + Station from = stationProvider.getStationById(object.getString("from")); Station to = null; - if (! object.getString("to").equals("")) { + + if (!object.getString("to").equals("")) { to = stationProvider.getStationById(object.getString("to")); } + RouteQuery query = new RouteQuery(from, to); query.created_at = new Date(object.getLong("created_at")); query.type = type; + + if (from == null) { + FirebaseCrash.logcat(Level.SEVERE.intValue(), "PersistentQuery", "Loaded invalid routeQuery: " + object.getString("from") + " could not be decoded! Type is " + type.toString()); + } + results.add(query); } catch (JSONException exception) { + FirebaseCrash.logcat(Level.WARNING.intValue(), "PersistentQuery", "Failed to load routequery for type " + type.toString() + ": " + exception.getMessage()); // ignored } } @@ -649,7 +666,7 @@ private Collection removeFromCollection(Collection colle Set toBeRemoved = new HashSet<>(); for (RouteQuery entry : collection) { for (RouteQuery removalEntry : remove) { - if (entry.from.getId().equals(removalEntry.from.getId()) && ((entry.to != null && removalEntry.to != null && entry.to.getId().equals(removalEntry.to.getId()))||(entry.to == null && removalEntry.to == null))) { + if (entry.from.getId().equals(removalEntry.from.getId()) && ((entry.to != null && removalEntry.to != null && entry.to.getId().equals(removalEntry.to.getId())) || (entry.to == null && removalEntry.to == null))) { toBeRemoved.add(entry); } } From 3111b1a885e23cc8d8209bb269e3cb04856e663f Mon Sep 17 00:00:00 2001 From: Bertware Date: Sun, 25 Jun 2017 11:12:59 +0200 Subject: [PATCH 3/7] Feedback and github link, fixed #28 --- Hyperrail/build.gradle | 2 +- .../hyperrail/android/FeedbackFragment.java | 65 ++++++++++++++++++ .../be/hyperrail/android/MainActivity.java | 8 +++ .../res/drawable-hdpi/ic_action_github.png | Bin 0 -> 730 bytes .../main/res/drawable-hdpi/ic_feedback.png | Bin 0 -> 180 bytes .../res/drawable-mdpi/ic_action_github.png | Bin 0 -> 490 bytes .../main/res/drawable-mdpi/ic_feedback.png | Bin 0 -> 140 bytes .../res/drawable-xhdpi/ic_action_github.png | Bin 0 -> 962 bytes .../main/res/drawable-xhdpi/ic_feedback.png | Bin 0 -> 161 bytes .../res/drawable-xxhdpi/ic_action_github.png | Bin 0 -> 1495 bytes .../main/res/drawable-xxhdpi/ic_feedback.png | Bin 0 -> 261 bytes .../res/drawable-xxxhdpi/ic_action_github.png | Bin 0 -> 4263 bytes .../main/res/drawable-xxxhdpi/ic_feedback.png | Bin 0 -> 288 bytes .../src/main/res/layout/activity_main.xml | 40 +++++------ .../src/main/res/layout/fragment_feedback.xml | 29 ++++++++ Hyperrail/src/main/res/menu/drawer_main.xml | 11 ++- Hyperrail/src/main/res/values-fr/strings.xml | 4 ++ .../res/values-fr/strings_preferences.xml | 2 + Hyperrail/src/main/res/values-nl/strings.xml | 4 ++ .../res/values-nl/strings_preferences.xml | 3 +- Hyperrail/src/main/res/values/strings.xml | 5 ++ .../main/res/values/strings_preferences.xml | 2 + Hyperrail/src/main/res/xml/pref_general.xml | 33 ++++++--- 23 files changed, 173 insertions(+), 35 deletions(-) create mode 100644 Hyperrail/src/main/java/be/hyperrail/android/FeedbackFragment.java create mode 100644 Hyperrail/src/main/res/drawable-hdpi/ic_action_github.png create mode 100644 Hyperrail/src/main/res/drawable-hdpi/ic_feedback.png create mode 100644 Hyperrail/src/main/res/drawable-mdpi/ic_action_github.png create mode 100644 Hyperrail/src/main/res/drawable-mdpi/ic_feedback.png create mode 100644 Hyperrail/src/main/res/drawable-xhdpi/ic_action_github.png create mode 100644 Hyperrail/src/main/res/drawable-xhdpi/ic_feedback.png create mode 100644 Hyperrail/src/main/res/drawable-xxhdpi/ic_action_github.png create mode 100644 Hyperrail/src/main/res/drawable-xxhdpi/ic_feedback.png create mode 100644 Hyperrail/src/main/res/drawable-xxxhdpi/ic_action_github.png create mode 100644 Hyperrail/src/main/res/drawable-xxxhdpi/ic_feedback.png create mode 100644 Hyperrail/src/main/res/layout/fragment_feedback.xml diff --git a/Hyperrail/build.gradle b/Hyperrail/build.gradle index 109dea4d..2fe827c0 100644 --- a/Hyperrail/build.gradle +++ b/Hyperrail/build.gradle @@ -54,12 +54,12 @@ dependencies { androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) + compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.android.support:support-v4:25.3.1' compile 'com.android.support:cardview-v7:25.3.1' compile 'com.android.support:recyclerview-v7:25.3.1' compile 'com.android.support:design:25.3.1' - compile 'com.google.android.gms:play-services-location:10.2.6' compile 'com.google.firebase:firebase-crash:10.2.6' compile 'com.google.firebase:firebase-perf:10.2.6' diff --git a/Hyperrail/src/main/java/be/hyperrail/android/FeedbackFragment.java b/Hyperrail/src/main/java/be/hyperrail/android/FeedbackFragment.java new file mode 100644 index 00000000..ec893ae6 --- /dev/null +++ b/Hyperrail/src/main/java/be/hyperrail/android/FeedbackFragment.java @@ -0,0 +1,65 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package be.hyperrail.android; + +import android.app.Fragment; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +/** + * A simple {@link Fragment} subclass. + */ +public class FeedbackFragment extends Fragment { + + public FeedbackFragment() { + // Required empty public constructor + } + + public static FeedbackFragment newInstance() { + return new FeedbackFragment(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + return inflater.inflate(R.layout.fragment_feedback, container, false); + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + view.findViewById(R.id.button_send).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Context context = FeedbackFragment.this.getActivity(); + String version = "unknown"; + + try { + PackageInfo pInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); + version = pInfo.versionName; + } catch (Exception e) { + // Ignored + } + + Intent feedbackEmail = new Intent(Intent.ACTION_SEND); + + feedbackEmail.setType("text/email"); + feedbackEmail.putExtra(Intent.EXTRA_EMAIL, new String[]{"feedback@hyperrail.be"}); + feedbackEmail.putExtra(Intent.EXTRA_SUBJECT, "Feedback for hyperrail " + version); + startActivity(Intent.createChooser(feedbackEmail, "Send feedback mail:")); + } + }); + } +} diff --git a/Hyperrail/src/main/java/be/hyperrail/android/MainActivity.java b/Hyperrail/src/main/java/be/hyperrail/android/MainActivity.java index f3112989..db9ed9c7 100644 --- a/Hyperrail/src/main/java/be/hyperrail/android/MainActivity.java +++ b/Hyperrail/src/main/java/be/hyperrail/android/MainActivity.java @@ -51,6 +51,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On private static final int VIEW_TYPE_ROUTE = 1; private static final int VIEW_TYPE_DISTURBANCE = 2; private static final int VIEW_TYPE_SETTINGS = 3; + private static final int VIEW_TYPE_FEEDBACK = 4; private boolean mDualPane = false; @@ -178,6 +179,10 @@ private void setView(int i, Bundle args) { frg = DisturbanceListFragment.newInstance(); setSubTitle(R.string.title_disturbances); break; + case VIEW_TYPE_FEEDBACK: + frg = FeedbackFragment.newInstance(); + setSubTitle(R.string.title_feedback); + break; } if (args != null){ frg.setArguments(args); @@ -221,6 +226,9 @@ public boolean onNavigationItemSelected(@NonNull MenuItem item) { Intent i = new Intent(this, SettingsActivity.class); startActivity(i); break; + case R.id.action_feedback: + setView(VIEW_TYPE_FEEDBACK,null); + break; } if (!mDualPane) { vDrawerLayout.closeDrawers(); diff --git a/Hyperrail/src/main/res/drawable-hdpi/ic_action_github.png b/Hyperrail/src/main/res/drawable-hdpi/ic_action_github.png new file mode 100644 index 0000000000000000000000000000000000000000..bc9331c45d31dde46a60175efb4487d081dd626a GIT binary patch literal 730 zcmV<00ww*4P)4=N=gwz1i?0y3(-xW1uY^$ zs0Q1pg^){WB|%001y0dVo1WhbCwe^Ix$n)p=Z*>Y!e{e%@0|O2bKkw^-bs0$m)gvv zoPZN>0!~0jn%EQqSTIWf2~BdB21efkH^KKLQ;thg>U23*{9esM z)@34aL?iGUvt<8 literal 0 HcmV?d00001 diff --git a/Hyperrail/src/main/res/drawable-hdpi/ic_feedback.png b/Hyperrail/src/main/res/drawable-hdpi/ic_feedback.png new file mode 100644 index 0000000000000000000000000000000000000000..2b832f5b7a19b531da92cbfe5a3d9f17b3dc0a14 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^(jd&i0wmS%+S~(D)t)YnAr-fh6BbziIR9z?v;Xt{ zvvVBU>ri@zBiHnQC;L^7+-i>t+r$^XW#GKU_uzUNvqn{ONiL_u$CkuZy=N2@jhW2; zqM;p literal 0 HcmV?d00001 diff --git a/Hyperrail/src/main/res/drawable-mdpi/ic_action_github.png b/Hyperrail/src/main/res/drawable-mdpi/ic_action_github.png new file mode 100644 index 0000000000000000000000000000000000000000..5fc2d0e94f364bfa2de2f4f24f01fad572da14b9 GIT binary patch literal 490 zcmVYagZP)y7@2Y=vo|fP%;X-R-uEsIOw2D z6a;Y)s$%i{7H&A6O>#dPMd-n2>b-ZLyyV_pEykGjmso9q|197DkK_D?fDL>Qf{6Vb z5&zBSb6YClf(nx#6&_5 zHhJeK!f)eX6U>4!Fbbx?G8hu(MdX{XRRnzUWP2K0?3(28RRls3e5fHnUstFiAeQeP z3~LAsf;ZA9qy!vdes0h$Y431k1UwQ{HW1h)xjY$xA_+P*5I7*YiZTLu67*moa7J>u zG6J38g9OfLEItD2y^1>@b=l3TZQU%@Pc!MXn1HGU- z<$Ql^viO?mji_;meDUPlU7 grL_IWq%Dvc-*j%tJoIg}LI3~&07*qoM6N<$f&jtR)Bpeg literal 0 HcmV?d00001 diff --git a/Hyperrail/src/main/res/drawable-mdpi/ic_feedback.png b/Hyperrail/src/main/res/drawable-mdpi/ic_feedback.png new file mode 100644 index 0000000000000000000000000000000000000000..904bc585f01a2a4aa7815515c5108cd0b1ea7064 GIT binary patch literal 140 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+0wn(&ce?|mf<0XvLn>}1Cn)g!N&hqd$9_h3 zpFih00;l|tm-lGU$U3lk1>@{RtPUOl6PX2q+yw)#2|g{bif-q7G(lANfK++mh8@`r o(p~DJCITT$AxjQ8@G>xHoNIag>+tV~K;s!aUHx3vIVCg!0GqNeXaE2J literal 0 HcmV?d00001 diff --git a/Hyperrail/src/main/res/drawable-xhdpi/ic_action_github.png b/Hyperrail/src/main/res/drawable-xhdpi/ic_action_github.png new file mode 100644 index 0000000000000000000000000000000000000000..63addc7c87077e734d35bbd7083e3168036ad914 GIT binary patch literal 962 zcmV;z13mnSP)-OTWhrb ztP;rsO|2&>LP^pprC6GhVt3~FZhc#~?aqAPojHFl&Z*za%$@Un=QsD>bMAL;L;dY0`uk8J zepa=B1hL3zs_@%-NmFh=u~2lZhB^U9lUh!`19Ju2WqWzwQ&X6Te$R+@Ov#`k#;G^J-eZ zj(vd{z!#t3&7L#ir_c98SjgbS*iyydhjnd?M6mknw;CL){ksoGukmxYe)kmE9-#lm zDg^A-y*cVvB-uCam^n3UU%v}5_-+%s!*xFQ1NYQlqp|$$wi`9fGBv*+(BQLU`y04| z)1SL9xB$1SrYaC{&-4otV-?yiMzSrE1)KsVn0`gZi~BVALxX^V%mR$;wfa2ZTA3%u zS_PDFTRpU|$$4?N$R3UpQLTU?-e*>;$W`^Dt9wQq!ZpF-fWJKk9K}BD+u~M$6<`He k0akz&U|k0wldT1B8K8hNp{TNX4zU*9^H17;vx#EdO?E zp27pqrRqO4CArv)uI!NblYJtZ=cmwIxjOTXyy>EBwuE)b>;1-ugEZX$~@*T?|6QUb2ex-C>!bD+jcb!PC{x JWt~$(697B{HUt0w literal 0 HcmV?d00001 diff --git a/Hyperrail/src/main/res/drawable-xxhdpi/ic_action_github.png b/Hyperrail/src/main/res/drawable-xxhdpi/ic_action_github.png new file mode 100644 index 0000000000000000000000000000000000000000..08b2aaac4cd4b9240453870972affe9ca3aa5060 GIT binary patch literal 1495 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 literal 0 HcmV?d00001 diff --git a/Hyperrail/src/main/res/drawable-xxxhdpi/ic_feedback.png b/Hyperrail/src/main/res/drawable-xxxhdpi/ic_feedback.png new file mode 100644 index 0000000000000000000000000000000000000000..015a36904e80d2274f3436815f4e7fe6edbc0769 GIT binary patch literal 288 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhawo_o4DhE&{od&`=y$w8#`;mQL3 z9WKr#oa@fHmURwRAM>dRO zzi{p%H}>;+5zie&^*+3_nsb#U_drH=GoQ$XlWcc27u;jpd*CF?UREKG1uqJiI8`P% z)Hm5Nak?;y{@K9=zopr0Q?(r#Q*>R literal 0 HcmV?d00001 diff --git a/Hyperrail/src/main/res/layout/activity_main.xml b/Hyperrail/src/main/res/layout/activity_main.xml index 843ac7c2..3acdaf16 100644 --- a/Hyperrail/src/main/res/layout/activity_main.xml +++ b/Hyperrail/src/main/res/layout/activity_main.xml @@ -1,35 +1,35 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@+id/activity" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> - + + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/drawer" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context="be.hyperrail.android.MainActivity"> + android:layout_height="wrap_content"/> - + \ No newline at end of file diff --git a/Hyperrail/src/main/res/layout/fragment_feedback.xml b/Hyperrail/src/main/res/layout/fragment_feedback.xml new file mode 100644 index 00000000..23dc9d5c --- /dev/null +++ b/Hyperrail/src/main/res/layout/fragment_feedback.xml @@ -0,0 +1,29 @@ + + + + + + + + +